gnome-packagekit r545 - in trunk: data po src
- From: rhughes svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-packagekit r545 - in trunk: data po src
- Date: Tue, 14 Apr 2009 16:28:59 +0000 (UTC)
Author: rhughes
Date: Tue Apr 14 16:28:59 2009
New Revision: 545
URL: http://svn.gnome.org/viewvc/gnome-packagekit?rev=545&view=rev
Log:
from git
Added:
trunk/src/egg-markdown.c
trunk/src/egg-markdown.h
trunk/src/gpk-dbus-task.c
trunk/src/gpk-dbus-task.h
trunk/src/gpk-helper-chooser.c
trunk/src/gpk-helper-chooser.h
trunk/src/gpk-helper-deps-install.c
trunk/src/gpk-helper-deps-install.h
trunk/src/gpk-helper-deps-remove.c
trunk/src/gpk-helper-deps-remove.h
trunk/src/gpk-helper-media-change.c
trunk/src/gpk-helper-media-change.h
trunk/src/gpk-helper-run.c
trunk/src/gpk-helper-run.h
trunk/src/gpk-helper-untrusted.c
trunk/src/gpk-helper-untrusted.h
trunk/src/gpk-modal-dialog.c
trunk/src/gpk-modal-dialog.h
Removed:
trunk/src/gpk-client-chooser.c
trunk/src/gpk-client-chooser.h
trunk/src/gpk-client-dialog.c
trunk/src/gpk-client-dialog.h
trunk/src/gpk-client-eula.c
trunk/src/gpk-client-eula.h
trunk/src/gpk-client-run.c
trunk/src/gpk-client-run.h
trunk/src/gpk-client-signature.c
trunk/src/gpk-client-signature.h
trunk/src/gpk-client-untrusted.c
trunk/src/gpk-client-untrusted.h
trunk/src/gpk-client.c
trunk/src/gpk-client.h
Modified:
trunk/data/gnome-packagekit.schemas.in
trunk/data/gpk-application.ui
trunk/data/gpk-log.ui
trunk/data/gpk-update-viewer.desktop.in
trunk/data/gpk-update-viewer.ui
trunk/po/POTFILES.in
trunk/src/Makefile.am
trunk/src/gpk-application.c
trunk/src/gpk-auto-refresh.c
trunk/src/gpk-cell-renderer-info.c
trunk/src/gpk-check-update.c
trunk/src/gpk-common.h
trunk/src/gpk-dbus.c
trunk/src/gpk-dbus.h
trunk/src/gpk-dialog.c
trunk/src/gpk-enum.c
trunk/src/gpk-enum.h
trunk/src/gpk-error.c
trunk/src/gpk-firmware.c
trunk/src/gpk-hardware.c
trunk/src/gpk-helper-eula.c
trunk/src/gpk-helper-repo-signature.c
trunk/src/gpk-install-catalog.c
trunk/src/gpk-install-local-file.c
trunk/src/gpk-install-mime-type.c
trunk/src/gpk-install-package-name.c
trunk/src/gpk-install-provide-file.c
trunk/src/gpk-self-test.c
trunk/src/gpk-update-viewer.c
trunk/src/gpk-vendor.h
trunk/src/gpk-watch.c
trunk/src/org.freedesktop.PackageKit.xml
Modified: trunk/data/gnome-packagekit.schemas.in
==============================================================================
--- trunk/data/gnome-packagekit.schemas.in (original)
+++ trunk/data/gnome-packagekit.schemas.in Tue Apr 14 16:28:59 2009
@@ -389,8 +389,8 @@
</schema>
<schema>
- <key>/schemas/apps/gnome-packagekit/update_viewer/precache_details</key>
- <applyto>/apps/gnome-packagekit/update_viewer/precache_details</applyto>
+ <key>/schemas/apps/gnome-packagekit/update-viewer/precache_details</key>
+ <applyto>/apps/gnome-packagekit/update-viewer/precache_details</applyto>
<owner>gnome-packagekit</owner>
<type>bool</type>
<default>true</default>
@@ -401,6 +401,18 @@
</schema>
<schema>
+ <key>/schemas/apps/gnome-packagekit/update-viewer/notify_mobile_connection</key>
+ <applyto>/apps/gnome-packagekit/update-viewer/notify_mobile_connection</applyto>
+ <owner>gnome-packagekit</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Notify the user before a large update is done on a mobile broadband connection</short>
+ <long>Notify the user before a large update is done on a mobile broadband connection</long>
+ </locale>
+ </schema>
+
+ <schema>
<key>/schemas/apps/gnome-packagekit/enable_font_helper</key>
<applyto>/apps/gnome-packagekit/enable_font_helper</applyto>
<owner>gnome-packagekit</owner>
Modified: trunk/data/gpk-application.ui
==============================================================================
--- trunk/data/gpk-application.ui (original)
+++ trunk/data/gpk-application.ui Tue Apr 14 16:28:59 2009
@@ -478,64 +478,12 @@
</packing>
</child>
<child>
- <object class="GtkNotebook" id="notebook_search_cancel">
+ <object class="GtkButton" id="button_find">
+ <property name="label" translatable="yes">Fi_nd</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="show_tabs">False</property>
- <property name="show_border">False</property>
- <property name="tab_border">0</property>
- <property name="tab_hborder">0</property>
- <property name="tab_vborder">0</property>
- <child>
- <object class="GtkButton" id="button_find">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <child>
- <object class="GtkLabel" id="label_button_find">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Fi_nd</property>
- <property name="use_underline">True</property>
- </object>
- </child>
- </object>
- </child>
- <child type="tab">
- <object class="GtkLabel" id="label_find">
- <property name="visible">True</property>
- <property name="label">find</property>
- </object>
- <packing>
- <property name="tab_fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="button_cancel">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <child>
- <object class="GtkLabel" id="label_button_cancel">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Cancel</property>
- <property name="use_underline">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child type="tab">
- <object class="GtkLabel" id="label_cancel">
- <property name="visible">True</property>
- <property name="label">cancel</property>
- </object>
- <packing>
- <property name="position">1</property>
- <property name="tab_fill">False</property>
- </packing>
- </child>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
</object>
<packing>
<property name="position">1</property>
@@ -570,6 +518,15 @@
</packing>
</child>
<child>
+ <object class="GtkProgressBar" id="progressbar_progress">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkHBox" id="hbox_status">
<property name="spacing">6</property>
<child>
@@ -587,7 +544,7 @@
</object>
<packing>
<property name="expand">False</property>
- <property name="position">2</property>
+ <property name="position">3</property>
</packing>
</child>
</object>
@@ -709,6 +666,20 @@
</packing>
</child>
<child>
+ <object class="GtkButton" id="button_cancel">
+ <property name="label" translatable="yes">gtk-cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkButton" id="button_clear">
<property name="label">gtk-clear</property>
<property name="visible">True</property>
@@ -719,7 +690,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
- <property name="position">1</property>
+ <property name="position">2</property>
</packing>
</child>
<child>
@@ -733,7 +704,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
- <property name="position">2</property>
+ <property name="position">3</property>
</packing>
</child>
</object>
Modified: trunk/data/gpk-log.ui
==============================================================================
--- trunk/data/gpk-log.ui (original)
+++ trunk/data/gpk-log.ui Tue Apr 14 16:28:59 2009
@@ -6,7 +6,7 @@
<property name="border_width">6</property>
<property name="title" translatable="yes">Software Log Viewer</property>
<property name="window_position">center-on-parent</property>
- <property name="type_hint">dialog</property>
+ <property name="type_hint">normal</property>
<property name="has_separator">False</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox1">
Modified: trunk/data/gpk-update-viewer.desktop.in
==============================================================================
--- trunk/data/gpk-update-viewer.desktop.in (original)
+++ trunk/data/gpk-update-viewer.desktop.in Tue Apr 14 16:28:59 2009
@@ -1,6 +1,6 @@
[Desktop Entry]
Encoding=UTF-8
-_Name=Update System
+_Name=Software Update
_GenericName=Software Update Viewer
_Comment=Update software installed on the system
Icon=system-software-update
Modified: trunk/data/gpk-update-viewer.ui
==============================================================================
--- trunk/data/gpk-update-viewer.ui (original)
+++ trunk/data/gpk-update-viewer.ui Tue Apr 14 16:28:59 2009
@@ -1,10 +1,10 @@
<?xml version="1.0"?>
<interface>
- <!-- interface-requires gtk+ 2.16 -->
+ <requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkDialog" id="dialog_updates">
<property name="border_width">5</property>
- <property name="title" translatable="yes">Update System</property>
+ <property name="title" translatable="yes">Software Update</property>
<property name="window_position">center</property>
<property name="icon_name">software-update-available</property>
<property name="type_hint">normal</property>
@@ -148,7 +148,6 @@
<object class="GtkTreeView" id="treeview_updates">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="rules_hint">True</property>
</object>
</child>
</object>
@@ -338,22 +337,8 @@
</packing>
</child>
<child>
- <object class="GtkButton" id="button_cancel">
- <property name="label">gtk-cancel</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="button_close">
- <property name="label">gtk-close</property>
+ <object class="GtkButton" id="button_quit">
+ <property name="label">gtk-quit</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="has_focus">True</property>
@@ -363,7 +348,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
- <property name="position">2</property>
+ <property name="position">1</property>
</packing>
</child>
<child>
@@ -378,7 +363,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
- <property name="position">3</property>
+ <property name="position">2</property>
</packing>
</child>
</object>
@@ -390,5 +375,10 @@
</child>
</object>
</child>
+ <action-widgets>
+ <action-widget response="0">button_help</action-widget>
+ <action-widget response="0">button_quit</action-widget>
+ <action-widget response="0">button_install</action-widget>
+ </action-widgets>
</object>
</interface>
Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in (original)
+++ trunk/po/POTFILES.in Tue Apr 14 16:28:59 2009
@@ -22,24 +22,26 @@
data/gpk-update-icon.desktop.in
data/gpk-update-viewer.desktop.in
data/gpk-update-viewer.ui
+python/packagekit/gtkwidgets.py
src/gpk-application.c
src/gpk-application-main.c
src/gpk-backend-status.c
src/gpk-check-update.c
-src/gpk-client.c
-src/gpk-client-chooser.c
-src/gpk-client-dialog.c
-src/gpk-client-eula.c
-src/gpk-client-run.c
-src/gpk-client-signature.c
-src/gpk-client-untrusted.c
src/gpk-common.c
src/gpk-consolekit.c
+src/gpk-dbus-task.c
+src/gpk-desktop.c
src/gpk-dialog.c
src/gpk-enum.c
src/gpk-error.c
src/gpk-firmware.c
src/gpk-hardware.c
+src/gpk-helper-chooser.c
+src/gpk-helper-deps-install.c
+src/gpk-helper-deps-remove.c
+src/gpk-helper-media-change.c
+src/gpk-helper-run.c
+src/gpk-helper-untrusted.c
src/gpk-inhibit.c
src/gpk-install-catalog.c
src/gpk-install-local-file.c
@@ -47,6 +49,7 @@
src/gpk-install-package-name.c
src/gpk-install-provide-file.c
src/gpk-log.c
+src/gpk-modal-dialog.c
src/gpk-prefs.c
src/gpk-repo.c
src/gpk-service-pack.c
@@ -54,6 +57,4 @@
src/gpk-update-icon.c
src/gpk-update-viewer.c
src/gpk-watch.c
-src/gpk-desktop.c
-python/packagekit/gtkwidgets.py
Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am (original)
+++ trunk/src/Makefile.am Tue Apr 14 16:28:59 2009
@@ -73,20 +73,24 @@
gpk-vendor.h \
gpk-language.c \
gpk-language.h \
- gpk-client.c \
- gpk-client.h \
- gpk-client-dialog.c \
- gpk-client-dialog.h \
- gpk-client-eula.c \
- gpk-client-eula.h \
- gpk-client-signature.c \
- gpk-client-signature.h \
- gpk-client-untrusted.c \
- gpk-client-untrusted.h \
- gpk-client-chooser.c \
- gpk-client-chooser.h \
- gpk-client-run.c \
- gpk-client-run.h \
+ gpk-modal-dialog.c \
+ gpk-modal-dialog.h \
+ gpk-helper-repo-signature.c \
+ gpk-helper-repo-signature.h \
+ gpk-helper-eula.c \
+ gpk-helper-eula.h \
+ gpk-helper-run.c \
+ gpk-helper-run.h \
+ gpk-helper-deps-remove.c \
+ gpk-helper-deps-remove.h \
+ gpk-helper-deps-install.c \
+ gpk-helper-deps-install.h \
+ gpk-helper-untrusted.c \
+ gpk-helper-untrusted.h \
+ gpk-helper-chooser.c \
+ gpk-helper-chooser.h \
+ gpk-helper-media-change.c \
+ gpk-helper-media-change.h \
gpk-smart-icon.c \
gpk-smart-icon.h \
gpk-gnome.c \
@@ -171,6 +175,8 @@
gpk-inhibit.h \
gpk-dbus.c \
gpk-dbus.h \
+ gpk-dbus-task.c \
+ gpk-dbus-task.h \
$(shared_SOURCES) \
$(NULL)
@@ -211,10 +217,6 @@
gpk_update_viewer_SOURCES = \
gpk-update-viewer.c \
- gpk-helper-repo-signature.c \
- gpk-helper-repo-signature.h \
- gpk-helper-eula.c \
- gpk-helper-eula.h \
gpk-cell-renderer-size.c \
gpk-cell-renderer-size.h \
gpk-cell-renderer-info.c \
@@ -292,6 +294,8 @@
egg-test.c \
gpk-dbus.c \
gpk-dbus.h \
+ gpk-dbus-task.c \
+ gpk-dbus-task.h \
$(shared_SOURCES) \
$(NULL)
Added: trunk/src/egg-markdown.c
==============================================================================
--- (empty file)
+++ trunk/src/egg-markdown.c Tue Apr 14 16:28:59 2009
@@ -0,0 +1,1286 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib.h>
+
+#include "egg-debug.h"
+#include "egg-string.h"
+#include "egg-markdown.h"
+
+/*******************************************************************************
+ *
+ * This is a simple Markdown parser.
+ * It can output to Pango, HTML or plain text. The following limitations are
+ * already known, and properly deliberate:
+ *
+ * - No code section support
+ * - No ordered list support
+ * - No blockquote section support
+ * - No image support
+ * - No links or email support
+ * - No backslash escapes support
+ * - No HTML escaping support
+ * - Auto-escapes certain word patterns, like http://
+ *
+ * It does support the rest of the standard pretty well, although it's not
+ * been run against any conformance tests. The parsing is single pass, with
+ * a simple enumerated intepretor mode and a single line back-memory.
+ *
+ ******************************************************************************/
+
+static void egg_markdown_finalize (GObject *object);
+
+#define EGG_MARKDOWN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), EGG_TYPE_MARKDOWN, EggMarkdownPrivate))
+
+#define EGG_MARKDOWN_MAX_LINE_LENGTH 1024
+
+typedef enum {
+ EGG_MARKDOWN_MODE_BLANK,
+ EGG_MARKDOWN_MODE_RULE,
+ EGG_MARKDOWN_MODE_BULLETT,
+ EGG_MARKDOWN_MODE_PARA,
+ EGG_MARKDOWN_MODE_H1,
+ EGG_MARKDOWN_MODE_H2,
+ EGG_MARKDOWN_MODE_UNKNOWN
+} EggMarkdownMode;
+
+typedef struct {
+ const gchar *em_start;
+ const gchar *em_end;
+ const gchar *strong_start;
+ const gchar *strong_end;
+ const gchar *code_start;
+ const gchar *code_end;
+ const gchar *h1_start;
+ const gchar *h1_end;
+ const gchar *h2_start;
+ const gchar *h2_end;
+ const gchar *bullett_start;
+ const gchar *bullett_end;
+ const gchar *rule;
+} EggMarkdownTags;
+
+struct EggMarkdownPrivate
+{
+ EggMarkdownMode mode;
+ EggMarkdownTags tags;
+ EggMarkdownOutput output;
+ gint max_lines;
+ guint line_count;
+ gboolean smart_quoting;
+ gboolean escape;
+ gboolean autocode;
+ GString *pending;
+ GString *processed;
+};
+
+G_DEFINE_TYPE (EggMarkdown, egg_markdown, G_TYPE_OBJECT)
+
+/**
+ * egg_markdown_to_text_line_is_rule:
+ *
+ * Horizontal rules are created by placing three or more hyphens, asterisks,
+ * or underscores on a line by themselves.
+ * You may use spaces between the hyphens or asterisks.
+ **/
+static gboolean
+egg_markdown_to_text_line_is_rule (const gchar *line)
+{
+ guint i;
+ guint len;
+ guint count = 0;
+ gchar *copy = NULL;
+ gboolean ret = FALSE;
+
+ len = egg_strlen (line, EGG_MARKDOWN_MAX_LINE_LENGTH);
+ if (len == 0)
+ goto out;
+
+ /* replace non-rule chars with ~ */
+ copy = g_strdup (line);
+ g_strcanon (copy, "-*_ ", '~');
+ for (i=0; i<len; i++) {
+ if (copy[i] == '~')
+ goto out;
+ if (copy[i] != ' ')
+ count++;
+ }
+
+ /* if we matched, return true */
+ if (count >= 3)
+ ret = TRUE;
+out:
+ g_free (copy);
+ return ret;
+}
+
+/**
+ * egg_markdown_to_text_line_is_bullett:
+ **/
+static gboolean
+egg_markdown_to_text_line_is_bullett (const gchar *line)
+{
+ return (g_str_has_prefix (line, "- ") ||
+ g_str_has_prefix (line, "* ") ||
+ g_str_has_prefix (line, "+ ") ||
+ g_str_has_prefix (line, " - ") ||
+ g_str_has_prefix (line, " * ") ||
+ g_str_has_prefix (line, " + "));
+}
+
+/**
+ * egg_markdown_to_text_line_is_header1:
+ **/
+static gboolean
+egg_markdown_to_text_line_is_header1 (const gchar *line)
+{
+ return g_str_has_prefix (line, "# ");
+}
+
+/**
+ * egg_markdown_to_text_line_is_header2:
+ **/
+static gboolean
+egg_markdown_to_text_line_is_header2 (const gchar *line)
+{
+ return g_str_has_prefix (line, "## ");
+}
+
+/**
+ * egg_markdown_to_text_line_is_header1_type2:
+ **/
+static gboolean
+egg_markdown_to_text_line_is_header1_type2 (const gchar *line)
+{
+ return g_str_has_prefix (line, "===");
+}
+
+/**
+ * egg_markdown_to_text_line_is_header2_type2:
+ **/
+static gboolean
+egg_markdown_to_text_line_is_header2_type2 (const gchar *line)
+{
+ return g_str_has_prefix (line, "---");
+}
+
+#if 0
+/**
+ * egg_markdown_to_text_line_is_code:
+ **/
+static gboolean
+egg_markdown_to_text_line_is_code (const gchar *line)
+{
+ return (g_str_has_prefix (line, " ") || g_str_has_prefix (line, "\t"));
+}
+
+/**
+ * egg_markdown_to_text_line_is_blockquote:
+ **/
+static gboolean
+egg_markdown_to_text_line_is_blockquote (const gchar *line)
+{
+ return (g_str_has_prefix (line, "> "));
+}
+#endif
+
+/**
+ * egg_markdown_to_text_line_is_blank:
+ **/
+static gboolean
+egg_markdown_to_text_line_is_blank (const gchar *line)
+{
+ guint i;
+ guint len;
+ gboolean ret = FALSE;
+
+ len = egg_strlen (line, EGG_MARKDOWN_MAX_LINE_LENGTH);
+
+ /* a line with no characters is blank by definition */
+ if (len == 0) {
+ ret = TRUE;
+ goto out;
+ }
+
+ /* find if there are only space chars */
+ for (i=0; i<len; i++) {
+ if (line[i] != ' ' && line[i] != '\t')
+ goto out;
+ }
+
+ /* if we matched, return true */
+ ret = TRUE;
+out:
+ return ret;
+}
+
+/**
+ * egg_markdown_replace:
+ **/
+static gchar *
+egg_markdown_replace (const gchar *haystack, const gchar *needle, const gchar *replace)
+{
+ gchar *new;
+ gchar **split;
+
+ split = g_strsplit (haystack, needle, -1);
+ new = g_strjoinv (replace, split);
+ g_strfreev (split);
+
+ return new;
+}
+
+/**
+ * egg_markdown_strstr_spaces:
+ **/
+static gchar *
+egg_markdown_strstr_spaces (const gchar *haystack, const gchar *needle)
+{
+ gchar *found;
+ const gchar *haystack_new = haystack;
+
+retry:
+ /* don't find if surrounded by spaces */
+ found = strstr (haystack_new, needle);
+ if (found == NULL)
+ return NULL;
+
+ /* start of the string, always valid */
+ if (found == haystack)
+ return found;
+
+ /* end of the string, always valid */
+ if (*(found-1) == ' ' && *(found+1) == ' ') {
+ haystack_new = found+1;
+ goto retry;
+ }
+ return found;
+}
+
+/**
+ * egg_markdown_to_text_line_formatter:
+ **/
+static gchar *
+egg_markdown_to_text_line_formatter (const gchar *line, const gchar *formatter, const gchar *left, const gchar *right)
+{
+ guint len;
+ gchar *str1;
+ gchar *str2;
+ gchar *start = NULL;
+ gchar *middle = NULL;
+ gchar *end = NULL;
+ gchar *copy = NULL;
+ gchar *data = NULL;
+ gchar *temp;
+
+ /* needed to know for shifts */
+ len = egg_strlen (formatter, EGG_MARKDOWN_MAX_LINE_LENGTH);
+ if (len == 0)
+ goto out;
+
+ /* find sections */
+ copy = g_strdup (line);
+ str1 = egg_markdown_strstr_spaces (copy, formatter);
+ if (str1 != NULL) {
+ *str1 = '\0';
+ str2 = egg_markdown_strstr_spaces (str1+len, formatter);
+ if (str2 != NULL) {
+ *str2 = '\0';
+ middle = str1 + len;
+ start = copy;
+ end = str2 + len;
+ }
+ }
+
+ /* if we found, replace and keep looking for the same string */
+ if (start != NULL && middle != NULL && end != NULL) {
+ temp = g_strdup_printf ("%s%s%s%s%s", start, left, middle, right, end);
+ /* recursive */
+ data = egg_markdown_to_text_line_formatter (temp, formatter, left, right);
+ g_free (temp);
+ } else {
+ /* not found, keep return as-is */
+ data = g_strdup (line);
+ }
+out:
+ g_free (copy);
+ return data;
+}
+
+/**
+ * egg_markdown_to_text_line_format_sections:
+ **/
+static gchar *
+egg_markdown_to_text_line_format_sections (EggMarkdown *self, const gchar *line)
+{
+ gchar *data = g_strdup (line);
+ gchar *temp;
+
+ /* bold1 */
+ temp = data;
+ data = egg_markdown_to_text_line_formatter (temp, "**", self->priv->tags.strong_start, self->priv->tags.strong_end);
+ g_free (temp);
+
+ /* bold2 */
+ temp = data;
+ data = egg_markdown_to_text_line_formatter (temp, "__", self->priv->tags.strong_start, self->priv->tags.strong_end);
+ g_free (temp);
+
+ /* italic1 */
+ temp = data;
+ data = egg_markdown_to_text_line_formatter (temp, "*", self->priv->tags.em_start, self->priv->tags.em_end);
+ g_free (temp);
+
+ /* italic2 */
+ temp = data;
+ data = egg_markdown_to_text_line_formatter (temp, "_", self->priv->tags.em_start, self->priv->tags.em_end);
+ g_free (temp);
+
+ /* em-dash */
+ temp = data;
+ data = egg_markdown_replace (temp, " -- ", " â ");
+ g_free (temp);
+
+ /* smart quoting */
+ if (self->priv->smart_quoting) {
+ temp = data;
+ data = egg_markdown_to_text_line_formatter (temp, "\"", "â", "â");
+ g_free (temp);
+
+ temp = data;
+ data = egg_markdown_to_text_line_formatter (temp, "'", "â", "â");
+ g_free (temp);
+ }
+
+ return data;
+}
+
+/**
+ * egg_markdown_to_text_line_format:
+ **/
+static gchar *
+egg_markdown_to_text_line_format (EggMarkdown *self, const gchar *line)
+{
+ guint i;
+ gchar *text;
+ gboolean mode = FALSE;
+ gchar **codes;
+ GString *string;
+
+ /* optimise the trivial case where we don't have any code tags */
+ text = strstr (line, "`");
+ if (text == NULL) {
+ text = egg_markdown_to_text_line_format_sections (self, line);
+ goto out;
+ }
+
+ /* we want to parse the code sections without formatting */
+ codes = g_strsplit (line, "`", -1);
+ string = g_string_new ("");
+ for (i=0; codes[i] != NULL; i++) {
+ if (!mode) {
+ text = egg_markdown_to_text_line_format_sections (self, codes[i]);
+ g_string_append (string, text);
+ g_free (text);
+ mode = TRUE;
+ } else {
+ /* just append without formatting */
+ g_string_append (string, self->priv->tags.code_start);
+ g_string_append (string, codes[i]);
+ g_string_append (string, self->priv->tags.code_end);
+ mode = FALSE;
+ }
+ }
+ text = g_string_free (string, FALSE);
+out:
+ return text;
+}
+
+/**
+ * egg_markdown_add_pending:
+ **/
+static gboolean
+egg_markdown_add_pending (EggMarkdown *self, const gchar *line)
+{
+ gchar *copy;
+
+ /* would put us over the limit */
+ if (self->priv->line_count >= self->priv->max_lines)
+ return FALSE;
+
+ copy = g_strdup (line);
+
+ /* strip leading and trailing spaces */
+ g_strstrip (copy);
+
+ /* append */
+ g_string_append_printf (self->priv->pending, "%s ", copy);
+
+ g_free (copy);
+ return TRUE;
+}
+
+/**
+ * egg_markdown_add_pending_header:
+ **/
+static gboolean
+egg_markdown_add_pending_header (EggMarkdown *self, const gchar *line)
+{
+ gchar *copy;
+ gboolean ret;
+
+ /* strip trailing # */
+ copy = g_strdup (line);
+ g_strdelimit (copy, "#", ' ');
+ ret = egg_markdown_add_pending (self, copy);
+ g_free (copy);
+ return ret;
+}
+
+/**
+ * egg_markdown_word_is_code:
+ **/
+static gboolean
+egg_markdown_word_is_code (const gchar *text)
+{
+ if (g_str_has_prefix (text, "`"))
+ return FALSE;
+ if (g_str_has_suffix (text, "`"))
+ return FALSE;
+ if (g_str_has_prefix (text, "/"))
+ return TRUE;
+ if (g_str_has_prefix (text, "#"))
+ return TRUE;
+ if (g_str_has_prefix (text, "http://"))
+ return TRUE;
+ if (g_str_has_prefix (text, "https://"))
+ return TRUE;
+ if (g_str_has_prefix (text, "ftp://"))
+ return TRUE;
+ if (g_strrstr (text, ".patch") != NULL)
+ return TRUE;
+ if (g_strrstr (text, "()") != NULL)
+ return TRUE;
+ if (g_strrstr (text, "@") != NULL)
+ return TRUE;
+ return FALSE;
+}
+
+/**
+ * egg_markdown_word_auto_format_code:
+ **/
+static gchar *
+egg_markdown_word_auto_format_code (const gchar *text)
+{
+ guint i;
+ gchar *temp;
+ gchar **words;
+ gboolean ret = FALSE;
+
+ /* split sentance up with space */
+ words = g_strsplit (text, " ", -1);
+
+ /* search each word */
+ for (i=0; words[i] != NULL; i++) {
+ if (egg_markdown_word_is_code (words[i])) {
+ temp = g_strdup_printf ("`%s`", words[i]);
+ g_free (words[i]);
+ words[i] = temp;
+ ret = TRUE;
+ }
+ }
+
+ /* no replacements, so just return a copy */
+ if (!ret) {
+ temp = g_strdup (text);
+ goto out;
+ }
+
+ /* join the array back into a string */
+ temp = g_strjoinv (" ", words);
+out:
+ g_strfreev (words);
+ return temp;
+}
+
+/**
+ * egg_markdown_flush_pending:
+ **/
+static void
+egg_markdown_flush_pending (EggMarkdown *self)
+{
+ gchar *copy;
+ gchar *temp;
+
+ /* no data yet */
+ if (self->priv->mode == EGG_MARKDOWN_MODE_UNKNOWN)
+ return;
+
+ /* remove trailing spaces */
+ while (g_str_has_suffix (self->priv->pending->str, " "))
+ g_string_set_size (self->priv->pending, self->priv->pending->len - 1);
+
+ /* pango requires escaping */
+ copy = g_strdup (self->priv->pending->str);
+ if (!self->priv->escape && self->priv->output == EGG_MARKDOWN_OUTPUT_PANGO) {
+ g_strdelimit (copy, "<", '(');
+ g_strdelimit (copy, ">", ')');
+ }
+
+ /* check words for code */
+ if (self->priv->autocode &&
+ (self->priv->mode == EGG_MARKDOWN_MODE_PARA ||
+ self->priv->mode == EGG_MARKDOWN_MODE_BULLETT)) {
+ temp = egg_markdown_word_auto_format_code (copy);
+ g_free (copy);
+ copy = temp;
+ }
+
+ /* escape */
+ if (self->priv->escape) {
+ temp = g_markup_escape_text (copy, -1);
+ g_free (copy);
+ copy = temp;
+ }
+
+ /* do formatting */
+ temp = egg_markdown_to_text_line_format (self, copy);
+ if (self->priv->mode == EGG_MARKDOWN_MODE_BULLETT) {
+ g_string_append_printf (self->priv->processed, "%s%s%s\n", self->priv->tags.bullett_start, temp, self->priv->tags.bullett_end);
+ self->priv->line_count++;
+ } else if (self->priv->mode == EGG_MARKDOWN_MODE_H1) {
+ g_string_append_printf (self->priv->processed, "%s%s%s\n", self->priv->tags.h1_start, temp, self->priv->tags.h1_end);
+ } else if (self->priv->mode == EGG_MARKDOWN_MODE_H2) {
+ g_string_append_printf (self->priv->processed, "%s%s%s\n", self->priv->tags.h2_start, temp, self->priv->tags.h2_end);
+ } else if (self->priv->mode == EGG_MARKDOWN_MODE_PARA ||
+ self->priv->mode == EGG_MARKDOWN_MODE_RULE) {
+ g_string_append_printf (self->priv->processed, "%s\n", temp);
+ self->priv->line_count++;
+ }
+
+ egg_debug ("adding '%s'", temp);
+
+ /* clear */
+ g_string_truncate (self->priv->pending, 0);
+ g_free (copy);
+ g_free (temp);
+}
+
+/**
+ * egg_markdown_to_text_line_process:
+ **/
+static gboolean
+egg_markdown_to_text_line_process (EggMarkdown *self, const gchar *line)
+{
+ gboolean ret;
+
+ /* blank */
+ ret = egg_markdown_to_text_line_is_blank (line);
+ if (ret) {
+ egg_debug ("blank: '%s'", line);
+ egg_markdown_flush_pending (self);
+ /* a new line after a list is the end of list, not a gap */
+ if (self->priv->mode != EGG_MARKDOWN_MODE_BULLETT)
+ ret = egg_markdown_add_pending (self, "\n");
+ self->priv->mode = EGG_MARKDOWN_MODE_BLANK;
+ goto out;
+ }
+
+ /* header1_type2 */
+ ret = egg_markdown_to_text_line_is_header1_type2 (line);
+ if (ret) {
+ egg_debug ("header1_type2: '%s'", line);
+ if (self->priv->mode == EGG_MARKDOWN_MODE_PARA)
+ self->priv->mode = EGG_MARKDOWN_MODE_H1;
+ goto out;
+ }
+
+ /* header2_type2 */
+ ret = egg_markdown_to_text_line_is_header2_type2 (line);
+ if (ret) {
+ egg_debug ("header2_type2: '%s'", line);
+ if (self->priv->mode == EGG_MARKDOWN_MODE_PARA)
+ self->priv->mode = EGG_MARKDOWN_MODE_H2;
+ goto out;
+ }
+
+ /* rule */
+ ret = egg_markdown_to_text_line_is_rule (line);
+ if (ret) {
+ egg_debug ("rule: '%s'", line);
+ egg_markdown_flush_pending (self);
+ self->priv->mode = EGG_MARKDOWN_MODE_RULE;
+ ret = egg_markdown_add_pending (self, self->priv->tags.rule);
+ goto out;
+ }
+
+ /* bullett */
+ ret = egg_markdown_to_text_line_is_bullett (line);
+ if (ret) {
+ egg_debug ("bullett: '%s'", line);
+ egg_markdown_flush_pending (self);
+ self->priv->mode = EGG_MARKDOWN_MODE_BULLETT;
+ ret = egg_markdown_add_pending (self, &line[2]);
+ goto out;
+ }
+
+ /* header1 */
+ ret = egg_markdown_to_text_line_is_header1 (line);
+ if (ret) {
+ egg_debug ("header1: '%s'", line);
+ egg_markdown_flush_pending (self);
+ self->priv->mode = EGG_MARKDOWN_MODE_H1;
+ ret = egg_markdown_add_pending_header (self, &line[2]);
+ goto out;
+ }
+
+ /* header2 */
+ ret = egg_markdown_to_text_line_is_header2 (line);
+ if (ret) {
+ egg_debug ("header2: '%s'", line);
+ egg_markdown_flush_pending (self);
+ self->priv->mode = EGG_MARKDOWN_MODE_H2;
+ ret = egg_markdown_add_pending_header (self, &line[3]);
+ goto out;
+ }
+
+ /* paragraph */
+ if (self->priv->mode == EGG_MARKDOWN_MODE_BLANK || self->priv->mode == EGG_MARKDOWN_MODE_UNKNOWN) {
+ egg_markdown_flush_pending (self);
+ self->priv->mode = EGG_MARKDOWN_MODE_PARA;
+ }
+
+ /* add to pending */
+ egg_debug ("continue: '%s'", line);
+ ret = egg_markdown_add_pending (self, line);
+out:
+ /* if we failed to add, we don't know the mode */
+ if (!ret)
+ self->priv->mode = EGG_MARKDOWN_MODE_UNKNOWN;
+ return ret;
+}
+
+/**
+ * egg_markdown_set_output:
+ **/
+gboolean
+egg_markdown_set_output (EggMarkdown *self, EggMarkdownOutput output)
+{
+ gboolean ret = TRUE;
+ g_return_val_if_fail (EGG_IS_MARKDOWN (self), FALSE);
+
+ /* PangoMarkup */
+ if (output == EGG_MARKDOWN_OUTPUT_PANGO) {
+ self->priv->tags.em_start = "<i>";
+ self->priv->tags.em_end = "</i>";
+ self->priv->tags.strong_start = "<b>";
+ self->priv->tags.strong_end = "</b>";
+ self->priv->tags.code_start = "<tt>";
+ self->priv->tags.code_end = "</tt>";
+ self->priv->tags.h1_start = "<big>";
+ self->priv->tags.h1_end = "</big>";
+ self->priv->tags.h2_start = "<b>";
+ self->priv->tags.h2_end = "</b>";
+ self->priv->tags.bullett_start = "â ";
+ self->priv->tags.bullett_end = "";
+ self->priv->tags.rule = "ââââââââââââââââââââââ\n";
+
+ /* XHTML */
+ } else if (output == EGG_MARKDOWN_OUTPUT_HTML) {
+ self->priv->tags.em_start = "<em>";
+ self->priv->tags.em_end = "<em>";
+ self->priv->tags.strong_start = "<strong>";
+ self->priv->tags.strong_end = "</strong>";
+ self->priv->tags.code_start = "<code>";
+ self->priv->tags.code_end = "</code>";
+ self->priv->tags.h1_start = "<h1>";
+ self->priv->tags.h1_end = "</h1>";
+ self->priv->tags.h2_start = "<h2>";
+ self->priv->tags.h2_end = "</h2>";
+ self->priv->tags.bullett_start = "<li>";
+ self->priv->tags.bullett_end = "</li>";
+ self->priv->tags.rule = "<hr>";
+
+ /* plain text */
+ } else if (output == EGG_MARKDOWN_OUTPUT_TEXT) {
+ self->priv->tags.em_start = "";
+ self->priv->tags.em_end = "";
+ self->priv->tags.strong_start = "";
+ self->priv->tags.strong_end = "";
+ self->priv->tags.code_start = "";
+ self->priv->tags.code_end = "";
+ self->priv->tags.h1_start = "[";
+ self->priv->tags.h1_end = "]";
+ self->priv->tags.h2_start = "-";
+ self->priv->tags.h2_end = "-";
+ self->priv->tags.bullett_start = "* ";
+ self->priv->tags.bullett_end = "";
+ self->priv->tags.rule = " ----- \n";
+
+ /* unknown */
+ } else {
+ egg_warning ("unknown output enum");
+ ret = FALSE;
+ }
+
+ /* save if valid */
+ if (ret)
+ self->priv->output = output;
+ return ret;
+}
+
+/**
+ * egg_markdown_set_max_lines:
+ **/
+gboolean
+egg_markdown_set_max_lines (EggMarkdown *self, gint max_lines)
+{
+ g_return_val_if_fail (EGG_IS_MARKDOWN (self), FALSE);
+ self->priv->max_lines = max_lines;
+ return TRUE;
+}
+
+/**
+ * egg_markdown_set_smart_quoting:
+ **/
+gboolean
+egg_markdown_set_smart_quoting (EggMarkdown *self, gboolean smart_quoting)
+{
+ g_return_val_if_fail (EGG_IS_MARKDOWN (self), FALSE);
+ self->priv->smart_quoting = smart_quoting;
+ return TRUE;
+}
+
+/**
+ * egg_markdown_set_escape:
+ **/
+gboolean
+egg_markdown_set_escape (EggMarkdown *self, gboolean escape)
+{
+ g_return_val_if_fail (EGG_IS_MARKDOWN (self), FALSE);
+ self->priv->escape = escape;
+ return TRUE;
+}
+
+/**
+ * egg_markdown_set_autocode:
+ **/
+gboolean
+egg_markdown_set_autocode (EggMarkdown *self, gboolean autocode)
+{
+ g_return_val_if_fail (EGG_IS_MARKDOWN (self), FALSE);
+ self->priv->autocode = autocode;
+ return TRUE;
+}
+
+/**
+ * egg_markdown_parse:
+ **/
+gchar *
+egg_markdown_parse (EggMarkdown *self, const gchar *markdown)
+{
+ gchar **lines;
+ guint i;
+ guint len;
+ gchar *temp;
+ gboolean ret;
+
+ g_return_val_if_fail (EGG_IS_MARKDOWN (self), NULL);
+ g_return_val_if_fail (self->priv->output != EGG_MARKDOWN_OUTPUT_UNKNOWN, NULL);
+
+ egg_debug ("input='%s'", markdown);
+
+ /* process */
+ self->priv->mode = EGG_MARKDOWN_MODE_UNKNOWN;
+ self->priv->line_count = 0;
+ g_string_truncate (self->priv->pending, 0);
+ g_string_truncate (self->priv->processed, 0);
+ lines = g_strsplit (markdown, "\n", -1);
+ len = g_strv_length (lines);
+
+ /* process each line */
+ for (i=0; i<len; i++) {
+ ret = egg_markdown_to_text_line_process (self, lines[i]);
+ if (!ret)
+ break;
+ }
+ g_strfreev (lines);
+ egg_markdown_flush_pending (self);
+
+ /* remove trailing \n */
+ while (g_str_has_suffix (self->priv->processed->str, "\n"))
+ g_string_set_size (self->priv->processed, self->priv->processed->len - 1);
+
+ /* get a copy */
+ temp = g_strdup (self->priv->processed->str);
+ g_string_truncate (self->priv->pending, 0);
+ g_string_truncate (self->priv->processed, 0);
+
+ egg_debug ("output='%s'", temp);
+
+ return temp;
+}
+
+/**
+ * egg_markdown_class_init:
+ * @klass: The EggMarkdownClass
+ **/
+static void
+egg_markdown_class_init (EggMarkdownClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = egg_markdown_finalize;
+ g_type_class_add_private (klass, sizeof (EggMarkdownPrivate));
+}
+
+/**
+ * egg_markdown_init:
+ **/
+static void
+egg_markdown_init (EggMarkdown *self)
+{
+ self->priv = EGG_MARKDOWN_GET_PRIVATE (self);
+
+ self->priv->mode = EGG_MARKDOWN_MODE_UNKNOWN;
+ self->priv->output = EGG_MARKDOWN_OUTPUT_UNKNOWN;
+ self->priv->pending = g_string_new ("");
+ self->priv->processed = g_string_new ("");
+ self->priv->max_lines = -1;
+ self->priv->smart_quoting = FALSE;
+ self->priv->escape = FALSE;
+ self->priv->autocode = FALSE;
+}
+
+/**
+ * egg_markdown_finalize:
+ * @object: The object to finalize
+ **/
+static void
+egg_markdown_finalize (GObject *object)
+{
+ EggMarkdown *self;
+
+ g_return_if_fail (EGG_IS_MARKDOWN (object));
+
+ self = EGG_MARKDOWN (object);
+
+ g_return_if_fail (self->priv != NULL);
+ g_string_free (self->priv->pending, TRUE);
+ g_string_free (self->priv->processed, TRUE);
+
+ G_OBJECT_CLASS (egg_markdown_parent_class)->finalize (object);
+}
+
+/**
+ * egg_markdown_new:
+ *
+ * Return value: a new EggMarkdown object.
+ **/
+EggMarkdown *
+egg_markdown_new (void)
+{
+ EggMarkdown *self;
+ self = g_object_new (EGG_TYPE_MARKDOWN, NULL);
+ return EGG_MARKDOWN (self);
+}
+
+/***************************************************************************
+ *** MAKE CHECK TESTS ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+egg_markdown_test (EggTest *test)
+{
+ EggMarkdown *self;
+ gchar *text;
+ gboolean ret;
+ const gchar *markdown;
+ const gchar *markdown_expected;
+
+ if (!egg_test_start (test, "EggMarkdown"))
+ return;
+
+ /************************************************************
+ **************** line_is_rule **************
+ ************************************************************/
+ ret = egg_markdown_to_text_line_is_rule ("* * *");
+ egg_test_title_assert (test, "is rule (1)", ret);
+
+ /************************************************************/
+ ret = egg_markdown_to_text_line_is_rule ("***");
+ egg_test_title_assert (test, "is rule (2)", ret);
+
+ /************************************************************/
+ ret = egg_markdown_to_text_line_is_rule ("*****");
+ egg_test_title_assert (test, "is rule (3)", ret);
+
+ /************************************************************/
+ ret = egg_markdown_to_text_line_is_rule ("- - -");
+ egg_test_title_assert (test, "is rule (4)", ret);
+
+ /************************************************************/
+ ret = egg_markdown_to_text_line_is_rule ("---------------------------------------");
+ egg_test_title_assert (test, "is rule (5)", ret);
+
+ /************************************************************/
+ ret = egg_markdown_to_text_line_is_rule ("");
+ egg_test_title_assert (test, "is rule (blank)", !ret);
+
+ /************************************************************/
+ ret = egg_markdown_to_text_line_is_rule ("richard hughes");
+ egg_test_title_assert (test, "is rule (text)", !ret);
+
+ /************************************************************/
+ ret = egg_markdown_to_text_line_is_rule ("- richard-hughes");
+ egg_test_title_assert (test, "is rule (bullet)", !ret);
+
+ /************************************************************/
+ ret = egg_markdown_to_text_line_is_blank ("");
+ egg_test_title_assert (test, "is blank (blank)", ret);
+
+ /************************************************************/
+ ret = egg_markdown_to_text_line_is_blank (" \t ");
+ egg_test_title_assert (test, "is blank (mix)", ret);
+
+ /************************************************************/
+ ret = egg_markdown_to_text_line_is_blank ("richard hughes");
+ egg_test_title_assert (test, "is blank (name)", !ret);
+
+ /************************************************************/
+ ret = egg_markdown_to_text_line_is_blank ("ccccccccc");
+ egg_test_title_assert (test, "is blank (full)", !ret);
+
+
+ /************************************************************
+ **************** replace **************
+ ************************************************************/
+ text = egg_markdown_replace ("summary -- really -- sure!", " -- ", " â ");
+ egg_test_title (test, "replace (multiple)");
+ if (egg_strequal (text, "summary â really â sure!"))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got %s", text);
+ g_free (text);
+
+ /************************************************************
+ **************** formatter **************
+ ************************************************************/
+ text = egg_markdown_to_text_line_formatter ("**is important** text", "**", "<b>", "</b>");
+ egg_test_title (test, "formatter (left)");
+ if (egg_strequal (text, "<b>is important</b> text"))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got %s", text);
+ g_free (text);
+
+ /************************************************************/
+ text = egg_markdown_to_text_line_formatter ("this is **important**", "**", "<b>", "</b>");
+ egg_test_title (test, "formatter (right)");
+ if (egg_strequal (text, "this is <b>important</b>"))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got %s", text);
+ g_free (text);
+
+ /************************************************************/
+ text = egg_markdown_to_text_line_formatter ("**important**", "**", "<b>", "</b>");
+ egg_test_title (test, "formatter (only)");
+ if (egg_strequal (text, "<b>important</b>"))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got %s", text);
+ g_free (text);
+
+ /************************************************************/
+ text = egg_markdown_to_text_line_formatter ("***important***", "**", "<b>", "</b>");
+ egg_test_title (test, "formatter (only)");
+ if (egg_strequal (text, "<b>*important</b>*"))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got %s", text);
+ g_free (text);
+
+ /************************************************************/
+ text = egg_markdown_to_text_line_formatter ("I guess * this is * not bold", "*", "<i>", "</i>");
+ egg_test_title (test, "formatter (with spaces)");
+ if (egg_strequal (text, "I guess * this is * not bold"))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got %s", text);
+ g_free (text);
+
+ /************************************************************/
+ text = egg_markdown_to_text_line_formatter ("this **is important** text in **several** places", "**", "<b>", "</b>");
+ egg_test_title (test, "formatter (middle, multiple)");
+ if (egg_strequal (text, "this <b>is important</b> text in <b>several</b> places"))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got %s", text);
+ g_free (text);
+
+ /************************************************************/
+ text = egg_markdown_word_auto_format_code ("this is http://www.hughsie.com/with_spaces_in_url inline link");
+ egg_test_title (test, "auto formatter (url)");
+ if (egg_strequal (text, "this is `http://www.hughsie.com/with_spaces_in_url` inline link"))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got %s", text);
+ g_free (text);
+
+ /************************************************************/
+ text = egg_markdown_to_text_line_formatter ("this was \"triffic\" it was", "\"", "â", "â");
+ egg_test_title (test, "formatter (quotes)");
+ if (egg_strequal (text, "this was âtrifficâ it was"))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got %s", text);
+ g_free (text);
+
+ /************************************************************/
+ text = egg_markdown_to_text_line_formatter ("This isn't a present", "'", "â", "â");
+ egg_test_title (test, "formatter (one quote)");
+ if (egg_strequal (text, "This isn't a present"))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got %s", text);
+ g_free (text);
+
+ /************************************************************
+ **************** markdown **************
+ ************************************************************/
+ egg_test_title (test, "get EggMarkdown object");
+ self = egg_markdown_new ();
+ egg_test_assert (test, self != NULL);
+
+ /************************************************************/
+ ret = egg_markdown_set_output (self, EGG_MARKDOWN_OUTPUT_PANGO);
+ egg_test_title_assert (test, "set pango output", ret);
+
+ /************************************************************/
+ markdown = "OEMs\n"
+ "====\n"
+ " - Bullett\n";
+ markdown_expected =
+ "<big>OEMs</big>\n"
+ "â Bullett";
+ egg_test_title (test, "markdown (type2 header)");
+ text = egg_markdown_parse (self, markdown);
+ if (egg_strequal (text, markdown_expected))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got '%s', expected '%s'", text, markdown_expected);
+ g_free (text);
+
+
+ /************************************************************/
+ markdown = "this is http://www.hughsie.com/with_spaces_in_url inline link\n";
+ markdown_expected = "this is <tt>http://www.hughsie.com/with_spaces_in_url</tt> inline link";
+ egg_test_title (test, "markdown (autocode)");
+ egg_markdown_set_autocode (self, TRUE);
+ text = egg_markdown_parse (self, markdown);
+ if (egg_strequal (text, markdown_expected))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got '%s', expected '%s'", text, markdown_expected);
+ g_free (text);
+
+ /************************************************************/
+ markdown = "*** This software is currently in alpha state ***\n";
+ markdown_expected = "<b><i> This software is currently in alpha state </b></i>";
+ egg_test_title (test, "markdown some invalid header");
+ text = egg_markdown_parse (self, markdown);
+ if (egg_strequal (text, markdown_expected))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got '%s', expected '%s'", text, markdown_expected);
+ g_free (text);
+
+ /************************************************************/
+ markdown = " - This is a *very*\n"
+ " short paragraph\n"
+ " that is not usual.\n"
+ " - Another";
+ markdown_expected =
+ "â This is a <i>very</i> short paragraph that is not usual.\n"
+ "â Another";
+ egg_test_title (test, "markdown (complex1)");
+ text = egg_markdown_parse (self, markdown);
+ if (egg_strequal (text, markdown_expected))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got '%s', expected '%s'", text, markdown_expected);
+ g_free (text);
+
+ /************************************************************/
+ markdown = "* This is a *very*\n"
+ " short paragraph\n"
+ " that is not usual.\n"
+ "* This is the second\n"
+ " bullett point.\n"
+ "* And the third.\n"
+ " \n"
+ "* * *\n"
+ " \n"
+ "Paragraph one\n"
+ "isn't __very__ long at all.\n"
+ "\n"
+ "Paragraph two\n"
+ "isn't much better.";
+ markdown_expected =
+ "â This is a <i>very</i> short paragraph that is not usual.\n"
+ "â This is the second bullett point.\n"
+ "â And the third.\n"
+ "ââââââââââââââââââââââ\n"
+ "Paragraph one isn't <b>very</b> long at all.\n"
+ "Paragraph two isn't much better.";
+ egg_test_title (test, "markdown (complex1)");
+ text = egg_markdown_parse (self, markdown);
+ if (egg_strequal (text, markdown_expected))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got '%s', expected '%s'", text, markdown_expected);
+ g_free (text);
+
+ /************************************************************/
+ markdown = "This is a spec file description or\n"
+ "an **update** description in bohdi.\n"
+ "\n"
+ "* * *\n"
+ "# Big title #\n"
+ "\n"
+ "The *following* things 'were' fixed:\n"
+ "- Fix `dave`\n"
+ "* Fubar update because of \"security\"\n";
+ markdown_expected =
+ "This is a spec file description or an <b>update</b> description in bohdi.\n"
+ "ââââââââââââââââââââââ\n"
+ "<big>Big title</big>\n"
+ "The <i>following</i> things 'were' fixed:\n"
+ "â Fix <tt>dave</tt>\n"
+ "â Fubar update because of \"security\"";
+ egg_test_title (test, "markdown (complex2)");
+ text = egg_markdown_parse (self, markdown);
+ if (egg_strequal (text, markdown_expected))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got '%s', expected '%s'", text, markdown_expected);
+ g_free (text);
+
+ /************************************************************/
+ markdown = "* list seporated with spaces -\n"
+ " first item\n"
+ "\n"
+ "* second item\n"
+ "\n"
+ "* third item\n";
+ markdown_expected =
+ "â list seporated with spaces - first item\n"
+ "â second item\n"
+ "â third item";
+ egg_test_title (test, "markdown (list with spaces)");
+ text = egg_markdown_parse (self, markdown);
+ if (egg_strequal (text, markdown_expected))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got '%s', expected '%s'", text, markdown_expected);
+ g_free (text);
+
+ /************************************************************/
+ ret = egg_markdown_set_max_lines (self, 1);
+ egg_test_title_assert (test, "set max_lines", ret);
+
+ /************************************************************/
+ markdown = "* list seporated with spaces -\n"
+ " first item\n"
+ "* second item\n";
+ markdown_expected =
+ "â list seporated with spaces - first item";
+ egg_test_title (test, "markdown (one line limit)");
+ text = egg_markdown_parse (self, markdown);
+ if (egg_strequal (text, markdown_expected))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got '%s', expected '%s'", text, markdown_expected);
+ g_free (text);
+
+ /************************************************************/
+ ret = egg_markdown_set_max_lines (self, 1);
+ egg_test_title_assert (test, "set max_lines", ret);
+
+ /************************************************************/
+ markdown = "* list & spaces";
+ markdown_expected =
+ "â list & spaces";
+ egg_test_title (test, "markdown (escaping)");
+ text = egg_markdown_parse (self, markdown);
+ if (egg_strequal (text, markdown_expected))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got '%s', expected '%s'", text, markdown_expected);
+ g_free (text);
+
+ /************************************************************/
+ egg_test_title (test, "markdown (free text)");
+ text = egg_markdown_parse (self, "This isn't a present");
+ if (egg_strequal (text, "This isn't a present"))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got '%s'", text);
+ g_free (text);
+
+ /************************************************************/
+ markdown = "*Thu Mar 12 12:00:00 2009* Dan Walsh <dwalsh redhat com> - 2.0.79-1\n"
+ "- Update to upstream \n"
+ " * Netlink socket handoff patch from Adam Jackson.\n"
+ " * AVC caching of compute_create results by Eric Paris.\n"
+ "\n"
+ "*Tue Mar 10 12:00:00 2009* Dan Walsh <dwalsh redhat com> - 2.0.78-5\n"
+ "- Add patch from ajax to accellerate X SELinux \n"
+ "- Update eparis patch\n";
+ markdown_expected =
+ "<i>Thu Mar 12 12:00:00 2009</i> Dan Walsh <tt><dwalsh redhat com></tt> - 2.0.79-1\n"
+ "â Update to upstream\n"
+ "â Netlink socket handoff patch from Adam Jackson.\n"
+ "â AVC caching of compute_create results by Eric Paris.\n"
+ "<i>Tue Mar 10 12:00:00 2009</i> Dan Walsh <tt><dwalsh redhat com></tt> - 2.0.78-5\n"
+ "â Add patch from ajax to accellerate X SELinux\n"
+ "â Update eparis patch";
+ egg_test_title (test, "markdown (end of bullett)");
+ egg_markdown_set_escape (self, TRUE);
+ ret = egg_markdown_set_max_lines (self, 1024);
+ text = egg_markdown_parse (self, markdown);
+ if (egg_strequal (text, markdown_expected))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed, got '%s', expected '%s'", text, markdown_expected);
+ g_free (text);
+
+ g_object_unref (self);
+
+ egg_test_end (test);
+}
+#endif
+
Added: trunk/src/egg-markdown.h
==============================================================================
--- (empty file)
+++ trunk/src/egg-markdown.h Tue Apr 14 16:28:59 2009
@@ -0,0 +1,78 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_MARKDOWN_H
+#define __EGG_MARKDOWN_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_MARKDOWN (egg_markdown_get_type ())
+#define EGG_MARKDOWN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EGG_TYPE_MARKDOWN, EggMarkdown))
+#define EGG_MARKDOWN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EGG_TYPE_MARKDOWN, EggMarkdownClass))
+#define EGG_IS_MARKDOWN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EGG_TYPE_MARKDOWN))
+#define EGG_IS_MARKDOWN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EGG_TYPE_MARKDOWN))
+#define EGG_MARKDOWN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EGG_TYPE_MARKDOWN, EggMarkdownClass))
+#define EGG_MARKDOWN_ERROR (egg_markdown_error_quark ())
+#define EGG_MARKDOWN_TYPE_ERROR (egg_markdown_error_get_type ())
+
+typedef struct EggMarkdownPrivate EggMarkdownPrivate;
+
+typedef struct
+{
+ GObject parent;
+ EggMarkdownPrivate *priv;
+} EggMarkdown;
+
+typedef struct
+{
+ GObjectClass parent_class;
+ void (* active_changed) (EggMarkdown *self,
+ gboolean active);
+} EggMarkdownClass;
+
+typedef enum {
+ EGG_MARKDOWN_OUTPUT_TEXT,
+ EGG_MARKDOWN_OUTPUT_PANGO,
+ EGG_MARKDOWN_OUTPUT_HTML,
+ EGG_MARKDOWN_OUTPUT_UNKNOWN
+} EggMarkdownOutput;
+
+GType egg_markdown_get_type (void);
+EggMarkdown *egg_markdown_new (void);
+gboolean egg_markdown_set_output (EggMarkdown *self,
+ EggMarkdownOutput output);
+gboolean egg_markdown_set_max_lines (EggMarkdown *self,
+ gint max_lines);
+gboolean egg_markdown_set_smart_quoting (EggMarkdown *self,
+ gboolean smart_quoting);
+gboolean egg_markdown_set_escape (EggMarkdown *self,
+ gboolean escape);
+gboolean egg_markdown_set_autocode (EggMarkdown *self,
+ gboolean autocode);
+gchar *egg_markdown_parse (EggMarkdown *self,
+ const gchar *text);
+
+G_END_DECLS
+
+#endif /* __EGG_MARKDOWN_H */
+
Modified: trunk/src/gpk-application.c
==============================================================================
--- trunk/src/gpk-application.c (original)
+++ trunk/src/gpk-application.c Tue Apr 14 16:28:59 2009
@@ -35,7 +35,6 @@
#include "egg-string.h"
#include "egg-markdown.h"
-#include "gpk-client.h"
#include "gpk-common.h"
#include "gpk-gnome.h"
#include "gpk-error.h"
@@ -43,10 +42,14 @@
#include "gpk-application.h"
#include "gpk-animated-icon.h"
#include "gpk-dialog.h"
-#include "gpk-client-run.h"
-#include "gpk-client-chooser.h"
#include "gpk-cell-renderer-uri.h"
#include "gpk-desktop.h"
+#include "gpk-helper-repo-signature.h"
+#include "gpk-helper-eula.h"
+#include "gpk-helper-run.h"
+#include "gpk-helper-deps-remove.h"
+#include "gpk-helper-deps-install.h"
+#include "gpk-helper-media-change.h"
static void gpk_application_finalize (GObject *object);
@@ -82,11 +85,8 @@
GtkListStore *details_store;
EggMarkdown *markdown;
PkControl *control;
- PkClient *client_search;
- PkClient *client_action;
- PkClient *client_details;
- PkClient *client_files;
- GpkClient *gclient;
+ PkClient *client_primary;
+ PkClient *client_secondary;
PkConnection *pconnection;
PkDesktop *desktop;
gchar *package;
@@ -105,6 +105,13 @@
PkActionMode action;
GPtrArray *package_list;
GtkWidget *image_status;
+ GpkHelperRepoSignature *helper_repo_signature;
+ GpkHelperEula *helper_eula;
+ GpkHelperRun *helper_run;
+ GpkHelperDepsRemove *helper_deps_remove;
+ GpkHelperDepsInstall *helper_deps_install;
+ GpkHelperMediaChange *helper_media_change;
+ gboolean dep_check_info_only;
};
enum {
@@ -149,7 +156,8 @@
G_DEFINE_TYPE (GpkApplication, gpk_application, G_TYPE_OBJECT)
-static gboolean gpk_application_refresh_search_results (GpkApplication *application);
+static void gpk_application_categories_finished (GpkApplication *application);
+static gboolean gpk_application_perform_search (GpkApplication *application);
/**
* gpk_application_class_init:
@@ -237,29 +245,6 @@
}
/**
- * gpk_application_set_find_cancel_buttons:
- **/
-static void
-gpk_application_set_find_cancel_buttons (GpkApplication *application, gboolean find)
-{
- GtkWidget *widget;
-
- /* if we can't do it, then just make the button insensitive */
- if (!pk_bitfield_contain (application->priv->roles, PK_ROLE_ENUM_CANCEL)) {
- widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "button_cancel"));
- gtk_widget_set_sensitive (widget, FALSE);
- }
-
- /* which tab to enable? */
- widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "notebook_search_cancel"));
- if (find) {
- gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), 0);
- } else {
- gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), 1);
- }
-}
-
-/**
* gpk_application_set_text_buffer:
**/
static void
@@ -498,50 +483,30 @@
static void
gpk_application_menu_files_cb (GtkAction *action, GpkApplication *application)
{
- GPtrArray *array;
+ gboolean ret;
GError *error = NULL;
- gchar **files;
- gchar *title;
- GtkWindow *window;
- GtkWidget *dialog;
- PkPackageId *id;
+ gchar **package_ids = NULL;
g_return_if_fail (PK_IS_APPLICATION (application));
- gpk_client_set_interaction (application->priv->gclient, GPK_CLIENT_INTERACT_WARNING_CONFIRM_PROGRESS);
- files = gpk_client_get_file_list (application->priv->gclient, application->priv->package, &error);
- if (files == NULL) {
- egg_warning ("could not get file list: %s", error->message);
+ /* reset client */
+ ret = pk_client_reset (application->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("cannot reset client: %s", error->message);
g_error_free (error);
- return;
+ goto out;
}
- /* convert to pointer array */
- array = pk_strv_to_ptr_array (files);
- g_ptr_array_sort (array, (GCompareFunc) gpk_application_strcmp_indirect);
-
- /* title */
- id = pk_package_id_new_from_string (application->priv->package);
- /* TRANSLATORS: title: how many files are installed by the application */
- title = g_strdup_printf (ngettext ("%i file installed by %s",
- "%i files installed by %s",
- array->len), array->len, id->name);
-
- window = GTK_WINDOW (gtk_builder_get_object (application->priv->builder, "window_manager"));
- dialog = gtk_message_dialog_new (window, GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "%s", title);
- gpk_dialog_embed_file_list_widget (GTK_DIALOG (dialog), array);
- gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
- gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 250);
-
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (GTK_WIDGET (dialog));
-
- g_free (title);
- g_ptr_array_foreach (array, (GFunc) g_free, NULL);
- g_ptr_array_free (array, TRUE);
- g_strfreev (files);
- pk_package_id_free (id);
+ /* set correct view */
+ package_ids = pk_package_ids_from_id (application->priv->package);
+ ret = pk_client_get_files (application->priv->client_primary, package_ids, &error);
+ if (!ret) {
+ egg_warning ("cannot get file lists for %s: %s", application->priv->package, error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ g_strfreev (package_ids);
}
/**
@@ -621,14 +586,11 @@
static void
gpk_application_menu_run_cb (GtkAction *action, GpkApplication *application)
{
- gchar *exec;
- GError *error = NULL;
gchar **package_ids;
GtkTreeView *treeview;
GtkTreeModel *model;
GtkTreeIter iter;
GtkTreeSelection *selection;
- GtkWindow *window;
PkBitfield state;
gboolean ret;
gchar *package_id = NULL;
@@ -651,16 +613,7 @@
if (pk_bitfield_contain (state, GPK_STATE_INSTALLED)) {
/* run this single package id */
package_ids = pk_package_ids_from_id (package_id);
- window = GTK_WINDOW (gtk_builder_get_object (application->priv->builder, "window_manager"));
- exec = gpk_client_run_show (window, package_ids);
- if (exec != NULL) {
- ret = g_spawn_command_line_async (exec, &error);
- if (!ret) {
- egg_warning ("failed to run: %s", error->message);
- g_error_free (error);
- }
- }
- g_free (exec);
+ gpk_helper_run_show (application->priv->helper_run, package_ids);
g_strfreev (package_ids);
}
g_free (package_id);
@@ -674,74 +627,28 @@
{
GError *error = NULL;
gboolean ret;
- PkPackageList *list;
- GtkWidget *widget;
- GtkWindow *window;
- gchar **package_ids;
+ gchar **package_ids = NULL;
/* cancel any previous request */
- ret = pk_client_reset (application->priv->client_files, &error);
+ ret = pk_client_reset (application->priv->client_primary, &error);
if (!ret) {
egg_warning ("failed to cancel, and adding to queue: %s", error->message);
g_error_free (error);
- return;
+ goto out;
}
/* get the requires */
- pk_client_set_synchronous (application->priv->client_files, TRUE, NULL);
package_ids = pk_package_ids_from_id (application->priv->package);
- ret = pk_client_get_requires (application->priv->client_files, PK_FILTER_ENUM_NONE,
+ application->priv->dep_check_info_only = TRUE;
+ ret = pk_client_get_requires (application->priv->client_primary, PK_FILTER_ENUM_NONE,
package_ids, TRUE, &error);
- pk_client_set_synchronous (application->priv->client_files, FALSE, NULL);
-
if (!ret) {
egg_warning ("failed to get requires: %s", error->message);
g_error_free (error);
- return;
- }
-
- list = pk_client_get_package_list (application->priv->client_files);
- window = GTK_WINDOW (gtk_builder_get_object (application->priv->builder, "window_manager"));
- if (pk_package_list_get_size (list) == 0) {
- gpk_error_dialog_modal (window,
- /* TRANSLATORS: no packages returned */
- _("No packages"),
- /* TRANSLATORS: this package is not required by any others */
- _("No other packages require this package"), NULL);
- } else {
- gchar *name;
- gchar *title;
- gchar *message;
- guint length;
- GtkWidget *dialog;
-
- length = pk_package_list_get_size (list);
- name = gpk_dialog_package_id_name_join_locale (package_ids);
- /* TRANSLATORS: title: how many packages require this package */
- title = g_strdup_printf (ngettext ("%i package requires %s",
- "%i packages require %s",
- length), length, name);
-
- /* TRANSLATORS: show a list of packages for the package */
- message = g_strdup_printf (ngettext ("Packages listed below require %s to function correctly.",
- "Packages listed below require %s to function correctly.",
- length), name);
-
- dialog = gtk_message_dialog_new (GTK_WINDOW (widget), GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "%s", title);
- gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", message);
- gpk_dialog_embed_package_list_widget (GTK_DIALOG (dialog), list);
-
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (GTK_WIDGET (dialog));
-
- g_free (name);
- g_free (title);
- g_free (message);
+ goto out;
}
-
+out:
g_strfreev (package_ids);
- g_object_unref (list);
}
/**
@@ -752,74 +659,28 @@
{
GError *error = NULL;
gboolean ret;
- PkPackageList *list;
- GtkWidget *widget;
- GtkWindow *window;
- gchar **package_ids;
+ gchar **package_ids = NULL;
/* cancel any previous request */
- ret = pk_client_reset (application->priv->client_files, &error);
+ ret = pk_client_reset (application->priv->client_primary, &error);
if (!ret) {
egg_warning ("failed to cancel, and adding to queue: %s", error->message);
g_error_free (error);
- return;
+ goto out;
}
/* get the depends */
- pk_client_set_synchronous (application->priv->client_files, TRUE, NULL);
package_ids = pk_package_ids_from_id (application->priv->package);
- ret = pk_client_get_depends (application->priv->client_files, PK_FILTER_ENUM_NONE,
+ application->priv->dep_check_info_only = TRUE;
+ ret = pk_client_get_depends (application->priv->client_primary, PK_FILTER_ENUM_NONE,
package_ids, TRUE, &error);
- pk_client_set_synchronous (application->priv->client_files, FALSE, NULL);
-
if (!ret) {
egg_warning ("failed to get depends: %s", error->message);
g_error_free (error);
- return;
- }
-
- list = pk_client_get_package_list (application->priv->client_files);
- window = GTK_WINDOW (gtk_builder_get_object (application->priv->builder, "window_manager"));
- if (pk_package_list_get_size (list) == 0) {
- gpk_error_dialog_modal (window,
- /* TRANSLATORS: no packages returned */
- _("No packages"),
- /* TRANSLATORS: this package does not depend on any others */
- _("This package does not depends on any others"), NULL);
- } else {
- gchar *name;
- gchar *title;
- gchar *message;
- guint length;
- GtkWidget *dialog;
-
- length = pk_package_list_get_size (list);
- name = gpk_dialog_package_id_name_join_locale (package_ids);
- /* TRANSLATORS: title: show the number of other packages we depend on */
- title = g_strdup_printf (ngettext ("%i additional package is required for %s",
- "%i additional packages are required for %s",
- length), length, name);
-
- /* TRANSLATORS: message: show the list of dependant packages for this package */
- message = g_strdup_printf (ngettext ("Packages listed below are required for %s to function correctly.",
- "Packages listed below are required for %s to function correctly.",
- length), name);
-
- dialog = gtk_message_dialog_new (GTK_WINDOW (widget), GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "%s", title);
- gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", message);
- gpk_dialog_embed_package_list_widget (GTK_DIALOG (dialog), list);
-
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (GTK_WIDGET (dialog));
-
- g_free (name);
- g_free (title);
- g_free (message);
+ goto out;
}
-
+out:
g_strfreev (package_ids);
- g_object_unref (list);
}
/**
@@ -1064,11 +925,17 @@
gboolean enabled;
PkBitfield state = 0;
static guint package_cnt = 0;
+ PkRoleEnum role;
g_return_if_fail (PK_IS_APPLICATION (application));
egg_debug ("package = %s:%s:%s", pk_info_enum_to_text (obj->info), obj->id->name, obj->summary);
+ /* ignore not search data */
+ pk_client_get_role (client, &role, NULL, NULL);
+ if (role == PK_ROLE_ENUM_GET_DEPENDS || role == PK_ROLE_ENUM_GET_REQUIRES)
+ return;
+
/* ignore progress */
if (obj->info != PK_INFO_ENUM_INSTALLED && obj->info != PK_INFO_ENUM_AVAILABLE &&
obj->info != PK_INFO_ENUM_COLLECTION_INSTALLED && obj->info != PK_INFO_ENUM_COLLECTION_AVAILABLE)
@@ -1149,42 +1016,20 @@
if (code == PK_ERROR_ENUM_TRANSACTION_CANCELLED)
return;
+ /* ignore the ones we can handle */
+ if (code == PK_ERROR_ENUM_GPG_FAILURE ||
+ code == PK_ERROR_ENUM_NO_LICENSE_AGREEMENT ||
+ code == PK_ERROR_ENUM_MEDIA_CHANGE_REQUIRED) {
+ egg_debug ("error ignored as we're handling %s\n%s", pk_error_enum_to_text (code), details);
+ return;
+ }
+
window = GTK_WINDOW (gtk_builder_get_object (application->priv->builder, "window_manager"));
gpk_error_dialog_modal (window, gpk_error_enum_to_localised_text (code),
gpk_error_enum_to_localised_message (code), details);
}
/**
- * gpk_application_refresh_search_results:
- **/
-static gboolean
-gpk_application_refresh_search_results (GpkApplication *application)
-{
- gboolean ret;
- GError *error = NULL;
- PkRoleEnum role;
-
- /* get role -- do we actually need to do anything */
- pk_client_get_role (application->priv->client_search, &role, NULL, NULL);
- if (role == PK_ROLE_ENUM_UNKNOWN) {
- egg_debug ("no defined role, no not requeuing");
- return FALSE;
- }
-
- /* hide details */
- gpk_application_clear_details (application);
- gpk_application_clear_packages (application);
-
- ret = pk_client_requeue (application->priv->client_search, &error);
- if (!ret) {
- egg_warning ("failed to requeue the search: %s", error->message);
- g_error_free (error);
- return FALSE;
- }
- return TRUE;
-}
-
-/**
* gpk_application_suggest_better_search:
**/
static void
@@ -1224,31 +1069,267 @@
}
/**
+ * gpk_update_viewer_requeue:
+ **/
+static gboolean
+gpk_update_viewer_requeue (GpkApplication *application)
+{
+ gboolean ret;
+ GError *error = NULL;
+
+ /* retry new action */
+ ret = pk_client_requeue (application->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("Failed to requeue: %s", error->message);
+ g_error_free (error);
+ }
+ return ret;
+}
+
+/**
+ * gpk_application_finished_get_depends:
+ **/
+static void
+gpk_application_finished_get_depends (GpkApplication *application, PkPackageList *list)
+{
+ GtkWindow *window;
+ gchar *name = NULL;
+ gchar *title = NULL;
+ gchar *message = NULL;
+ gchar **package_ids = NULL;
+ guint length;
+ GtkWidget *dialog;
+
+ /* empty list */
+ window = GTK_WINDOW (gtk_builder_get_object (application->priv->builder, "window_manager"));
+ if (pk_package_list_get_size (list) == 0) {
+ gpk_error_dialog_modal (window,
+ /* TRANSLATORS: no packages returned */
+ _("No packages"),
+ /* TRANSLATORS: this package does not depend on any others */
+ _("This package does not depends on any others"), NULL);
+ goto out;
+ }
+
+ length = pk_package_list_get_size (list);
+ package_ids = pk_package_ids_from_id (application->priv->package);
+ name = gpk_dialog_package_id_name_join_locale (package_ids);
+ /* TRANSLATORS: title: show the number of other packages we depend on */
+ title = g_strdup_printf (ngettext ("%i additional package is required for %s",
+ "%i additional packages are required for %s",
+ length), length, name);
+
+ /* TRANSLATORS: message: show the list of dependant packages for this package */
+ message = g_strdup_printf (ngettext ("Packages listed below are required for %s to function correctly.",
+ "Packages listed below are required for %s to function correctly.",
+ length), name);
+
+ dialog = gtk_message_dialog_new (window, GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "%s", title);
+ gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", message);
+ gpk_dialog_embed_package_list_widget (GTK_DIALOG (dialog), list);
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+out:
+ g_strfreev (package_ids);
+ g_free (name);
+ g_free (title);
+ g_free (message);
+}
+
+/**
+ * gpk_application_finished_get_requires:
+ **/
+static void
+gpk_application_finished_get_requires (GpkApplication *application, PkPackageList *list)
+{
+ GtkWindow *window;
+ gchar *name = NULL;
+ gchar *title = NULL;
+ gchar *message = NULL;
+ gchar **package_ids = NULL;
+ guint length;
+ GtkWidget *dialog;
+
+ /* empty list */
+ window = GTK_WINDOW (gtk_builder_get_object (application->priv->builder, "window_manager"));
+ if (pk_package_list_get_size (list) == 0) {
+ gpk_error_dialog_modal (window,
+ /* TRANSLATORS: no packages returned */
+ _("No packages"),
+ /* TRANSLATORS: this package is not required by any others */
+ _("No other packages require this package"), NULL);
+ goto out;
+ }
+
+ length = pk_package_list_get_size (list);
+ package_ids = pk_package_ids_from_id (application->priv->package);
+ name = gpk_dialog_package_id_name_join_locale (package_ids);
+ /* TRANSLATORS: title: how many packages require this package */
+ title = g_strdup_printf (ngettext ("%i package requires %s",
+ "%i packages require %s",
+ length), length, name);
+
+ /* TRANSLATORS: show a list of packages for the package */
+ message = g_strdup_printf (ngettext ("Packages listed below require %s to function correctly.",
+ "Packages listed below require %s to function correctly.",
+ length), name);
+
+ dialog = gtk_message_dialog_new (window, GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "%s", title);
+ gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", message);
+ gpk_dialog_embed_package_list_widget (GTK_DIALOG (dialog), list);
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+out:
+ g_strfreev (package_ids);
+ g_free (name);
+ g_free (title);
+ g_free (message);
+}
+
+/**
+ * gpk_application_perform_search_idle_cb:
+ **/
+static gboolean
+gpk_application_perform_search_idle_cb (GpkApplication *application)
+{
+ gpk_application_perform_search (application);
+ return FALSE;
+}
+
+/**
+ * gpk_application_primary_requeue:
+ **/
+static gboolean
+gpk_application_primary_requeue (GpkApplication *application)
+{
+ gboolean ret;
+ GError *error = NULL;
+
+ /* retry new action */
+ ret = pk_client_requeue (application->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("Failed to requeue: %s", error->message);
+ g_error_free (error);
+ }
+ return ret;
+}
+
+/**
* gpk_application_finished_cb:
**/
static void
-gpk_application_finished_cb (PkClient *client, PkExitEnum exit, guint runtime, GpkApplication *application)
+gpk_application_finished_cb (PkClient *client, PkExitEnum exit_enum, guint runtime, GpkApplication *application)
{
GtkWidget *widget;
PkRoleEnum role;
+ PkPackageList *list;
+ gchar **package_ids;
g_return_if_fail (PK_IS_APPLICATION (application));
/* get role */
pk_client_get_role (client, &role, NULL, NULL);
+ egg_debug ("role: %s, exit: %s", pk_role_enum_to_text (role), pk_exit_enum_to_text (exit_enum));
+
+ widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "progressbar_progress"));
+ gtk_widget_hide (widget);
+
+ /* reset UI */
+ widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "treeview_groups"));
+ gtk_widget_set_sensitive (widget, TRUE);
+ widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "textview_description"));
+ gtk_widget_set_sensitive (widget, TRUE);
+ widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "treeview_detail"));
+ gtk_widget_set_sensitive (widget, TRUE);
+ widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "treeview_packages"));
+ gtk_widget_set_sensitive (widget, TRUE);
+ widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "entry_text"));
+ gtk_widget_set_sensitive (widget, TRUE);
+ widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "button_apply"));
+ gtk_widget_set_sensitive (widget, TRUE);
+ gpk_application_set_buttons_apply_clear (application);
+
+ /* if secondary, ignore */
+ if (client == application->priv->client_primary &&
+ (exit_enum == PK_EXIT_ENUM_KEY_REQUIRED ||
+ exit_enum == PK_EXIT_ENUM_EULA_REQUIRED)) {
+ egg_debug ("ignoring primary sig-required or eula");
+ return;
+ }
+
+ if (role == PK_ROLE_ENUM_GET_CATEGORIES) {
+ /* get complex group list */
+ gpk_application_categories_finished (application);
+ }
+
+ /* get deps */
+ if (role == PK_ROLE_ENUM_GET_DEPENDS &&
+ exit_enum == PK_EXIT_ENUM_SUCCESS) {
+ list = pk_client_get_package_list (application->priv->client_primary);
+ if (application->priv->dep_check_info_only)
+ gpk_application_finished_get_depends (application, list);
+ else
+ gpk_helper_deps_install_show (application->priv->helper_deps_install, application->priv->package_list, list);
+ g_object_unref (list);
+
+ }
+
+ /* get reqs */
+ if (role == PK_ROLE_ENUM_GET_REQUIRES &&
+ exit_enum == PK_EXIT_ENUM_SUCCESS) {
+ list = pk_client_get_package_list (application->priv->client_primary);
+ if (application->priv->dep_check_info_only)
+ gpk_application_finished_get_requires (application, list);
+ else
+ gpk_helper_deps_remove_show (application->priv->helper_deps_remove, application->priv->package_list, list);
+ g_object_unref (list);
+ }
+
+ /* we've just agreed to auth or a EULA */
+ if (role == PK_ROLE_ENUM_INSTALL_SIGNATURE ||
+ role == PK_ROLE_ENUM_ACCEPT_EULA) {
+ if (exit_enum == PK_EXIT_ENUM_SUCCESS)
+ gpk_update_viewer_requeue (application);
+ }
+
+ /* do we need to update the search? */
+ if (role == PK_ROLE_ENUM_INSTALL_PACKAGES ||
+ role == PK_ROLE_ENUM_REMOVE_PACKAGES) {
+ /* refresh the search as the items may have changed and the filter has not changed */
+ if (exit_enum == PK_EXIT_ENUM_SUCCESS) {
+ /* idle add in the background */
+ g_idle_add ((GSourceFunc) gpk_application_perform_search_idle_cb, application);
+
+ /* this is async */
+ package_ids = pk_package_ids_from_id (application->priv->package);
+ gpk_helper_run_show (application->priv->helper_run, package_ids);
+ g_strfreev (package_ids);
+
+ /* clear if success */
+ g_ptr_array_foreach (application->priv->package_list, (GFunc) g_free, NULL);
+ g_ptr_array_set_size (application->priv->package_list, 0);
+ application->priv->action = PK_ACTION_NONE;
+ gpk_application_set_buttons_apply_clear (application);
+ }
+ }
+
+ /* we've just agreed to auth or a EULA */
+ if (role == PK_ROLE_ENUM_INSTALL_SIGNATURE ||
+ role == PK_ROLE_ENUM_ACCEPT_EULA) {
+ if (exit_enum == PK_EXIT_ENUM_SUCCESS)
+ gpk_application_primary_requeue (application);
+ }
if (role == PK_ROLE_ENUM_SEARCH_NAME ||
role == PK_ROLE_ENUM_SEARCH_DETAILS ||
role == PK_ROLE_ENUM_SEARCH_GROUP ||
role == PK_ROLE_ENUM_GET_PACKAGES) {
-
- /* switch round buttons */
- gpk_application_set_find_cancel_buttons (application, TRUE);
-
/* were there no entries found? */
- if (exit == PK_EXIT_ENUM_SUCCESS && !application->priv->has_package) {
-
- /* try to be helpful... */
+ if (exit_enum == PK_EXIT_ENUM_SUCCESS && !application->priv->has_package) {
gpk_application_suggest_better_search (application);
}
@@ -1256,13 +1337,6 @@
widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "entry_text"));
gtk_widget_grab_focus (widget);
}
-
- /* do we need to update the search? */
- if (role == PK_ROLE_ENUM_INSTALL_PACKAGES ||
- role == PK_ROLE_ENUM_REMOVE_PACKAGES) {
- /* refresh the search as the items may have changed and the filter has not changed */
- gpk_application_refresh_search_results (application);
- }
}
/**
@@ -1275,12 +1349,11 @@
g_return_if_fail (PK_IS_APPLICATION (application));
- ret = pk_client_cancel (application->priv->client_search, NULL);
+ ret = pk_client_cancel (application->priv->client_primary, NULL);
egg_debug ("canceled? %i", ret);
/* switch buttons around */
if (ret) {
- gpk_application_set_find_cancel_buttons (application, TRUE);
application->priv->search_mode = PK_MODE_UNKNOWN;
}
}
@@ -1321,7 +1394,7 @@
egg_debug ("find %s", application->priv->search_text);
/* reset */
- ret = pk_client_reset (application->priv->client_search, &error);
+ ret = pk_client_reset (application->priv->client_primary, &error);
if (!ret) {
egg_warning ("failed to reset client: %s", error->message);
g_error_free (error);
@@ -1330,15 +1403,15 @@
/* do the search */
if (application->priv->search_type == PK_SEARCH_NAME) {
- ret = pk_client_search_name (application->priv->client_search,
+ ret = pk_client_search_name (application->priv->client_primary,
application->priv->filters_current,
application->priv->search_text, &error);
} else if (application->priv->search_type == PK_SEARCH_DETAILS) {
- ret = pk_client_search_details (application->priv->client_search,
+ ret = pk_client_search_details (application->priv->client_primary,
application->priv->filters_current,
application->priv->search_text, &error);
} else if (application->priv->search_type == PK_SEARCH_FILE) {
- ret = pk_client_search_file (application->priv->client_search,
+ ret = pk_client_search_file (application->priv->client_primary,
application->priv->filters_current,
application->priv->search_text, &error);
} else {
@@ -1374,7 +1447,7 @@
g_return_val_if_fail (application->priv->group != NULL, FALSE);
/* cancel this, we don't care about old results that are pending */
- ret = pk_client_reset (application->priv->client_search, &error);
+ ret = pk_client_reset (application->priv->client_primary, &error);
if (!ret) {
egg_warning ("failed to reset client: %s", error->message);
g_error_free (error);
@@ -1382,11 +1455,11 @@
}
if (application->priv->search_mode == PK_MODE_GROUP) {
- ret = pk_client_search_group (application->priv->client_search,
+ ret = pk_client_search_group (application->priv->client_primary,
application->priv->filters_current,
application->priv->group, &error);
} else {
- ret = pk_client_get_packages (application->priv->client_search,
+ ret = pk_client_get_packages (application->priv->client_primary,
application->priv->filters_current, &error);
}
@@ -1425,12 +1498,6 @@
} else {
egg_debug ("doing nothing");
}
- if (!ret)
- return ret;
-
- /* switch around buttons */
- gpk_application_set_find_cancel_buttons (application, FALSE);
-
return ret;
}
@@ -1484,19 +1551,13 @@
}
/* we might have visual stuff running, close them down */
- ret = pk_client_cancel (application->priv->client_search, &error);
- if (!ret) {
- egg_warning ("failed to cancel client: %s", error->message);
- g_error_free (error);
- error = NULL;
- }
- ret = pk_client_cancel (application->priv->client_details, &error);
+ ret = pk_client_cancel (application->priv->client_primary, &error);
if (!ret) {
egg_warning ("failed to cancel client: %s", error->message);
g_error_free (error);
error = NULL;
}
- ret = pk_client_cancel (application->priv->client_files, &error);
+ ret = pk_client_cancel (application->priv->client_secondary, &error);
if (!ret) {
egg_warning ("failed to cancel client: %s", error->message);
g_error_free (error);
@@ -1678,44 +1739,50 @@
gboolean ret = FALSE;
GError *error = NULL;
gchar **package_ids = NULL;
- gchar *exec;
- GtkWindow *window;
g_return_if_fail (PK_IS_APPLICATION (application));
package_ids = pk_ptr_array_to_strv (application->priv->package_list);
if (application->priv->action == PK_ACTION_INSTALL) {
- gpk_client_set_interaction (application->priv->gclient, GPK_CLIENT_INTERACT_WARNING_CONFIRM_PROGRESS);
- ret = gpk_client_install_package_ids (application->priv->gclient, package_ids, NULL);
- /* can we show the user the new application? */
- if (ret) {
- window = GTK_WINDOW (gtk_builder_get_object (application->priv->builder, "window_manager"));
- exec = gpk_client_run_show (window, package_ids);
- if (exec != NULL) {
- ret = g_spawn_command_line_async (exec, &error);
- if (!ret) {
- egg_warning ("failed to run: %s", error->message);
- g_error_free (error);
- }
- }
- g_free (exec);
+
+ /* reset client */
+ ret = pk_client_reset (application->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("failed to cancel: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* install */
+ application->priv->dep_check_info_only = FALSE;
+ ret = pk_client_get_depends (application->priv->client_primary, pk_bitfield_value (PK_FILTER_ENUM_NOT_INSTALLED), package_ids, TRUE, &error);
+ if (!ret) {
+ egg_warning ("failed to get depends: %s", error->message);
+ g_error_free (error);
+ goto out;
}
}
if (application->priv->action == PK_ACTION_REMOVE) {
- gpk_client_set_interaction (application->priv->gclient, GPK_CLIENT_INTERACT_WARNING_CONFIRM_PROGRESS);
- ret = gpk_client_remove_package_ids (application->priv->gclient, package_ids, NULL);
- }
- g_strfreev (package_ids);
+ /* reset client */
+ ret = pk_client_reset (application->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("failed to cancel: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
- /* refresh the search as the items may have changed and the filter has not changed */
- if (ret) {
- /* clear if success */
- g_ptr_array_foreach (application->priv->package_list, (GFunc) g_free, NULL);
- g_ptr_array_set_size (application->priv->package_list, 0);
- application->priv->action = PK_ACTION_NONE;
- gpk_application_set_buttons_apply_clear (application);
- gpk_application_refresh_search_results (application);
+ /* install */
+ application->priv->dep_check_info_only = FALSE;
+ ret = pk_client_get_requires (application->priv->client_primary, pk_bitfield_value (PK_FILTER_ENUM_INSTALLED), package_ids, TRUE, &error);
+ if (!ret) {
+ egg_warning ("failed to get requires: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
}
+out:
+ g_strfreev (package_ids);
+ return;
}
static void
@@ -1912,7 +1979,7 @@
gtk_widget_set_sensitive (widget, ret);
/* cancel any previous request */
- ret = pk_client_reset (application->priv->client_details, &error);
+ ret = pk_client_reset (application->priv->client_primary, &error);
if (!ret) {
egg_warning ("failed to cancel, and adding to queue: %s", error->message);
g_error_free (error);
@@ -1921,7 +1988,7 @@
/* get the details */
package_ids = pk_package_ids_from_id (application->priv->package);
- ret = pk_client_get_details (application->priv->client_details, package_ids, &error);
+ ret = pk_client_get_details (application->priv->client_primary, package_ids, &error);
g_strfreev (package_ids);
if (!ret) {
egg_warning ("failed to get details: %s", error->message);
@@ -2271,8 +2338,28 @@
static void
gpk_application_menu_refresh_cb (GtkAction *action, GpkApplication *application)
{
- gpk_client_set_interaction (application->priv->gclient, GPK_CLIENT_INTERACT_WARNING_CONFIRM_PROGRESS);
- gpk_client_refresh_cache (application->priv->gclient, NULL);
+ gboolean ret;
+ GError *error = NULL;
+
+ g_return_if_fail (PK_IS_APPLICATION (application));
+
+ /* reset client */
+ ret = pk_client_reset (application->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("cannot reset client: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* set correct view */
+ ret = pk_client_refresh_cache (application->priv->client_primary, TRUE, &error);
+ if (!ret) {
+ egg_warning ("cannot get refresh cache: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ return;
}
/**
@@ -2536,6 +2623,26 @@
g_return_if_fail (PK_IS_APPLICATION (application));
+ if (application->priv->action == PK_ACTION_INSTALL ||
+ application->priv->action == PK_ACTION_REMOVE) {
+ widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "treeview_groups"));
+ gtk_widget_set_sensitive (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "textview_description"));
+ gtk_widget_set_sensitive (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "treeview_detail"));
+ gtk_widget_set_sensitive (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "treeview_packages"));
+ gtk_widget_set_sensitive (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "entry_text"));
+ gtk_widget_set_sensitive (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "button_apply"));
+ gtk_widget_set_sensitive (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "button_clear"));
+ gtk_widget_set_sensitive (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "button_find"));
+ gtk_widget_set_sensitive (widget, FALSE);
+ }
+
widget = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "hbox_status"));
if (status == PK_STATUS_ENUM_FINISHED) {
gtk_widget_hide (widget);
@@ -2568,6 +2675,188 @@
gtk_widget_set_sensitive (widget, allow_cancel);
}
+
+/**
+ * gpk_application_repo_signature_event_cb:
+ **/
+static void
+gpk_application_repo_signature_event_cb (GpkHelperRepoSignature *helper_repo_signature, GtkResponseType type, const gchar *key_id, const gchar *package_id, GpkApplication *application)
+{
+ gboolean ret;
+ GError *error = NULL;
+
+ if (type != GTK_RESPONSE_YES) {
+ goto out;
+ }
+
+ /* reset client */
+ ret = pk_client_reset (application->priv->client_secondary, &error);
+ if (!ret) {
+ egg_warning ("cannot reset client: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* install signature */
+ ret = pk_client_install_signature (application->priv->client_secondary, PK_SIGTYPE_ENUM_GPG, key_id, package_id, &error);
+ if (!ret) {
+ egg_warning ("cannot install signature: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ return;
+}
+
+/**
+ * gpk_application_eula_event_cb:
+ **/
+static void
+gpk_application_eula_event_cb (GpkHelperEula *helper_eula, GtkResponseType type, const gchar *eula_id, GpkApplication *application)
+{
+ gboolean ret;
+ GError *error = NULL;
+
+ if (type != GTK_RESPONSE_YES) {
+ goto out;
+ }
+
+ /* reset client */
+ ret = pk_client_reset (application->priv->client_secondary, &error);
+ if (!ret) {
+ egg_warning ("cannot reset client: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* install signature */
+ ret = pk_client_accept_eula (application->priv->client_secondary, eula_id, &error);
+ if (!ret) {
+ egg_warning ("cannot accept eula: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ return;
+}
+
+/**
+ * gpk_application_deps_remove_event_cb:
+ **/
+static void
+gpk_application_deps_remove_event_cb (GpkHelperDepsRemove *helper_deps_remove, GtkResponseType type, GpkApplication *application)
+{
+ gboolean ret;
+ GError *error = NULL;
+ gchar **package_ids = NULL;
+
+ if (type != GTK_RESPONSE_YES) {
+ goto out;
+ }
+
+ /* reset client */
+ ret = pk_client_reset (application->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("cannot reset client: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* actually remove packages this time */
+ package_ids = pk_ptr_array_to_strv (application->priv->package_list);
+ ret = pk_client_remove_packages (application->priv->client_primary, package_ids, TRUE, FALSE, &error);
+ if (!ret) {
+ egg_warning ("cannot remove packages: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ g_strfreev (package_ids);
+}
+
+/**
+ * gpk_application_deps_install_event_cb:
+ **/
+static void
+gpk_application_deps_install_event_cb (GpkHelperDepsInstall *helper_deps_install, GtkResponseType type, GpkApplication *application)
+{
+ gboolean ret;
+ GError *error = NULL;
+ gchar **package_ids = NULL;
+
+ if (type != GTK_RESPONSE_YES) {
+ goto out;
+ }
+
+ /* reset client */
+ ret = pk_client_reset (application->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("cannot reset client: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* actually remove packages this time */
+ package_ids = pk_ptr_array_to_strv (application->priv->package_list);
+ ret = pk_client_install_packages (application->priv->client_primary, package_ids, &error);
+ if (!ret) {
+ egg_warning ("cannot install packages: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ g_strfreev (package_ids);
+}
+
+/**
+ * gpk_application_media_change_event_cb:
+ **/
+static void
+gpk_application_media_change_event_cb (GpkHelperMediaChange *helper_media_change, GtkResponseType type, GpkApplication *application)
+{
+ if (type != GTK_RESPONSE_YES)
+ goto out;
+
+ /* requeue */
+ gpk_update_viewer_requeue (application);
+out:
+ return;
+}
+
+/**
+ * gpk_application_eula_required_cb:
+ **/
+static void
+gpk_application_eula_required_cb (PkClient *client, const gchar *eula_id, const gchar *package_id,
+ const gchar *vendor_name, const gchar *license_agreement, GpkApplication *application)
+{
+ /* use the helper */
+ gpk_helper_eula_show (application->priv->helper_eula, eula_id, package_id, vendor_name, license_agreement);
+}
+
+/**
+ * gpk_application_media_change_required_cb:
+ **/
+static void
+gpk_application_media_change_required_cb (PkClient *client, PkMediaTypeEnum type, const gchar *media_id, const gchar *media_text, GpkApplication *application)
+{
+ /* use the helper */
+ gpk_helper_media_change_show (application->priv->helper_media_change, type, media_id, media_text);
+}
+
+/**
+ * gpk_application_repo_signature_required_cb:
+ **/
+static void
+gpk_application_repo_signature_required_cb (PkClient *client, const gchar *package_id, const gchar *repository_name,
+ const gchar *key_url, const gchar *key_userid, const gchar *key_id,
+ const gchar *key_fingerprint, const gchar *key_timestamp,
+ PkSigTypeEnum type, GpkApplication *application)
+{
+ /* use the helper */
+ gpk_helper_repo_signature_show (application->priv->helper_repo_signature, package_id, repository_name, key_url, key_userid, key_id, key_fingerprint, key_timestamp);
+}
+
/**
* gpk_application_package_row_activated_cb:
**/
@@ -2768,10 +3057,10 @@
}
/**
- * gpk_application_categories_finished_cb:
+ * gpk_application_categories_finished:
**/
static void
-gpk_application_categories_finished_cb (PkClient *client, PkExitEnum exit, guint runtime, GpkApplication *application)
+gpk_application_categories_finished (GpkApplication *application)
{
PkObjList *list;
const PkCategoryObj *obj;
@@ -2819,7 +3108,7 @@
}
/* get return values */
- list = pk_client_get_cached_objects (client);
+ list = pk_client_get_cached_objects (application->priv->client_primary);
if (list->len == 0) {
egg_warning ("no results from GetCategories");
goto out;
@@ -2859,7 +3148,7 @@
gtk_tree_view_collapse_all (treeview);
g_object_unref (list);
out:
- g_object_unref (client);
+ return;
}
/**
@@ -2869,34 +3158,30 @@
gpk_application_create_group_list_categories (GpkApplication *application)
{
GError *error = NULL;
- PkClient *client;
- gboolean ret;
+ gboolean ret = FALSE;
/* check we can do this */
if (!pk_bitfield_contain (application->priv->roles, PK_ROLE_ENUM_GET_CATEGORIES)) {
egg_warning ("backend does not support complex groups");
- return FALSE;
+ goto out;
}
- /* async */
- client = pk_client_new ();
- pk_client_set_use_buffer (client, TRUE, NULL);
- g_signal_connect (client, "finished",
- G_CALLBACK (gpk_application_categories_finished_cb), application);
- g_signal_connect (client, "finished",
- G_CALLBACK (gpk_application_finished_cb), application);
- g_signal_connect (client, "status-changed",
- G_CALLBACK (gpk_application_status_changed_cb), application);
+ /* reset client */
+ ret = pk_client_reset (application->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("cannot reset client: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
/* get categories supported */
- ret = pk_client_get_categories (client, &error);
+ ret = pk_client_get_categories (application->priv->client_primary, &error);
if (!ret) {
egg_warning ("failed to get categories: %s", error->message);
g_error_free (error);
- g_object_unref (client);
+ goto out;
}
-
- /* client will be unreff'd in finished handler */
+out:
return ret;
}
@@ -2938,6 +3223,52 @@
}
/**
+ * gpk_application_files_cb:
+ **/
+static void
+gpk_application_files_cb (PkClient *client, const gchar *package_id,
+ const gchar *filelist, GpkApplication *application)
+{
+ GPtrArray *array;
+ gchar **files;
+ gchar *title;
+ GtkWindow *window;
+ GtkWidget *dialog;
+ PkPackageId *id;
+
+ g_return_if_fail (PK_IS_APPLICATION (application));
+
+ files = g_strsplit (filelist, ";", -1);
+
+ /* convert to pointer array */
+ array = pk_strv_to_ptr_array (files);
+ g_ptr_array_sort (array, (GCompareFunc) gpk_application_strcmp_indirect);
+
+ /* title */
+ id = pk_package_id_new_from_string (application->priv->package);
+ /* TRANSLATORS: title: how many files are installed by the application */
+ title = g_strdup_printf (ngettext ("%i file installed by %s",
+ "%i files installed by %s",
+ array->len), array->len, id->name);
+
+ window = GTK_WINDOW (gtk_builder_get_object (application->priv->builder, "window_manager"));
+ dialog = gtk_message_dialog_new (window, GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "%s", title);
+ gpk_dialog_embed_file_list_widget (GTK_DIALOG (dialog), array);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 250);
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+
+ g_free (title);
+ g_ptr_array_foreach (array, (GFunc) g_free, NULL);
+ g_ptr_array_free (array, TRUE);
+ g_strfreev (files);
+ pk_package_id_free (id);
+}
+
+/**
* gpk_application_init:
**/
static void
@@ -2962,6 +3293,7 @@
application->priv->url = NULL;
application->priv->search_text = NULL;
application->priv->has_package = FALSE;
+ application->priv->dep_check_info_only = FALSE;
application->priv->details_event_id = 0;
application->priv->package_list = g_ptr_array_new ();
@@ -3008,56 +3340,40 @@
"/usr/share/PackageKit/icons");
application->priv->control = pk_control_new ();
- application->priv->gclient = gpk_client_new ();
-
- application->priv->client_search = pk_client_new ();
- g_signal_connect (application->priv->client_search, "package",
- G_CALLBACK (gpk_application_package_cb), application);
- g_signal_connect (application->priv->client_search, "error-code",
- G_CALLBACK (gpk_application_error_code_cb), application);
- g_signal_connect (application->priv->client_search, "finished",
- G_CALLBACK (gpk_application_finished_cb), application);
- g_signal_connect (application->priv->client_search, "status-changed",
- G_CALLBACK (gpk_application_status_changed_cb), application);
- g_signal_connect (application->priv->client_search, "allow-cancel",
- G_CALLBACK (gpk_application_allow_cancel_cb), application);
- application->priv->client_action = pk_client_new ();
- g_signal_connect (application->priv->client_action, "package",
+ /* this is what we use mainly */
+ application->priv->client_primary = pk_client_new ();
+ pk_client_set_use_buffer (application->priv->client_primary, TRUE, NULL);
+ g_signal_connect (application->priv->client_primary, "files",
+ G_CALLBACK (gpk_application_files_cb), application);
+ g_signal_connect (application->priv->client_primary, "package",
G_CALLBACK (gpk_application_package_cb), application);
- g_signal_connect (application->priv->client_action, "error-code",
- G_CALLBACK (gpk_application_error_code_cb), application);
- g_signal_connect (application->priv->client_action, "finished",
- G_CALLBACK (gpk_application_finished_cb), application);
- g_signal_connect (application->priv->client_action, "status-changed",
- G_CALLBACK (gpk_application_status_changed_cb), application);
- g_signal_connect (application->priv->client_action, "allow-cancel",
- G_CALLBACK (gpk_application_allow_cancel_cb), application);
- g_signal_connect (application->priv->client_action, "repo-detail",
- G_CALLBACK (pk_application_repo_detail_cb), application);
-
- application->priv->client_details = pk_client_new ();
- g_signal_connect (application->priv->client_details, "details",
+ g_signal_connect (application->priv->client_primary, "details",
G_CALLBACK (gpk_application_details_cb), application);
- g_signal_connect (application->priv->client_details, "error-code",
+ g_signal_connect (application->priv->client_primary, "error-code",
G_CALLBACK (gpk_application_error_code_cb), application);
- g_signal_connect (application->priv->client_details, "finished",
+ g_signal_connect (application->priv->client_primary, "finished",
G_CALLBACK (gpk_application_finished_cb), application);
- g_signal_connect (application->priv->client_details, "status-changed",
+ g_signal_connect (application->priv->client_primary, "status-changed",
G_CALLBACK (gpk_application_status_changed_cb), application);
- g_signal_connect (application->priv->client_details, "allow-cancel",
+ g_signal_connect (application->priv->client_primary, "allow-cancel",
G_CALLBACK (gpk_application_allow_cancel_cb), application);
-
- application->priv->client_files = pk_client_new ();
- pk_client_set_use_buffer (application->priv->client_files, TRUE, NULL);
- g_signal_connect (application->priv->client_files, "error-code",
+ g_signal_connect (application->priv->client_primary, "repo-detail",
+ G_CALLBACK (pk_application_repo_detail_cb), application);
+ g_signal_connect (application->priv->client_primary, "repo-signature-required",
+ G_CALLBACK (gpk_application_repo_signature_required_cb), application);
+ g_signal_connect (application->priv->client_primary, "eula-required",
+ G_CALLBACK (gpk_application_eula_required_cb), application);
+ g_signal_connect (application->priv->client_primary, "media-change-required",
+ G_CALLBACK (gpk_application_media_change_required_cb), application);
+
+ /* this is for auth and eula callbacks */
+ application->priv->client_secondary = pk_client_new ();
+ pk_client_set_use_buffer (application->priv->client_secondary, TRUE, NULL);
+ g_signal_connect (application->priv->client_secondary, "error-code",
G_CALLBACK (gpk_application_error_code_cb), application);
- g_signal_connect (application->priv->client_files, "finished",
+ g_signal_connect (application->priv->client_secondary, "finished",
G_CALLBACK (gpk_application_finished_cb), application);
- g_signal_connect (application->priv->client_files, "status-changed",
- G_CALLBACK (gpk_application_status_changed_cb), application);
- g_signal_connect (application->priv->client_files, "allow-cancel",
- G_CALLBACK (gpk_application_allow_cancel_cb), application);
/* get bitfield */
application->priv->roles = pk_control_get_actions (application->priv->control, NULL);
@@ -3092,9 +3408,29 @@
main_window = GTK_WIDGET (gtk_builder_get_object (application->priv->builder, "window_manager"));
- /* make GpkClient windows modal */
- gtk_widget_realize (main_window);
- gpk_client_set_parent (application->priv->gclient, GTK_WINDOW (main_window));
+ /* helpers */
+ application->priv->helper_repo_signature = gpk_helper_repo_signature_new ();
+ g_signal_connect (application->priv->helper_repo_signature, "event", G_CALLBACK (gpk_application_repo_signature_event_cb), application);
+ gpk_helper_repo_signature_set_parent (application->priv->helper_repo_signature, GTK_WINDOW (main_window));
+
+ application->priv->helper_eula = gpk_helper_eula_new ();
+ g_signal_connect (application->priv->helper_eula, "event", G_CALLBACK (gpk_application_eula_event_cb), application);
+ gpk_helper_eula_set_parent (application->priv->helper_eula, GTK_WINDOW (main_window));
+
+ application->priv->helper_run = gpk_helper_run_new ();
+ gpk_helper_run_set_parent (application->priv->helper_run, GTK_WINDOW (main_window));
+
+ application->priv->helper_deps_remove = gpk_helper_deps_remove_new ();
+ g_signal_connect (application->priv->helper_deps_remove, "event", G_CALLBACK (gpk_application_deps_remove_event_cb), application);
+ gpk_helper_deps_remove_set_parent (application->priv->helper_deps_remove, GTK_WINDOW (main_window));
+
+ application->priv->helper_deps_install = gpk_helper_deps_install_new ();
+ g_signal_connect (application->priv->helper_deps_install, "event", G_CALLBACK (gpk_application_deps_install_event_cb), application);
+ gpk_helper_deps_install_set_parent (application->priv->helper_deps_install, GTK_WINDOW (main_window));
+
+ application->priv->helper_media_change = gpk_helper_media_change_new ();
+ g_signal_connect (application->priv->helper_media_change, "event", G_CALLBACK (gpk_application_media_change_event_cb), application);
+ gpk_helper_media_change_set_parent (application->priv->helper_media_change, GTK_WINDOW (main_window));
/* Hide window first so that the dialogue resizes itself without redrawing */
gtk_widget_hide (main_window);
@@ -3335,6 +3671,8 @@
g_signal_connect (widget, "activate",
G_CALLBACK (gpk_application_find_cb), application);
+ g_signal_connect (widget, "paste-clipboard",
+ G_CALLBACK (gpk_application_find_cb), application);
g_signal_connect (widget, "icon-press",
G_CALLBACK (gpk_application_entry_text_icon_press_cb), application);
@@ -3465,7 +3803,7 @@
gpk_application_create_group_list_enum (application);
/* get repos, so we can show the full name in the software source box */
- ret = pk_client_get_repo_list (application->priv->client_action, PK_FILTER_ENUM_NONE, &error);
+ ret = pk_client_get_repo_list (application->priv->client_primary, PK_FILTER_ENUM_NONE, &error);
if (!ret) {
egg_warning ("failed to get repo list: %s", error->message);
g_error_free (error);
@@ -3540,16 +3878,19 @@
g_object_unref (application->priv->packages_store);
g_object_unref (application->priv->details_store);
g_object_unref (application->priv->control);
- g_object_unref (application->priv->client_search);
- g_object_unref (application->priv->client_action);
- g_object_unref (application->priv->client_details);
- g_object_unref (application->priv->client_files);
+ g_object_unref (application->priv->client_primary);
+ g_object_unref (application->priv->client_secondary);
g_object_unref (application->priv->pconnection);
g_object_unref (application->priv->desktop);
g_object_unref (application->priv->gconf_client);
- g_object_unref (application->priv->gclient);
g_object_unref (application->priv->markdown);
g_object_unref (application->priv->builder);
+ g_object_unref (application->priv->helper_eula);
+ g_object_unref (application->priv->helper_run);
+ g_object_unref (application->priv->helper_deps_remove);
+ g_object_unref (application->priv->helper_deps_install);
+ g_object_unref (application->priv->helper_media_change);
+ g_object_unref (application->priv->helper_repo_signature);
g_ptr_array_foreach (application->priv->package_list, (GFunc) g_free, NULL);
g_ptr_array_set_size (application->priv->package_list, 0);
Modified: trunk/src/gpk-auto-refresh.c
==============================================================================
--- trunk/src/gpk-auto-refresh.c (original)
+++ trunk/src/gpk-auto-refresh.c Tue Apr 14 16:28:59 2009
@@ -364,6 +364,17 @@
}
/**
+ * gpk_auto_refresh_maybe_get_updates_logon_cb:
+ **/
+static gboolean
+gpk_auto_refresh_maybe_get_updates_logon_cb (GpkAutoRefresh *arefresh)
+{
+ gpk_auto_refresh_maybe_get_updates (arefresh);
+ /* never repeat, even if failure */
+ return FALSE;
+}
+
+/**
* gpk_auto_refresh_change_state:
**/
static gboolean
@@ -389,7 +400,7 @@
* we need to wait until upper layers finish hooking up to the signal first. */
if (arefresh->priv->force_get_updates_login_timeout_id == 0)
arefresh->priv->force_get_updates_login_timeout_id =
- g_timeout_add_seconds (GPK_UPDATES_LOGIN_TIMEOUT, (GSourceFunc) gpk_auto_refresh_maybe_get_updates, arefresh);
+ g_timeout_add_seconds (GPK_UPDATES_LOGIN_TIMEOUT, (GSourceFunc) gpk_auto_refresh_maybe_get_updates_logon_cb, arefresh);
}
}
Modified: trunk/src/gpk-cell-renderer-info.c
==============================================================================
--- trunk/src/gpk-cell-renderer-info.c (original)
+++ trunk/src/gpk-cell-renderer-info.c Tue Apr 14 16:28:59 2009
@@ -33,7 +33,8 @@
enum {
PROP_0,
- PROP_VALUE
+ PROP_VALUE,
+ PROP_IGNORE_VALUES
};
#define GPK_CELL_RENDERER_INFO_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GPK_TYPE_CELL_RENDERER_INFO, GpkCellRendererInfoPrivate))
@@ -42,6 +43,7 @@
{
PkInfoEnum value;
const gchar *icon_name;
+ GPtrArray *ignore;
};
G_DEFINE_TYPE (GpkCellRendererInfo, gpk_cell_renderer_info, GTK_TYPE_CELL_RENDERER_PIXBUF)
@@ -64,23 +66,58 @@
}
}
+static gboolean
+gpk_cell_renderer_should_show (GpkCellRendererInfo *cru)
+{
+ guint i;
+ gboolean ret = FALSE;
+ GPtrArray *array;
+ PkInfoEnum info;
+
+ /* are we in the ignore array */
+ array = cru->priv->ignore;
+ for (i=0; i<array->len; i++) {
+ info = GPOINTER_TO_UINT (g_ptr_array_index (array, i));
+ if (info == cru->priv->value)
+ goto out;
+ }
+ ret = TRUE;
+out:
+ return ret;
+}
+
static void
gpk_cell_renderer_info_set_property (GObject *object, guint param_id,
const GValue *value, GParamSpec *pspec)
{
+ const gchar *text;
+ gchar **split;
+ gboolean ret;
+ guint i;
+ PkInfoEnum info;
GpkCellRendererInfo *cru = GPK_CELL_RENDERER_INFO (object);
switch (param_id) {
case PROP_VALUE:
cru->priv->value = g_value_get_uint (value);
- if (cru->priv->value == PK_INFO_ENUM_UNKNOWN) {
- g_object_set (cru, "visible", FALSE, NULL);
+ ret = gpk_cell_renderer_should_show (cru);
+ if (!ret) {
+ g_object_set (cru, "icon-name", "", NULL);
} else {
cru->priv->icon_name = gpk_info_status_enum_to_icon_name (cru->priv->value);
- g_object_set (cru, "visible", TRUE, NULL);
g_object_set (cru, "icon-name", cru->priv->icon_name, NULL);
}
break;
+ case PROP_IGNORE_VALUES:
+ /* split up ignore values */
+ text = g_value_get_string (value);
+ split = g_strsplit (text, ",", -1);
+ for (i=0; split[i] != NULL; i++) {
+ info = pk_info_enum_from_text (split[i]);
+ g_ptr_array_add (cru->priv->ignore, GUINT_TO_POINTER (info));
+ }
+ g_strfreev (split);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
@@ -96,6 +133,7 @@
{
GpkCellRendererInfo *cru;
cru = GPK_CELL_RENDERER_INFO (object);
+ g_ptr_array_free (cru->priv->ignore, TRUE);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -116,6 +154,9 @@
g_object_class_install_property (object_class, PROP_VALUE,
g_param_spec_uint ("value", "VALUE",
"VALUE", 0, G_MAXUINT, PK_INFO_ENUM_UNKNOWN, G_PARAM_READWRITE));
+ g_object_class_install_property (object_class, PROP_IGNORE_VALUES,
+ g_param_spec_string ("ignore-values", "IGNORE-VALUES",
+ "IGNORE-VALUES", "unknown", G_PARAM_WRITABLE));
g_type_class_add_private (object_class, sizeof (GpkCellRendererInfoPrivate));
}
@@ -129,6 +170,7 @@
cru->priv = GPK_CELL_RENDERER_INFO_GET_PRIVATE (cru);
cru->priv->value = PK_INFO_ENUM_UNKNOWN;
cru->priv->icon_name = NULL;
+ cru->priv->ignore = g_ptr_array_new ();
}
/**
Modified: trunk/src/gpk-check-update.c
==============================================================================
--- trunk/src/gpk-check-update.c (original)
+++ trunk/src/gpk-check-update.c Tue Apr 14 16:28:59 2009
@@ -43,13 +43,15 @@
#include "egg-string.h"
#include "egg-dbus-monitor.h"
+#include "gpk-consolekit.h"
#include "gpk-common.h"
#include "gpk-gnome.h"
#include "gpk-smart-icon.h"
#include "gpk-auto-refresh.h"
-#include "gpk-client.h"
#include "gpk-check-update.h"
#include "gpk-enum.h"
+#include "gpk-error.h"
+#include "gpk-helper-repo-signature.h"
static void gpk_check_update_finalize (GObject *object);
@@ -57,8 +59,6 @@
/* the maximum number of lines of data on the libnotify widget */
#define GPK_CHECK_UPDATE_MAX_NUMBER_SECURITY_ENTRIES 7
-#define ACTION_DISTRO_UPGRADE_INFO "distro-upgrade-info"
-#define ACTION_DISTRO_UPGRADE_DO_NOT_SHOW "distro-upgrade-do-not-show-available"
struct GpkCheckUpdatePrivate
{
@@ -66,15 +66,11 @@
PkConnection *pconnection;
PkTaskList *tlist;
PkControl *control;
+ GpkHelperRepoSignature *helper_repo_signature;
GpkAutoRefresh *arefresh;
- GpkClient *gclient_refresh_cache;
- GpkClient *gclient_update_system;
- GpkClient *gclient_get_updates;
- GpkClient *gclient_get_distro_upgrades;
+ PkClient *client_primary;
+ PkClient *client_secondary;
GConfClient *gconf_client;
- gboolean cache_okay;
- gboolean cache_update_in_progress;
- gboolean get_updates_in_progress;
guint number_updates_critical_last_shown;
NotifyNotification *notification_updates_available;
GPtrArray *important_updates_array;
@@ -290,7 +286,7 @@
g_return_val_if_fail (GPK_IS_CHECK_UPDATE (cupdate), FALSE);
/* debug so we can catch polling */
- egg_debug ("polling check");
+ egg_debug ("post updates check");
gpk_check_update_query_updates (cupdate, FALSE);
return FALSE;
@@ -303,18 +299,25 @@
gpk_check_update_update_system (GpkCheckUpdate *cupdate)
{
gboolean ret;
- ret = gpk_client_update_system (cupdate->priv->gclient_update_system, NULL);
+ GError *error = NULL;
- /* this isn't valid anymore */
- if (ret)
- cupdate->priv->number_updates_critical_last_shown = 0;
+ ret = pk_client_reset (cupdate->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("cannot reset client: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
- /* we failed, show the icon */
+ ret = pk_client_update_system (cupdate->priv->client_primary, &error);
if (!ret) {
+ /* we failed, show the icon */
+ egg_warning ("cannot update system: %s", error->message);
+ g_error_free (error);
gpk_smart_icon_set_icon_name (cupdate->priv->sicon, NULL);
/* we failed, so re-get the update list */
g_timeout_add_seconds (2, (GSourceFunc) gpk_check_update_get_updates_post_update_cb, cupdate);
}
+out:
return ret;
}
@@ -326,7 +329,6 @@
{
GpkCheckUpdate *cupdate = GPK_CHECK_UPDATE (data);
g_return_if_fail (GPK_IS_CHECK_UPDATE (cupdate));
- gpk_client_set_interaction (cupdate->priv->gclient_update_system, GPK_CLIENT_INTERACT_WARNING_CONFIRM_PROGRESS);
gpk_check_update_update_system (cupdate);
}
@@ -400,41 +402,64 @@
gchar **package_ids;
GpkCheckUpdate *cupdate = GPK_CHECK_UPDATE (data);
- if (egg_strequal (action, "update-all-packages")) {
- gpk_client_set_interaction (cupdate->priv->gclient_update_system, GPK_CLIENT_INTERACT_WARNING);
+ if (egg_strequal (action, "do-not-show-complete-restart")) {
+ egg_debug ("set %s to FALSE", GPK_CONF_NOTIFY_UPDATE_COMPLETE_RESTART);
+ gconf_client_set_bool (cupdate->priv->gconf_client, GPK_CONF_NOTIFY_UPDATE_COMPLETE_RESTART, FALSE, NULL);
+ } else if (egg_strequal (action, "do-not-show-complete")) {
+ egg_debug ("set %s to FALSE", GPK_CONF_NOTIFY_UPDATE_COMPLETE);
+ gconf_client_set_bool (cupdate->priv->gconf_client, GPK_CONF_NOTIFY_UPDATE_COMPLETE, FALSE, NULL);
+ } else if (egg_strequal (action, "do-not-show-update-started")) {
+ egg_debug ("set %s to FALSE", GPK_CONF_NOTIFY_UPDATE_STARTED);
+ gconf_client_set_bool (cupdate->priv->gconf_client, GPK_CONF_NOTIFY_UPDATE_STARTED, FALSE, NULL);
+ } else if (egg_strequal (action, "do-not-show-notify-critical")) {
+ egg_debug ("set %s to FALSE", GPK_CONF_NOTIFY_CRITICAL);
+ gconf_client_set_bool (cupdate->priv->gconf_client, GPK_CONF_NOTIFY_CRITICAL, FALSE, NULL);
+ } else if (egg_strequal (action, "do-not-show-update-not-battery")) {
+ egg_debug ("set %s to FALSE", GPK_CONF_NOTIFY_UPDATE_NOT_BATTERY);
+ gconf_client_set_bool (cupdate->priv->gconf_client, GPK_CONF_NOTIFY_UPDATE_NOT_BATTERY, FALSE, NULL);
+ } else if (egg_strequal (action, "distro-upgrade-do-not-show-available")) {
+ egg_debug ("set %s to FALSE", GPK_CONF_NOTIFY_DISTRO_UPGRADES);
+ gconf_client_set_bool (cupdate->priv->gconf_client, GPK_CONF_NOTIFY_DISTRO_UPGRADES, FALSE, NULL);
+// } else if (egg_strequal (action, "show-error-details")) {
+// /* TRANSLATORS: detailed text about the error */
+// gpk_error_dialog (_("Error details"), _("Package Manager error details"), cupdate->priv->error_details);
+ } else if (egg_strequal (action, "cancel")) {
+ /* try to cancel */
+ ret = pk_client_cancel (cupdate->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("failed to cancel client: %s", error->message);
+ g_error_free (error);
+ }
+ } else if (egg_strequal (action, "update-all-packages")) {
gpk_check_update_update_system (cupdate);
} else if (egg_strequal (action, "update-just-security")) {
+ ret = pk_client_reset (cupdate->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("cannot reset client: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
/* just update the important updates */
package_ids = pk_package_ids_from_array (cupdate->priv->important_updates_array);
- gpk_client_set_interaction (cupdate->priv->gclient_update_system, GPK_CLIENT_INTERACT_WARNING);
- ret = gpk_client_update_packages (cupdate->priv->gclient_update_system, package_ids, &error);
+ ret = pk_client_update_packages (cupdate->priv->client_primary, package_ids, &error);
if (!ret) {
egg_warning ("Individual updates failed: %s", error->message);
g_error_free (error);
}
- /* this isn't valid anymore */
- if (ret)
- cupdate->priv->number_updates_critical_last_shown = 0;
g_strfreev (package_ids);
- } else if (egg_strequal (action, "do-not-show-notify-critical")) {
- egg_debug ("set %s to FALSE", GPK_CONF_NOTIFY_CRITICAL);
- gconf_client_set_bool (cupdate->priv->gconf_client, GPK_CONF_NOTIFY_CRITICAL, FALSE, NULL);
- } else if (egg_strequal (action, "do-not-show-update-not-battery")) {
- egg_debug ("set %s to FALSE", GPK_CONF_NOTIFY_UPDATE_NOT_BATTERY);
- gconf_client_set_bool (cupdate->priv->gconf_client, GPK_CONF_NOTIFY_UPDATE_NOT_BATTERY, FALSE, NULL);
- } else if (egg_strequal (action, ACTION_DISTRO_UPGRADE_INFO)) {
+ } else if (egg_strequal (action, "distro-upgrade-info")) {
ret = g_spawn_command_line_async ("/usr/share/PackageKit/pk-upgrade-distro.sh", NULL);
if (!ret) {
egg_warning ("Failure launching pk-upgrade-distro.sh");
}
- } else if (egg_strequal (action, ACTION_DISTRO_UPGRADE_DO_NOT_SHOW)) {
- egg_debug ("set %s to FALSE", GPK_CONF_NOTIFY_DISTRO_UPGRADES);
- gconf_client_set_bool (cupdate->priv->gconf_client, GPK_CONF_NOTIFY_DISTRO_UPGRADES, FALSE, NULL);
} else {
egg_warning ("unknown action id: %s", action);
}
+out:
+ return;
}
/**
@@ -672,6 +697,93 @@
static gboolean
gpk_check_update_query_updates (GpkCheckUpdate *cupdate, gboolean policy_action)
{
+ gboolean ret = FALSE;
+ GError *error = NULL;
+
+ g_return_val_if_fail (GPK_IS_CHECK_UPDATE (cupdate), FALSE);
+
+ /* No point if we are already updating */
+ if (pk_task_list_contains_role (cupdate->priv->tlist, PK_ROLE_ENUM_UPDATE_PACKAGES) ||
+ pk_task_list_contains_role (cupdate->priv->tlist, PK_ROLE_ENUM_UPDATE_SYSTEM)) {
+ egg_debug ("Not checking for updates as already in progress");
+ goto out;
+ }
+
+ ret = pk_client_reset (cupdate->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("cannot reset client: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ ret = pk_client_get_updates (cupdate->priv->client_primary, PK_FILTER_ENUM_NONE, &error);
+ if (!ret) {
+ egg_warning ("cannot get updates: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ return ret;
+}
+
+/**
+ * gpk_check_update_notify_doing_updates:
+ **/
+static void
+gpk_check_update_notify_doing_updates (GpkCheckUpdate *cupdate)
+{
+ gboolean ret;
+ GError *error = NULL;
+ NotifyNotification *notification;
+
+ /* in GConf? */
+ ret = gconf_client_get_bool (cupdate->priv->gconf_client, GPK_CONF_NOTIFY_CRITICAL, NULL);
+ if (!ret)
+ goto out;
+
+ /* TRANSLATORS: title: notification when we scheduled an automatic update */
+ notification = notify_notification_new (_("Updates are being installed"),
+ /* TRANSLATORS: tell the user why the hard disk is grinding... */
+ _("Updates are being automatically installed on your computer"),
+ "software-update-urgent", NULL);
+ notify_notification_set_timeout (notification, 15000);
+ notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
+ /* TRANSLATORS: button: cancel the update system */
+ notify_notification_add_action (notification, "cancel",
+ _("Cancel update"), gpk_check_update_libnotify_cb, cupdate, NULL);
+ /* TRANSLATORS: button: don't show this again */
+ notify_notification_add_action (notification, "do-not-show-update-started",
+ _("Do not show this again"), gpk_check_update_libnotify_cb, cupdate, NULL);
+ ret = notify_notification_show (notification, &error);
+ if (!ret) {
+ egg_warning ("error: %s", error->message);
+ g_error_free (error);
+ }
+out:
+ return;
+}
+
+/**
+ * gpk_check_update_policy_all_idle_cb:
+ **/
+static gboolean
+gpk_check_update_policy_all_idle_cb (GpkCheckUpdate *cupdate)
+{
+ gboolean ret;
+ ret = gpk_check_update_update_system (cupdate);
+ if (ret)
+ gpk_check_update_notify_doing_updates (cupdate);
+
+ /* never repeat */
+ return FALSE;
+}
+
+/**
+ * gpk_check_update_process_updates:
+ **/
+static gboolean
+gpk_check_update_process_updates (GpkCheckUpdate *cupdate, PkPackageList *list, gboolean policy_action)
+{
const PkPackageObj *obj;
guint length;
guint i;
@@ -685,35 +797,10 @@
const gchar *icon;
gchar *package_id;
gchar **package_ids;
- PkPackageList *list;
GError *error = NULL;
g_return_val_if_fail (GPK_IS_CHECK_UPDATE (cupdate), FALSE);
- /* are we already called */
- if (cupdate->priv->get_updates_in_progress) {
- egg_debug ("GetUpdate already in progress");
- return FALSE;
- }
-
- /* No point if we are already updating */
- if (pk_task_list_contains_role (cupdate->priv->tlist, PK_ROLE_ENUM_UPDATE_PACKAGES) ||
- pk_task_list_contains_role (cupdate->priv->tlist, PK_ROLE_ENUM_UPDATE_SYSTEM)) {
- egg_debug ("Not checking for updates as already in progress");
- return FALSE;
- }
-
- /* get updates */
- gpk_client_set_interaction (cupdate->priv->gclient_get_updates, GPK_CLIENT_INTERACT_NEVER);
- cupdate->priv->get_updates_in_progress = TRUE;
- list = gpk_client_get_updates (cupdate->priv->gclient_get_updates, &error);
- cupdate->priv->get_updates_in_progress = FALSE;
- if (list == NULL) {
- egg_warning ("failed to get updates: %s", error->message);
- g_error_free (error);
- return FALSE;
- }
-
/* sort by name */
pk_package_list_sort (list);
@@ -776,11 +863,8 @@
/* TRANSLATORS: tooltip: how many updates are waiting to be applied */
g_string_append_printf (status_tooltip, ngettext ("There is %d update available",
"There are %d updates available", length), length);
-#if GTK_CHECK_VERSION(2,15,0)
gtk_status_icon_set_tooltip_text (GTK_STATUS_ICON (cupdate->priv->sicon), status_tooltip->str);
-#else
- gtk_status_icon_set_tooltip (GTK_STATUS_ICON (cupdate->priv->sicon), status_tooltip->str);
-#endif
+
/* if we are just refreshing after a failed update, don't try to do the actions */
if (!policy_action) {
egg_debug ("skipping actions");
@@ -822,17 +906,22 @@
goto out;
}
+ ret = pk_client_reset (cupdate->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("cannot reset client: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
/* convert */
package_ids = pk_package_ids_from_array (security_array);
- gpk_client_set_interaction (cupdate->priv->gclient_update_system, GPK_CLIENT_INTERACT_WARNING);
- ret = gpk_client_update_packages (cupdate->priv->gclient_update_system, package_ids, &error);
+ ret = pk_client_update_packages (cupdate->priv->client_primary, package_ids, &error);
if (!ret) {
egg_warning ("Individual updates failed: %s", error->message);
g_error_free (error);
+ } else {
+ gpk_check_update_notify_doing_updates (cupdate);
}
- /* this isn't valid anymore */
- if (ret)
- cupdate->priv->number_updates_critical_last_shown = 0;
g_strfreev (package_ids);
goto out;
}
@@ -840,15 +929,13 @@
/* just do everything */
if (update == GPK_UPDATE_ENUM_ALL) {
egg_debug ("we should do the update automatically!");
- gpk_client_set_interaction (cupdate->priv->gclient_update_system, GPK_CLIENT_INTERACT_WARNING);
- g_idle_add ((GSourceFunc) gpk_check_update_update_system, cupdate);
+ g_idle_add ((GSourceFunc) gpk_check_update_policy_all_idle_cb, cupdate);
goto out;
}
/* shouldn't happen */
egg_warning ("unknown update mode");
out:
- g_object_unref (list);
g_string_free (status_security, TRUE);
g_string_free (status_tooltip, TRUE);
g_ptr_array_foreach (security_array, (GFunc) g_free, NULL);
@@ -862,6 +949,7 @@
static gboolean
gpk_check_update_query_updates_idle_cb (GpkCheckUpdate *cupdate)
{
+ egg_warning ("idle cb");
gpk_check_update_query_updates (cupdate, TRUE);
return FALSE;
}
@@ -876,13 +964,7 @@
/* now try to get newest update list */
egg_warning ("updates changed");
-
- /* ignore our own updates */
- if (!cupdate->priv->get_updates_in_progress) {
- g_idle_add ((GSourceFunc) gpk_check_update_query_updates_idle_cb, cupdate);
- egg_warning ("not own updates");
- } else
- egg_warning ("own updates");
+ g_idle_add ((GSourceFunc) gpk_check_update_query_updates_idle_cb, cupdate);
}
/**
@@ -930,37 +1012,25 @@
gpk_check_update_auto_refresh_cache_cb (GpkAutoRefresh *arefresh, GpkCheckUpdate *cupdate)
{
gboolean ret;
- g_return_if_fail (GPK_IS_CHECK_UPDATE (cupdate));
-
- /* got a cache, no need to poll */
- if (cupdate->priv->cache_okay)
- return;
-
- /* already in progress, but not yet certified okay */
- if (cupdate->priv->cache_update_in_progress)
- return;
+ GError *error = NULL;
- cupdate->priv->cache_update_in_progress = TRUE;
- cupdate->priv->cache_okay = TRUE;
+ g_return_if_fail (GPK_IS_CHECK_UPDATE (cupdate));
- /* use the gnome helper to refresh the cache */
- gpk_client_set_interaction (cupdate->priv->gclient_refresh_cache, GPK_CLIENT_INTERACT_NEVER);
- ret = gpk_client_refresh_cache (cupdate->priv->gclient_refresh_cache, NULL);
+ ret = pk_client_reset (cupdate->priv->client_primary, &error);
if (!ret) {
- /* we failed to get the cache */
- egg_warning ("failed to refresh cache");
-
- /* try again in a few minutes */
- cupdate->priv->cache_okay = FALSE;
- } else {
- /* stop the polling */
- cupdate->priv->cache_okay = TRUE;
+ egg_warning ("cannot reset client: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
- /* now try to get updates */
- egg_debug ("get updates");
- gpk_check_update_query_updates (cupdate, TRUE);
+ ret = pk_client_refresh_cache (cupdate->priv->client_primary, TRUE, &error);
+ if (!ret) {
+ egg_warning ("cannot refresh cache: %s", error->message);
+ g_error_free (error);
+ goto out;
}
- cupdate->priv->cache_update_in_progress = FALSE;
+out:
+ return;
}
/**
@@ -972,6 +1042,7 @@
g_return_if_fail (GPK_IS_CHECK_UPDATE (cupdate));
/* show the icon at login time */
+ egg_debug ("login cb");
g_idle_add ((GSourceFunc) gpk_check_update_query_updates_idle_cb, cupdate);
}
@@ -981,9 +1052,34 @@
static void
gpk_check_update_auto_get_upgrades_cb (GpkAutoRefresh *arefresh, GpkCheckUpdate *cupdate)
{
+ gboolean ret;
GError *error = NULL;
- const GPtrArray *array;
+
+ ret = pk_client_reset (cupdate->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("cannot reset client: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ ret = pk_client_get_distro_upgrades (cupdate->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("cannot get updates: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ return;
+}
+
+/**
+ * gpk_check_update_process_distro_upgrades:
+ **/
+static void
+gpk_check_update_process_distro_upgrades (GpkCheckUpdate *cupdate, PkObjList *array)
+{
gboolean ret;
+ GError *error = NULL;
guint i;
PkDistroUpgradeObj *obj;
const gchar *title;
@@ -991,15 +1087,6 @@
GString *string = NULL;
g_return_if_fail (GPK_IS_CHECK_UPDATE (cupdate));
- /* get updates */
- gpk_client_set_interaction (cupdate->priv->gclient_get_distro_upgrades, GPK_CLIENT_INTERACT_NEVER);
- array = gpk_client_get_distro_upgrades (cupdate->priv->gclient_get_distro_upgrades, &error);
- if (array == NULL) {
- egg_warning ("failed to get upgrades: %s", error->message);
- g_error_free (error);
- goto out;
- }
-
/* any updates? */
if (array->len == 0) {
egg_debug ("no upgrades");
@@ -1016,7 +1103,7 @@
/* find the upgrade string */
string = g_string_new ("");
for (i=0; i < array->len; i++) {
- obj = (PkDistroUpgradeObj *) g_ptr_array_index (array, i);
+ obj = (PkDistroUpgradeObj *) pk_obj_list_index (array, i);
g_string_append_printf (string, "%s (%s)\n", obj->name, pk_distro_upgrade_enum_to_text (obj->state));
}
if (string->len != 0)
@@ -1031,10 +1118,10 @@
}
notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER);
notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL);
- notify_notification_add_action (notification, ACTION_DISTRO_UPGRADE_INFO,
+ notify_notification_add_action (notification, "distro-upgrade-info",
/* TRANSLATORS: provides more information about the upgrade */
_("More information"), gpk_check_update_libnotify_cb, cupdate, NULL);
- notify_notification_add_action (notification, ACTION_DISTRO_UPGRADE_DO_NOT_SHOW,
+ notify_notification_add_action (notification, "distro-upgrade-do-not-show-available",
/* TRANSLATORS: hides forever */
_("Do not show this again"), gpk_check_update_libnotify_cb, cupdate, NULL);
ret = notify_notification_show (notification, &error);
@@ -1074,6 +1161,247 @@
}
/**
+ * gpk_check_update_error_code_cb:
+ **/
+static void
+gpk_check_update_error_code_cb (PkClient *client, PkErrorCodeEnum code, const gchar *details, GpkCheckUpdate *cupdate)
+{
+ /* ignore some errors */
+ if (code == PK_ERROR_ENUM_PROCESS_KILL ||
+ code == PK_ERROR_ENUM_TRANSACTION_CANCELLED) {
+ egg_debug ("error ignored %s\n%s", pk_error_enum_to_text (code), details);
+ return;
+ }
+
+ /* ignore the ones we can handle */
+ if (code == PK_ERROR_ENUM_GPG_FAILURE) {
+ egg_debug ("error ignored as we're handling %s\n%s", pk_error_enum_to_text (code), details);
+ return;
+ }
+
+ /* not modal as we are a status icon */
+ gpk_error_dialog (gpk_error_enum_to_localised_text (code),
+ gpk_error_enum_to_localised_message (code), details);
+}
+
+/**
+ * gpk_check_update_repo_signature_event_cb:
+ **/
+static void
+gpk_check_update_repo_signature_event_cb (GpkHelperRepoSignature *helper_repo_signature, GtkResponseType type, const gchar *key_id, const gchar *package_id, GpkCheckUpdate *cupdate)
+{
+ gboolean ret;
+ GError *error = NULL;
+
+ if (type != GTK_RESPONSE_YES) {
+ goto out;
+ }
+
+ /* reset client */
+ ret = pk_client_reset (cupdate->priv->client_secondary, &error);
+ if (!ret) {
+ egg_warning ("cannot reset client: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* install signature */
+ ret = pk_client_install_signature (cupdate->priv->client_secondary, PK_SIGTYPE_ENUM_GPG, key_id, package_id, &error);
+ if (!ret) {
+ egg_warning ("cannot install signature: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+ /* set state */
+ egg_debug ("repo sig cb");
+ gpk_check_update_query_updates (cupdate, TRUE);
+out:
+ return;
+}
+
+/**
+ * gpk_check_update_repo_signature_required_cb:
+ **/
+static void
+gpk_check_update_repo_signature_required_cb (PkClient *client, const gchar *package_id, const gchar *repository_name,
+ const gchar *key_url, const gchar *key_userid, const gchar *key_id,
+ const gchar *key_fingerprint, const gchar *key_timestamp,
+ PkSigTypeEnum type, GpkCheckUpdate *cupdate)
+{
+ /* use the helper */
+ gpk_helper_repo_signature_show (cupdate->priv->helper_repo_signature, package_id,
+ repository_name, key_url, key_userid, key_id, key_fingerprint, key_timestamp);
+}
+
+/**
+ * gpk_check_update_primary_requeue:
+ **/
+static gboolean
+gpk_check_update_primary_requeue (GpkCheckUpdate *cupdate)
+{
+ gboolean ret;
+ GError *error = NULL;
+
+ /* retry new action */
+ ret = pk_client_requeue (cupdate->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("Failed to requeue: %s", error->message);
+ g_error_free (error);
+ }
+ return ret;
+}
+
+/**
+ * gpk_check_update_finished_notify:
+ **/
+static void
+gpk_check_update_finished_notify (GpkCheckUpdate *cupdate, PkClient *client)
+{
+ gboolean ret;
+ GError *error = NULL;
+ NotifyNotification *notification;
+ PkRestartEnum restart;
+ guint i;
+ guint length;
+ PkPackageList *list;
+ const PkPackageObj *obj;
+ GString *message_text;
+ guint skipped_number = 0;
+ const gchar *message;
+
+ /* check we got some packages */
+ list = pk_client_get_package_list (client);
+ length = pk_package_list_get_size (list);
+ egg_debug ("length=%i", length);
+ if (length == 0) {
+ egg_debug ("no updates");
+ return;
+ }
+
+ message_text = g_string_new ("");
+
+ /* find any we skipped */
+ for (i=0; i<length; i++) {
+ obj = pk_package_list_get_obj (list, i);
+ egg_debug ("%s, %s, %s", pk_info_enum_to_text (obj->info),
+ obj->id->name, obj->summary);
+ if (obj->info == PK_INFO_ENUM_BLOCKED) {
+ skipped_number++;
+ g_string_append_printf (message_text, "<b>%s</b> - %s\n",
+ obj->id->name, obj->summary);
+ }
+ }
+ g_object_unref (list);
+
+ /* notify the user if there were skipped entries */
+ if (skipped_number > 0) {
+ /* TRANSLATORS: we did the update, but some updates were skipped and not applied */
+ message = ngettext ("One package was skipped:",
+ "Some packages were skipped:", skipped_number);
+ g_string_prepend (message_text, message);
+ g_string_append_c (message_text, '\n');
+ }
+
+ /* add a message that we need to restart */
+ restart = pk_client_get_require_restart (client);
+ if (restart != PK_RESTART_ENUM_NONE) {
+ message = gpk_restart_enum_to_localised_text (restart);
+
+ /* add a gap if we are putting both */
+ if (skipped_number > 0)
+ g_string_append (message_text, "\n");
+
+ g_string_append (message_text, message);
+ g_string_append_c (message_text, '\n');
+ }
+
+ /* trim off extra newlines */
+ if (message_text->len != 0)
+ g_string_set_size (message_text, message_text->len-1);
+
+ /* do we do the notification? */
+ ret = gconf_client_get_bool (cupdate->priv->gconf_client, GPK_CONF_NOTIFY_UPDATE_COMPLETE, NULL);
+ if (!ret) {
+ egg_debug ("ignoring due to GConf");
+ return;
+ }
+
+ /* TRANSLATORS: title: system update completed all okay */
+ notification = notify_notification_new (_("The system update has completed"), message_text->str, "help-browser", NULL);
+ notify_notification_set_timeout (notification, 15000);
+ notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
+ if (restart == PK_RESTART_ENUM_SYSTEM) {
+ notify_notification_add_action (notification, "restart",
+ /* TRANSLATORS: restart computer as system packages need update */
+ _("Restart computer now"), gpk_check_update_libnotify_cb, cupdate, NULL);
+ notify_notification_add_action (notification, "do-not-show-complete-restart",
+ /* TRANSLATORS: don't show this option again (for restart) */
+ _("Do not show this again"), gpk_check_update_libnotify_cb, cupdate, NULL);
+ } else {
+ notify_notification_add_action (notification, "do-not-show-complete",
+ /* TRANSLATORS: don't show this option again (when finished) */
+ _("Do not show this again"), gpk_check_update_libnotify_cb, cupdate, NULL);
+ }
+ ret = notify_notification_show (notification, &error);
+ if (!ret) {
+ egg_warning ("error: %s", error->message);
+ g_error_free (error);
+ }
+ g_string_free (message_text, TRUE);
+}
+
+/**
+ * gpk_check_update_finished_cb:
+ **/
+static void
+gpk_check_update_finished_cb (PkClient *client, PkExitEnum exit_enum, guint runtime, GpkCheckUpdate *cupdate)
+{
+ PkRoleEnum role;
+ PkPackageList *list;
+ PkObjList *array;
+
+ pk_client_get_role (client, &role, NULL, NULL);
+ egg_debug ("role: %s, exit: %s", pk_role_enum_to_text (role), pk_exit_enum_to_text (exit_enum));
+
+ /* we've just agreed to auth */
+ if (role == PK_ROLE_ENUM_INSTALL_SIGNATURE) {
+ if (exit_enum == PK_EXIT_ENUM_SUCCESS)
+ gpk_check_update_primary_requeue (cupdate);
+ }
+
+ /* get-updates */
+ if (role == PK_ROLE_ENUM_GET_UPDATES &&
+ exit_enum == PK_EXIT_ENUM_SUCCESS) {
+ list = pk_client_get_package_list (client);
+ gpk_check_update_process_updates (cupdate, list, TRUE);
+ g_object_unref (list);
+ }
+
+ /* get-upgrades */
+ if (role == PK_ROLE_ENUM_GET_DISTRO_UPGRADES &&
+ exit_enum == PK_EXIT_ENUM_SUCCESS) {
+ array = pk_client_get_cached_objects (client);
+ gpk_check_update_process_distro_upgrades (cupdate, array);
+ g_object_unref (array);
+ }
+
+ /* refresh-cache */
+ if (role == PK_ROLE_ENUM_REFRESH_CACHE &&
+ exit_enum == PK_EXIT_ENUM_SUCCESS) {
+ egg_debug ("finished refresh cb");
+ gpk_check_update_query_updates (cupdate, TRUE);
+ }
+
+ /* updates */
+ if ((role == PK_ROLE_ENUM_UPDATE_PACKAGES ||
+ role == PK_ROLE_ENUM_UPDATE_SYSTEM) &&
+ exit_enum == PK_EXIT_ENUM_SUCCESS) {
+ gpk_check_update_finished_notify (cupdate, client);
+ cupdate->priv->number_updates_critical_last_shown = 0;
+ }
+}
+
+/**
* gpk_check_update_init:
* @cupdate: This class instance
**/
@@ -1088,7 +1416,11 @@
cupdate->priv->number_updates_critical_last_shown = 0;
cupdate->priv->sicon = gpk_smart_icon_new ();
+ /* preload all the common GConf keys */
cupdate->priv->gconf_client = gconf_client_get_default ();
+ gconf_client_add_dir (cupdate->priv->gconf_client, GPK_CONF_DIR,
+ GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+
cupdate->priv->arefresh = gpk_auto_refresh_new ();
g_signal_connect (cupdate->priv->arefresh, "refresh-cache",
G_CALLBACK (gpk_check_update_auto_refresh_cache_cb), cupdate);
@@ -1115,11 +1447,26 @@
g_signal_connect (cupdate->priv->dbus_monitor_viewer, "connection-changed",
G_CALLBACK (gpk_cupdate_connection_changed_cb), cupdate);
- /* install stuff using the gnome helpers */
- cupdate->priv->gclient_refresh_cache = gpk_client_new ();
- cupdate->priv->gclient_update_system = gpk_client_new ();
- cupdate->priv->gclient_get_updates = gpk_client_new ();
- cupdate->priv->gclient_get_distro_upgrades = gpk_client_new ();
+ /* use an asynchronous query object */
+ cupdate->priv->client_primary = pk_client_new ();
+ pk_client_set_use_buffer (cupdate->priv->client_primary, TRUE, NULL);
+ g_signal_connect (cupdate->priv->client_primary, "finished",
+ G_CALLBACK (gpk_check_update_finished_cb), cupdate);
+ g_signal_connect (cupdate->priv->client_primary, "error-code",
+ G_CALLBACK (gpk_check_update_error_code_cb), cupdate);
+ g_signal_connect (cupdate->priv->client_primary, "repo-signature-required",
+ G_CALLBACK (gpk_check_update_repo_signature_required_cb), cupdate);
+
+ /* this is for the auth callback */
+ cupdate->priv->client_secondary = pk_client_new ();
+ g_signal_connect (cupdate->priv->client_secondary, "error-code",
+ G_CALLBACK (gpk_check_update_error_code_cb), cupdate);
+ g_signal_connect (cupdate->priv->client_secondary, "finished",
+ G_CALLBACK (gpk_check_update_finished_cb), cupdate);
+
+ /* helpers */
+ cupdate->priv->helper_repo_signature = gpk_helper_repo_signature_new ();
+ g_signal_connect (cupdate->priv->helper_repo_signature, "event", G_CALLBACK (gpk_check_update_repo_signature_event_cb), NULL);
cupdate->priv->pconnection = pk_connection_new ();
g_signal_connect (cupdate->priv->pconnection, "connection-changed",
@@ -1140,11 +1487,6 @@
cupdate->priv->tlist = pk_task_list_new ();
g_signal_connect (cupdate->priv->tlist, "changed",
G_CALLBACK (gpk_check_update_task_list_changed_cb), cupdate);
-
- /* refresh the cache, and poll until we get a good refresh */
- cupdate->priv->cache_okay = FALSE;
- cupdate->priv->cache_update_in_progress = FALSE;
- cupdate->priv->get_updates_in_progress = FALSE;
}
/**
@@ -1168,11 +1510,10 @@
g_object_unref (cupdate->priv->arefresh);
g_object_unref (cupdate->priv->gconf_client);
g_object_unref (cupdate->priv->control);
- g_object_unref (cupdate->priv->gclient_refresh_cache);
- g_object_unref (cupdate->priv->gclient_update_system);
- g_object_unref (cupdate->priv->gclient_get_updates);
- g_object_unref (cupdate->priv->gclient_get_distro_upgrades);
+ g_object_unref (cupdate->priv->client_primary);
+ g_object_unref (cupdate->priv->client_secondary);
g_object_unref (cupdate->priv->dbus_monitor_viewer);
+ g_object_unref (cupdate->priv->helper_repo_signature);
if (cupdate->priv->important_updates_array != NULL) {
g_ptr_array_foreach (cupdate->priv->important_updates_array, (GFunc) g_free, NULL);
g_ptr_array_free (cupdate->priv->important_updates_array, TRUE);
Modified: trunk/src/gpk-common.h
==============================================================================
--- trunk/src/gpk-common.h (original)
+++ trunk/src/gpk-common.h Tue Apr 14 16:28:59 2009
@@ -62,7 +62,8 @@
#define GPK_CONF_APPLICATION_FILTER_NEWEST "/apps/gnome-packagekit/application/filter_newest"
#define GPK_CONF_APPLICATION_CATEGORY_GROUPS "/apps/gnome-packagekit/application/category_groups"
#define GPK_CONF_APPLICATION_SEARCH_MODE "/apps/gnome-packagekit/application/search_mode"
-#define GPK_CONF_UPDATE_VIEWER_PRECACHE_DETAILS "/apps/gnome-packagekit/update_viewer/precache_details"
+#define GPK_CONF_UPDATE_VIEWER_PRECACHE_DETAILS "/apps/gnome-packagekit/update-viewer/precache_details"
+#define GPK_CONF_UPDATE_VIEWER_MOBILE_BBAND "/apps/gnome-packagekit/update-viewer/notify_mobile_connection"
#define GPK_CONF_IGNORED_MESSAGES "/apps/gnome-packagekit/ignored_messages"
#define GPK_CONF_ENABLE_FONT_HELPER "/apps/gnome-packagekit/enable_font_helper"
Added: trunk/src/gpk-dbus-task.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-dbus-task.c Tue Apr 14 16:28:59 2009
@@ -0,0 +1,3338 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <string.h>
+#include <glib/gi18n.h>
+#include <glib/gprintf.h>
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+
+#include <fontconfig/fontconfig.h>
+#include <gtk/gtk.h>
+#include <gconf/gconf-client.h>
+#include <polkit-gnome/polkit-gnome.h>
+#include <libnotify/notify.h>
+#include <packagekit-glib/packagekit.h>
+
+#include "egg-debug.h"
+#include "egg-string.h"
+
+#include "gpk-dbus.h"
+#include "gpk-dbus-task.h"
+#include "gpk-modal-dialog.h"
+#include "gpk-common.h"
+#include "gpk-gnome.h"
+#include "gpk-error.h"
+#include "gpk-language.h"
+#include "gpk-dialog.h"
+#include "gpk-vendor.h"
+#include "gpk-enum.h"
+#include "gpk-x11.h"
+#include "gpk-desktop.h"
+#include "gpk-helper-repo-signature.h"
+#include "gpk-helper-eula.h"
+#include "gpk-helper-run.h"
+#include "gpk-helper-untrusted.h"
+#include "gpk-helper-chooser.h"
+
+static void gpk_dbus_task_finalize (GObject *object);
+
+#define GPK_DBUS_TASK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPK_TYPE_DBUS_TASK, GpkDbusTaskPrivate))
+#define GPK_DBUS_TASK_FINISHED_AUTOCLOSE_DELAY 10 /* seconds */
+
+typedef enum {
+ GPK_DBUS_TASK_ROLE_IS_INSTALLED,
+ GPK_DBUS_TASK_ROLE_SEARCH_FILE,
+ GPK_DBUS_TASK_ROLE_INSTALL_PACKAGE_FILES,
+ GPK_DBUS_TASK_ROLE_INSTALL_PROVIDE_FILES,
+ GPK_DBUS_TASK_ROLE_INSTALL_MIME_TYPES,
+ GPK_DBUS_TASK_ROLE_INSTALL_GSTREAMER_RESOURCES,
+ GPK_DBUS_TASK_ROLE_INSTALL_FONTCONFIG_RESOURCES,
+ GPK_DBUS_TASK_ROLE_INSTALL_PACKAGE_NAMES,
+ GPK_DBUS_TASK_ROLE_INSTALL_CATALOGS,
+ GPK_DBUS_TASK_ROLE_UNKNOWN
+} GpkDbusTaskRole;
+
+/**
+ * GpkDbusTaskPrivate:
+ *
+ * Private #GpkDbusTask data
+ **/
+struct _GpkDbusTaskPrivate
+{
+ GdkWindow *parent_window;
+ GConfClient *gconf_client;
+ PkClient *client_primary;
+ PkClient *client_secondary;
+ PkDesktop *desktop;
+ PkControl *control;
+ PkExitEnum exit;
+ PkBitfield roles;
+ GpkLanguage *language;
+ GpkModalDialog *dialog;
+ GpkVendor *vendor;
+ gboolean show_confirm_search;
+ gboolean show_confirm_deps;
+ gboolean show_confirm_install;
+ gboolean show_progress;
+ gboolean show_finished;
+ gboolean show_warning;
+ guint timestamp;
+ gchar *parent_title;
+ gchar *parent_icon_name;
+ gchar *error_details;
+ gint timeout;
+ GpkHelperRepoSignature *helper_repo_signature;
+ GpkHelperEula *helper_eula;
+ GpkHelperRun *helper_run;
+ GpkHelperUntrusted *helper_untrusted;
+ GpkHelperChooser *helper_chooser;
+ DBusGMethodInvocation *context;
+ GpkDbusTaskRole role;
+ gchar **package_ids;
+ gchar **files;
+ PkErrorCodeEnum last_exit_code;
+};
+
+G_DEFINE_TYPE (GpkDbusTask, gpk_dbus_task, G_TYPE_OBJECT)
+
+/**
+ * gpk_dbus_task_set_interaction:
+ **/
+gboolean
+gpk_dbus_task_set_interaction (GpkDbusTask *task, PkBitfield interact)
+{
+ g_return_val_if_fail (GPK_IS_DBUS_TASK (task), FALSE);
+
+ task->priv->show_confirm_search = pk_bitfield_contain (interact, GPK_CLIENT_INTERACT_CONFIRM_SEARCH);
+ task->priv->show_confirm_deps = pk_bitfield_contain (interact, GPK_CLIENT_INTERACT_CONFIRM_DEPS);
+ task->priv->show_confirm_install = pk_bitfield_contain (interact, GPK_CLIENT_INTERACT_CONFIRM_INSTALL);
+ task->priv->show_progress = pk_bitfield_contain (interact, GPK_CLIENT_INTERACT_PROGRESS);
+ task->priv->show_finished = pk_bitfield_contain (interact, GPK_CLIENT_INTERACT_FINISHED);
+ task->priv->show_warning = pk_bitfield_contain (interact, GPK_CLIENT_INTERACT_WARNING);
+
+ /* debug */
+ egg_debug ("confirm_search:%i, confirm_deps:%i, confirm_install:%i, progress:%i, finished:%i, warning:%i",
+ task->priv->show_confirm_search, task->priv->show_confirm_deps,
+ task->priv->show_confirm_install, task->priv->show_progress,
+ task->priv->show_finished, task->priv->show_warning);
+
+ return TRUE;
+}
+
+/**
+ * gpk_dbus_task_set_context:
+ **/
+gboolean
+gpk_dbus_task_set_context (GpkDbusTask *task, DBusGMethodInvocation *context)
+{
+ g_return_val_if_fail (GPK_IS_DBUS_TASK (task), FALSE);
+ g_return_val_if_fail (context != NULL, FALSE);
+
+ task->priv->context = context;
+ return TRUE;
+}
+
+/**
+ * gpk_dbus_task_set_timeout:
+ **/
+gboolean
+gpk_dbus_task_set_timeout (GpkDbusTask *task, gint timeout)
+{
+ g_return_val_if_fail (GPK_IS_DBUS_TASK (task), FALSE);
+
+ task->priv->timeout = timeout;
+ return TRUE;
+}
+
+/**
+ * gpk_dbus_task_set_xid:
+ **/
+gboolean
+gpk_dbus_task_set_xid (GpkDbusTask *task, guint32 xid)
+{
+ GdkDisplay *display;
+ g_return_val_if_fail (GPK_IS_DBUS_TASK (task), FALSE);
+
+ display = gdk_display_get_default ();
+ task->priv->parent_window = gdk_window_foreign_new_for_display (display, xid);
+ egg_debug ("parent_window=%p", task->priv->parent_window);
+ gpk_modal_dialog_set_parent (task->priv->dialog, task->priv->parent_window);
+ return TRUE;
+}
+
+/**
+ * gpk_dbus_task_set_timestamp:
+ **/
+gboolean
+gpk_dbus_task_set_timestamp (GpkDbusTask *task, guint32 timestamp)
+{
+ g_return_val_if_fail (GPK_IS_DBUS_TASK (task), FALSE);
+ task->priv->timestamp = timestamp;
+ return TRUE;
+}
+
+/**
+ * gpk_dbus_task_repo_signature_event_cb:
+ **/
+static void
+gpk_dbus_task_repo_signature_event_cb (GpkHelperRepoSignature *helper_repo_signature, GtkResponseType type, const gchar *key_id, const gchar *package_id, GpkDbusTask *task)
+{
+ gboolean ret;
+ GError *error = NULL;
+
+ if (type != GTK_RESPONSE_YES) {
+ goto out;
+ }
+
+ /* reset client */
+ ret = pk_client_reset (task->priv->client_secondary, &error);
+ if (!ret) {
+ egg_warning ("cannot reset client: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* install signature */
+ ret = pk_client_install_signature (task->priv->client_secondary, PK_SIGTYPE_ENUM_GPG, key_id, package_id, &error);
+ if (!ret) {
+ egg_warning ("cannot install signature: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ return;
+}
+
+/**
+ * gpk_dbus_task_eula_event_cb:
+ **/
+static void
+gpk_dbus_task_eula_event_cb (GpkHelperEula *helper_eula, GtkResponseType type, const gchar *eula_id, GpkDbusTask *task)
+{
+ gboolean ret;
+ GError *error = NULL;
+
+ if (type != GTK_RESPONSE_YES) {
+ goto out;
+ }
+
+ /* reset client */
+ ret = pk_client_reset (task->priv->client_secondary, &error);
+ if (!ret) {
+ egg_warning ("cannot reset client: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* install signature */
+ ret = pk_client_accept_eula (task->priv->client_secondary, eula_id, &error);
+ if (!ret) {
+ egg_warning ("cannot accept eula: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ return;
+}
+
+/**
+ * gpk_dbus_task_eula_cb:
+ **/
+static void
+gpk_dbus_task_eula_required_cb (PkClient *client, const gchar *eula_id, const gchar *package_id,
+ const gchar *vendor_name, const gchar *license_agreement, GpkDbusTask *task)
+{
+ g_return_if_fail (GPK_IS_DBUS_TASK (task));
+
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_CUSTOM, pk_bitfield_value (GPK_MODAL_DIALOG_WIDGET_PROGRESS_BAR));
+ gpk_modal_dialog_set_title (task->priv->dialog, _("EULA required"));
+ gpk_modal_dialog_set_image_status (task->priv->dialog, PK_STATUS_ENUM_SIG_CHECK);
+ gpk_modal_dialog_set_percentage (task->priv->dialog, 101);
+ if (task->priv->show_progress)
+ gpk_modal_dialog_present (task->priv->dialog);
+
+ /* use the helper */
+ gpk_helper_eula_show (task->priv->helper_eula, eula_id, package_id, vendor_name, license_agreement);
+}
+
+/**
+ * gpk_dbus_task_repo_signature_required_cb:
+ **/
+static void
+gpk_dbus_task_repo_signature_required_cb (PkClient *client, const gchar *package_id, const gchar *repository_name,
+ const gchar *key_url, const gchar *key_userid, const gchar *key_id,
+ const gchar *key_fingerprint, const gchar *key_timestamp,
+ PkSigTypeEnum type, GpkDbusTask *task)
+{
+ g_return_if_fail (GPK_IS_DBUS_TASK (task));
+
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_CUSTOM, pk_bitfield_value (GPK_MODAL_DIALOG_WIDGET_PROGRESS_BAR));
+ gpk_modal_dialog_set_title (task->priv->dialog, _("Signature required"));
+ gpk_modal_dialog_set_image_status (task->priv->dialog, PK_STATUS_ENUM_SIG_CHECK);
+ gpk_modal_dialog_set_percentage (task->priv->dialog, 101);
+ if (task->priv->show_progress)
+ gpk_modal_dialog_present (task->priv->dialog);
+
+ /* use the helper */
+ gpk_helper_repo_signature_show (task->priv->helper_repo_signature, package_id, repository_name, key_url, key_userid, key_id, key_fingerprint, key_timestamp);
+}
+
+static void gpk_dbus_task_install_package_files_internal (GpkDbusTask *task, gboolean trusted);
+
+/**
+ * gpk_dbus_task_untrusted_event_cb:
+ **/
+static void
+gpk_dbus_task_untrusted_event_cb (GpkHelperUntrusted *helper_untrusted, GtkResponseType type, GpkDbusTask *task)
+{
+ GError *error = NULL;
+ const gchar *title;
+
+ if (type != GTK_RESPONSE_YES) {
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_CANCELLED, "did not agree to download");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ title = _("Install untrusted");
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_PROGRESS, 0);
+ gpk_modal_dialog_set_title (task->priv->dialog, title);
+ if (task->priv->show_progress)
+ gpk_modal_dialog_present_with_time (task->priv->dialog, task->priv->timestamp);
+
+ /* install trusted */
+ gpk_dbus_task_install_package_files_internal (task, FALSE);
+out:
+ if (error != NULL)
+ g_error_free (error);
+ return;
+}
+
+static void gpk_dbus_task_install_package_ids_dep_check (GpkDbusTask *task);
+
+/**
+ * gpk_dbus_task_chooser_event_cb:
+ **/
+static void
+gpk_dbus_task_chooser_event_cb (GpkHelperChooser *helper_chooser, GtkResponseType type, const gchar *package_id, GpkDbusTask *task)
+{
+ GError *error = NULL;
+
+ /* selected nothing */
+ if (type != GTK_RESPONSE_YES || package_id == NULL) {
+
+ /* failed */
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_CANCELLED, "did not choose anything to install");
+ dbus_g_method_return_error (task->priv->context, error);
+
+ if (task->priv->show_warning) {
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, 0);
+ /* TRANSLATORS: we failed to install */
+ gpk_modal_dialog_set_title (task->priv->dialog, _("Failed to install software"));
+ /* TRANSLATORS: we didn't select any applications that were returned */
+ gpk_modal_dialog_set_message (task->priv->dialog, _("No applications were chosen to be installed"));
+ gpk_modal_dialog_present (task->priv->dialog);
+ gpk_modal_dialog_run (task->priv->dialog);
+ }
+ goto out;
+ }
+
+ /* install this specific package */
+ task->priv->package_ids = pk_package_ids_from_id (package_id);
+
+ /* install these packages with deps */
+ gpk_dbus_task_install_package_ids_dep_check (task);
+
+out:
+ if (error != NULL)
+ g_error_free (error);
+ return;
+}
+
+/**
+ * gpk_dbus_task_libnotify_cb:
+ **/
+static void
+gpk_dbus_task_libnotify_cb (NotifyNotification *notification, gchar *action, gpointer data)
+{
+ GpkDbusTask *task = GPK_DBUS_TASK (data);
+
+ if (egg_strequal (action, "show-error-details")) {
+ /* TRANSLATORS: detailed text about the error */
+ gpk_error_dialog (_("Error details"), _("Package Manager error details"), task->priv->error_details);
+ } else {
+ egg_warning ("unknown action id: %s", action);
+ }
+}
+
+/**
+ * gpk_dbus_task_error_msg:
+ **/
+static void
+gpk_dbus_task_error_msg (GpkDbusTask *task, const gchar *title, GError *error)
+{
+ GtkWindow *window;
+ /* TRANSLATORS: default fallback error -- this should never happen */
+ const gchar *message = _("Unknown error. Please refer to the detailed report and report in your distribution bugtracker.");
+ const gchar *details = NULL;
+
+ if (!task->priv->show_warning)
+ return;
+
+ /* setup UI */
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, 0);
+
+ /* print a proper error if we have it */
+ if (error != NULL) {
+ if (error->code == PK_CLIENT_ERROR_FAILED_AUTH ||
+ g_str_has_prefix (error->message, "org.freedesktop.packagekit.")) {
+ /* TRANSLATORS: failed authentication */
+ message = _("You don't have the necessary privileges to perform this action.");
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-permissions");
+ } else if (error->code == PK_CLIENT_ERROR_CANNOT_START_DAEMON) {
+ /* TRANSLATORS: could not start system service */
+ message = _("The packagekitd service could not be started.");
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-no-service");
+ } else if (error->code == PK_CLIENT_ERROR_INVALID_INPUT) {
+ /* TRANSLATORS: the user tried to query for something invalid */
+ message = _("The query is not valid.");
+ details = error->message;
+ } else if (error->code == PK_CLIENT_ERROR_INVALID_FILE) {
+ /* TRANSLATORS: the user tried to install a file that was not compatable or broken */
+ message = _("The file is not valid.");
+ details = error->message;
+ } else {
+ details = error->message;
+ }
+ }
+
+ /* it's a normal UI, not a backtrace so keep in the UI */
+ if (details == NULL) {
+ gpk_modal_dialog_set_title (task->priv->dialog, title);
+ gpk_modal_dialog_set_message (task->priv->dialog, message);
+ gpk_modal_dialog_present_with_time (task->priv->dialog, task->priv->timestamp);
+ gpk_modal_dialog_run (task->priv->dialog);
+ return;
+ }
+
+ /* hide the main window */
+ window = gpk_modal_dialog_get_window (task->priv->dialog);
+ gpk_error_dialog_modal_with_time (window, title, message, details, task->priv->timestamp);
+}
+
+/**
+ * gpk_dbus_task_install_package_ids:
+ * @task: a valid #GpkDbusTask instance
+ * @package_id: a package_id such as <literal>hal-info;0.20;i386;fedora</literal>
+ * @error: a %GError to put the error code and message in, or %NULL
+ *
+ * Return value: %TRUE if the method succeeded
+ **/
+static void
+gpk_dbus_task_install_package_ids (GpkDbusTask *task)
+{
+ gboolean ret;
+ GError *error = NULL;
+ GError *error_local = NULL;
+
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_PROGRESS, GPK_MODAL_DIALOG_PACKAGE_PADDING);
+ /* TRANSLATORS: title: installing packages */
+ gpk_modal_dialog_set_title (task->priv->dialog, _("Installing packages"));
+ if (task->priv->show_progress)
+ gpk_modal_dialog_present (task->priv->dialog);
+
+ /* reset */
+ ret = pk_client_reset (task->priv->client_primary, &error_local);
+ if (!ret) {
+ /* TRANSLATORS: this should never happen, low level failure */
+ gpk_dbus_task_error_msg (task, _("Failed to reset client to perform action"), error_local);
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "%s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* set timeout */
+ pk_client_set_timeout (task->priv->client_primary, task->priv->timeout, NULL);
+
+ ret = pk_client_install_packages (task->priv->client_primary, task->priv->package_ids, &error_local);
+ if (!ret) {
+ /* TRANSLATORS: error: failed to install, detailed error follows */
+ gpk_dbus_task_error_msg (task, _("Failed to install package"), error_local);
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "%s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+out:
+ if (error != NULL)
+ g_error_free (error);
+ if (error_local != NULL)
+ g_error_free (error_local);
+}
+
+/**
+ * gpk_dbus_task_install_package_ids_dep_check:
+ * @task: a valid #GpkDbusTask instance
+ * @package_id: a package_id such as <literal>hal-info;0.20;i386;fedora</literal>
+ * @error: a %GError to put the error code and message in, or %NULL
+ *
+ * Return value: %TRUE if the method succeeded
+ **/
+static void
+gpk_dbus_task_install_package_ids_dep_check (GpkDbusTask *task)
+{
+ gboolean ret;
+ GError *error = NULL;
+ GError *error_local = NULL;
+
+ g_return_if_fail (GPK_IS_DBUS_TASK (task));
+ g_return_if_fail (task->priv->package_ids != NULL);
+
+ /* are we dumb and can't check for depends? */
+ if (!pk_bitfield_contain (task->priv->roles, PK_ROLE_ENUM_GET_DEPENDS)) {
+ egg_warning ("skipping depends check");
+ gpk_dbus_task_install_package_ids (task);
+ goto out;
+ }
+
+ /* have we previously said we don't want to be shown the confirmation */
+ ret = gconf_client_get_bool (task->priv->gconf_client, GPK_CONF_SHOW_DEPENDS, NULL);
+ if (!ret) {
+ egg_warning ("we've said we don't want the dep dialog");
+ gpk_dbus_task_install_package_ids (task);
+ goto out;
+ }
+
+ /* optional */
+ if (!task->priv->show_confirm_deps) {
+ egg_warning ("skip confirm as not allowed to interact with user");
+ gpk_dbus_task_install_package_ids (task);
+ goto out;
+ }
+
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_PROGRESS, GPK_MODAL_DIALOG_PACKAGE_PADDING);
+ /* TRANSLATORS: finding a list of packages that we would also need to download */
+ gpk_modal_dialog_set_title (task->priv->dialog, _("Finding other packages we require"));
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-finding-depends");
+
+ /* setup the UI */
+ if (task->priv->show_progress)
+ gpk_modal_dialog_present (task->priv->dialog);
+
+ /* reset */
+ ret = pk_client_reset (task->priv->client_primary, &error_local);
+ if (!ret) {
+ /* TRANSLATORS: this is an internal error, and should not be seen */
+ gpk_dbus_task_error_msg (task, _("Failed to reset client"), error_local);
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "%s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* set timeout */
+ pk_client_set_timeout (task->priv->client_primary, task->priv->timeout, NULL);
+
+ /* find out if this would drag in other packages */
+ ret = pk_client_get_depends (task->priv->client_primary, pk_bitfield_value (PK_FILTER_ENUM_NOT_INSTALLED), task->priv->package_ids, TRUE, &error_local);
+ if (!ret) {
+ /* TRANSLATORS: error: could not get the extra package list when installing a package */
+ gpk_dbus_task_error_msg (task, _("Could not work out what packages would be also installed"), error_local);
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "%s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* wait for async reply */
+
+out:
+ if (error != NULL)
+ g_error_free (error);
+ if (error_local != NULL)
+ g_error_free (error_local);
+}
+
+/**
+ * gpk_dbus_task_error_from_exit_enum:
+ **/
+static GError *
+gpk_dbus_task_error_from_exit_enum (PkExitEnum exit)
+{
+ GError *error = NULL;
+
+ /* trivial case */
+ if (exit == PK_EXIT_ENUM_SUCCESS)
+ goto out;
+
+ /* set the correct error type */
+ if (exit == PK_EXIT_ENUM_FAILED)
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_FAILED, "Unspecified failure");
+ else if (exit == PK_EXIT_ENUM_CANCELLED)
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_CANCELLED, "Transaction was cancelled");
+ else if (exit == PK_EXIT_ENUM_KEY_REQUIRED)
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_CANCELLED, "A key was required but not provided");
+ else if (exit == PK_EXIT_ENUM_EULA_REQUIRED)
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_CANCELLED, "A EULA was not agreed to");
+ else if (exit == PK_EXIT_ENUM_KILLED)
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_CANCELLED, "The transaction was killed");
+ else
+ egg_error ("unknown exit code");
+out:
+ return error;
+}
+
+/**
+ * gpk_dbus_task_install_package_ids_dep_check_idle_cb:
+ **/
+static gboolean
+gpk_dbus_task_install_package_ids_dep_check_idle_cb (GpkDbusTask *task)
+{
+ egg_warning ("idle add install package ids dep check");
+ gpk_dbus_task_install_package_ids_dep_check (task);
+ return FALSE;
+}
+
+/**
+ * gpk_dbus_task_install_package_ids_idle_cb:
+ **/
+static gboolean
+gpk_dbus_task_install_package_ids_idle_cb (GpkDbusTask *task)
+{
+ egg_warning ("idle add install package ids");
+ gpk_dbus_task_install_package_ids (task);
+ return FALSE;
+}
+
+/**
+ * gpk_dbus_task_finished_cb:
+ **/
+static void
+gpk_dbus_task_finished_cb (PkClient *client, PkExitEnum exit_enum, guint runtime, GpkDbusTask *task)
+{
+ PkRoleEnum role = PK_ROLE_ENUM_UNKNOWN;
+ gboolean ret;
+ guint len;
+ guint i;
+ const gchar *name = NULL;
+ GError *error = NULL;
+ GError *error_local = NULL;
+ PkPackageList *list = NULL;
+ const PkPackageObj *obj;
+ gboolean already_installed = FALSE;
+ gchar *title = NULL;
+ gchar *message = NULL;
+ gchar *text = NULL;
+ PkPackageId *id = NULL;
+ gchar *info_url = NULL;
+ gchar **package_ids = NULL;
+ GtkResponseType button;
+ gchar *package_id = NULL;
+
+ /* get role */
+ pk_client_get_role (client, &role, NULL, NULL);
+ egg_debug ("role: %s, exit: %s", pk_role_enum_to_text (role), pk_exit_enum_to_text (exit_enum));
+
+ /* stop spinning */
+ gpk_modal_dialog_set_percentage (task->priv->dialog, 100);
+
+ /* we failed because we're handling the auth, just ignore */
+ if (client == task->priv->client_primary &&
+ (exit_enum == PK_EXIT_ENUM_KEY_REQUIRED ||
+ exit_enum == PK_EXIT_ENUM_EULA_REQUIRED)) {
+ egg_debug ("ignoring primary sig-required or eula");
+ goto out;
+ }
+
+ /* EULA or GPG key auth done */
+ if (client == task->priv->client_secondary &&
+ exit_enum == PK_EXIT_ENUM_SUCCESS) {
+
+ /* try again */
+ ret = pk_client_requeue (task->priv->client_primary, &error_local);
+ if (!ret) {
+ egg_warning ("Failed to requeue: %s", error_local->message);
+ error = g_error_new (GPK_DBUS_ERROR, PK_ERROR_ENUM_INTERNAL_ERROR, "cannot requeue: %s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ }
+ goto out;
+ }
+
+ if (exit_enum != PK_EXIT_ENUM_SUCCESS) {
+
+ /* we failed because of failed exit code */
+ if (task->priv->last_exit_code == PK_ERROR_ENUM_GPG_FAILURE ||
+ task->priv->last_exit_code == PK_ERROR_ENUM_BAD_GPG_SIGNATURE ||
+ task->priv->last_exit_code == PK_ERROR_ENUM_MISSING_GPG_SIGNATURE) {
+ egg_warning ("showing untrusted ui");
+ gpk_helper_untrusted_show (task->priv->helper_untrusted, task->priv->last_exit_code);
+ goto out;
+ }
+
+ /* show finished? */
+ if (!task->priv->show_finished)
+ gpk_modal_dialog_close (task->priv->dialog);
+
+ /* fail the transaction and set the correct error */
+ error = gpk_dbus_task_error_from_exit_enum (exit_enum);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* from InstallMimeTypes */
+ if (task->priv->role == GPK_DBUS_TASK_ROLE_INSTALL_MIME_TYPES &&
+ role == PK_ROLE_ENUM_WHAT_PROVIDES) {
+
+ /* found nothing? */
+ list = pk_client_get_package_list (task->priv->client_primary);
+ len = pk_package_list_get_size (list);
+ if (len == 0) {
+ if (task->priv->show_warning) {
+ info_url = gpk_vendor_get_not_found_url (task->priv->vendor, GPK_VENDOR_URL_TYPE_MIME);
+ /* only show the "more info" button if there is a valid link */
+ if (info_url != NULL)
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, GPK_MODAL_DIALOG_BUTTON_ACTION);
+ else
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, 0);
+ /* TRANSLATORS: title */
+ gpk_modal_dialog_set_title (task->priv->dialog, _("Failed to find software"));
+ /* TRANSLATORS: nothing found in the software sources that helps */
+ gpk_modal_dialog_set_message (task->priv->dialog, _("No new applications can be found to handle this type of file"));
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-package-not-found");
+ /* TRANSLATORS: button: show the user a button to get more help finding stuff */
+ gpk_modal_dialog_set_action (task->priv->dialog, _("More information"));
+ gpk_modal_dialog_present (task->priv->dialog);
+ button = gpk_modal_dialog_run (task->priv->dialog);
+ if (button == GTK_RESPONSE_OK)
+ gpk_gnome_open (info_url);
+ }
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_NO_PACKAGES_FOUND, "nothing was found to handle mime type");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* populate a chooser */
+ gpk_helper_chooser_show (task->priv->helper_chooser, list);
+ goto out;
+ }
+
+ /* from InstallProvideFiles */
+ if (task->priv->role == GPK_DBUS_TASK_ROLE_INSTALL_PROVIDE_FILES &&
+ role == PK_ROLE_ENUM_SEARCH_FILE) {
+ /* found nothing? */
+ list = pk_client_get_package_list (task->priv->client_primary);
+ len = pk_package_list_get_size (list);
+ if (len == 0) {
+ if (task->priv->show_warning) {
+ info_url = gpk_vendor_get_not_found_url (task->priv->vendor, GPK_VENDOR_URL_TYPE_DEFAULT);
+ /* only show the "more info" button if there is a valid link */
+ if (info_url != NULL)
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, GPK_MODAL_DIALOG_BUTTON_ACTION);
+ else
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, 0);
+ /* TRANSLATORS: failed to fild the package for thefile */
+ gpk_modal_dialog_set_title (task->priv->dialog, _("Failed to find package"));
+ /* TRANSLATORS: nothing found */
+ gpk_modal_dialog_set_message (task->priv->dialog, _("The file could not be found in any packages"));
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-package-not-found");
+ /* TRANSLATORS: button: show the user a button to get more help finding stuff */
+ gpk_modal_dialog_set_action (task->priv->dialog, _("More information"));
+ gpk_modal_dialog_present (task->priv->dialog);
+ button = gpk_modal_dialog_run (task->priv->dialog);
+ if (button == GTK_RESPONSE_OK)
+ gpk_gnome_open (info_url);
+ }
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_NO_PACKAGES_FOUND, "no files found");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* see what we've got already */
+ for (i=0; i<len; i++) {
+ obj = pk_package_list_get_obj (list, i);
+ if (obj->info == PK_INFO_ENUM_INSTALLED) {
+ already_installed = TRUE;
+ id = obj->id;
+ } else if (obj->info == PK_INFO_ENUM_AVAILABLE) {
+ egg_debug ("package '%s' resolved to:", obj->id->name);
+ id = obj->id;
+ }
+ }
+
+ /* already installed? */
+ if (already_installed) {
+ if (task->priv->show_warning) {
+ /* TRANSLATORS: we've already got a package that provides this file */
+ text = g_strdup_printf (_("The %s package already provides this file"), id->name);
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, 0);
+ /* TRANSLATORS: title */
+ gpk_modal_dialog_set_title (task->priv->dialog, _("Failed to install file"));
+ gpk_modal_dialog_set_message (task->priv->dialog, text);
+ gpk_modal_dialog_present (task->priv->dialog);
+ gpk_modal_dialog_run (task->priv->dialog);
+ g_free (text);
+ }
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_FAILED, "already provided");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* install this specific package */
+ package_id = pk_package_id_to_string (id);
+ /* convert to data */
+ task->priv->package_ids = pk_package_ids_from_id (package_id);
+
+ /* install these packages with deps */
+ g_idle_add ((GSourceFunc) gpk_dbus_task_install_package_ids_dep_check_idle_cb, task);
+ goto out;
+ }
+
+ /* from InstallPackageIds */
+ if (role == PK_ROLE_ENUM_GET_DEPENDS) {
+ /* these are the new packages */
+ list = pk_client_get_package_list (task->priv->client_primary);
+ len = pk_package_list_get_size (list);
+ if (len == 0) {
+ egg_debug ("no deps");
+ goto skip_checks;
+ }
+
+ /* TRANSLATORS: title: tell the user we have to install additional packages */
+ title = g_strdup_printf (ngettext ("%i additional package also has to be installed",
+ "%i additional packages also have to be installed",
+ len), len);
+
+ /* message */
+ text = gpk_dialog_package_id_name_join_locale (task->priv->package_ids);
+ /* TRANSLATORS: message: explain to the user what we are doing in more detail */
+ message = g_strdup_printf (ngettext ("To install %s, an additional package also has to be downloaded.",
+ "To install %s, additional packages also have to be downloaded.",
+ len), text);
+ g_free (text);
+
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_CONFIRM, GPK_MODAL_DIALOG_PACKAGE_LIST);
+ gpk_modal_dialog_set_package_list (task->priv->dialog, list);
+ gpk_modal_dialog_set_title (task->priv->dialog, title);
+ gpk_modal_dialog_set_message (task->priv->dialog, message);
+ /* TRANSLATORS: title: installing package */
+ gpk_modal_dialog_set_action (task->priv->dialog, _("Install"));
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-install-other-packages");
+ gpk_modal_dialog_present_with_time (task->priv->dialog, task->priv->timestamp);
+ button = gpk_modal_dialog_run (task->priv->dialog);
+
+ /* did we click no or exit the window? */
+ if (button != GTK_RESPONSE_OK) {
+ gpk_modal_dialog_close (task->priv->dialog);
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_CANCELLED, "did not agree to additional deps");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+skip_checks:
+ g_idle_add ((GSourceFunc) gpk_dbus_task_install_package_ids_idle_cb, task);
+ }
+
+ /* from InstallPackageIds */
+ if (role == PK_ROLE_ENUM_INSTALL_PACKAGES ||
+ role == PK_ROLE_ENUM_INSTALL_FILES) {
+
+ /* show summary? */
+ if (task->priv->show_finished) {
+ list = pk_client_get_package_list (client);
+ /* TRANSLATORS: list the packages we just installed */
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_FINISHED, GPK_MODAL_DIALOG_PACKAGE_LIST);
+ gpk_modal_dialog_set_message (task->priv->dialog, _("The following packages were installed:"));
+
+ /* filter out installed */
+ for (i=0; i<PK_OBJ_LIST(list)->len; i++) {
+ obj = pk_obj_list_index (PK_OBJ_LIST (list), i);
+ if (obj->info != PK_INFO_ENUM_INSTALLING) {
+ pk_obj_list_remove_index (PK_OBJ_LIST (list), i);
+ i--;
+ }
+ }
+ gpk_modal_dialog_set_package_list (task->priv->dialog, list);
+ gpk_modal_dialog_present (task->priv->dialog);
+ g_object_unref (list);
+ } else {
+ gpk_modal_dialog_close (task->priv->dialog);
+ }
+
+ /* done! */
+ egg_warning ("doing async return");
+ dbus_g_method_return (task->priv->context, TRUE); /* FIXME: we send true? */
+ goto out;
+ }
+
+ /* IsInstalled */
+ if (task->priv->role == GPK_DBUS_TASK_ROLE_IS_INSTALLED) {
+ list = pk_client_get_package_list (task->priv->client_primary);
+
+ /* one or more entry? */
+ ret = (PK_OBJ_LIST(list)->len > 0);
+ egg_warning ("doing async return");
+ dbus_g_method_return (task->priv->context, ret);
+ goto out;
+ }
+
+ /* SearchFile */
+ if (task->priv->role == GPK_DBUS_TASK_ROLE_SEARCH_FILE) {
+ list = pk_client_get_package_list (task->priv->client_primary);
+
+ /* one or more entry? */
+ len = PK_OBJ_LIST(list)->len;
+ if (len > 0)
+ name = pk_package_list_get_obj (list, 0)->id->name;
+ egg_warning ("doing async return");
+ dbus_g_method_return (task->priv->context, (len > 0), name);
+ goto out;
+ }
+
+ /* InstallPackageNames */
+ if (task->priv->role == GPK_DBUS_TASK_ROLE_INSTALL_PACKAGE_NAMES &&
+ role == PK_ROLE_ENUM_RESOLVE) {
+
+ /* found nothing? */
+ list = pk_client_get_package_list (task->priv->client_primary);
+ len = pk_package_list_get_size (list);
+ if (len == 0) {
+ if (task->priv->show_warning) {
+ //FIXME: shows package_id in UI
+ /* TRANSLATORS: couldn't resolve name to package */
+ title = g_strdup_printf (_("Could not find packages"));
+ info_url = gpk_vendor_get_not_found_url (task->priv->vendor, GPK_VENDOR_URL_TYPE_DEFAULT);
+ /* only show the "more info" button if there is a valid link */
+ if (info_url != NULL)
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, GPK_MODAL_DIALOG_BUTTON_ACTION);
+ else
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, 0);
+ gpk_modal_dialog_set_title (task->priv->dialog, title);
+ /* TRANSLATORS: message: could not find */
+ gpk_modal_dialog_set_message (task->priv->dialog, _("The packages could not be found in any software source"));
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-package-not-found");
+ /* TRANSLATORS: button: a link to the help file */
+ gpk_modal_dialog_set_action (task->priv->dialog, _("More information"));
+ gpk_modal_dialog_present (task->priv->dialog);
+ button = gpk_modal_dialog_run (task->priv->dialog);
+ if (button == GTK_RESPONSE_OK)
+ gpk_gnome_open (info_url);
+ g_free (info_url);
+ g_free (title);
+ }
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_NO_PACKAGES_FOUND, "no package found");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* see what we've got already */
+ for (i=0; i<len; i++) {
+ obj = pk_package_list_get_obj (list, i);
+ if (obj->info == PK_INFO_ENUM_INSTALLED) {
+ already_installed = TRUE;
+ } else if (obj->info == PK_INFO_ENUM_AVAILABLE) {
+ egg_debug ("package '%s' resolved", obj->id->name);
+ id = obj->id;
+ //TODO: we need to list these in a gpk-dbus_task-chooser
+ }
+ }
+
+ /* already installed? */
+ if (already_installed) {
+ if (task->priv->show_warning) {
+ //FIXME: shows package_id in UI
+ /* TRANSLATORS: title: package is already installed */
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, 0);
+ gpk_modal_dialog_set_title (task->priv->dialog, _("Failed to install packages"));
+ /* TRANSLATORS: message: package is already installed */
+ gpk_modal_dialog_set_message (task->priv->dialog, _("The package is already installed"));
+ gpk_modal_dialog_present (task->priv->dialog);
+ gpk_modal_dialog_run (task->priv->dialog);
+ }
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_FAILED, "package already found");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* got junk? */
+ if (id == NULL) {
+ if (task->priv->show_warning) {
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, 0);
+ /* TRANSLATORS: failed to install, shouldn't be shown */
+ gpk_modal_dialog_set_title (task->priv->dialog, _("Failed to install package"));
+ /* TRANSLATORS: the search gave us the wrong result. internal error. barf. */
+ gpk_modal_dialog_set_message (task->priv->dialog, _("Incorrect response from search"));
+ gpk_modal_dialog_present (task->priv->dialog);
+ gpk_modal_dialog_run (task->priv->dialog);
+ }
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "incorrect response from search");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* convert to data */
+ task->priv->package_ids = pk_package_list_to_strv (list);
+
+ /* install these packages with deps */
+ g_idle_add ((GSourceFunc) gpk_dbus_task_install_package_ids_dep_check_idle_cb, task);
+ goto out;
+ }
+
+out:
+ g_free (info_url);
+ g_free (package_id);
+ g_strfreev (package_ids);
+ if (error != NULL)
+ g_error_free (error);
+ if (error_local != NULL)
+ g_error_free (error_local);
+ if (list != NULL)
+ g_object_unref (list);
+}
+
+/**
+ * gpk_dbus_task_set_status:
+ **/
+static gboolean
+gpk_dbus_task_set_status (GpkDbusTask *task, PkStatusEnum status)
+{
+ g_return_val_if_fail (GPK_IS_DBUS_TASK (task), FALSE);
+
+ /* do we force progress? */
+ if (!task->priv->show_progress) {
+ if (status == PK_STATUS_ENUM_DOWNLOAD_REPOSITORY ||
+ status == PK_STATUS_ENUM_DOWNLOAD_PACKAGELIST ||
+ status == PK_STATUS_ENUM_DOWNLOAD_FILELIST ||
+ status == PK_STATUS_ENUM_DOWNLOAD_CHANGELOG ||
+ status == PK_STATUS_ENUM_DOWNLOAD_GROUP ||
+ status == PK_STATUS_ENUM_DOWNLOAD_UPDATEINFO ||
+ status == PK_STATUS_ENUM_REFRESH_CACHE) {
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_PROGRESS, 0);
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-progress");
+ gpk_modal_dialog_present_with_time (task->priv->dialog, 0);
+ }
+ }
+
+ /* ignore */
+ if (!task->priv->show_progress) {
+ egg_warning ("not showing progress");
+ return FALSE;
+ }
+
+ /* set icon */
+ gpk_modal_dialog_set_image_status (task->priv->dialog, status);
+
+ /* set label */
+ gpk_modal_dialog_set_title (task->priv->dialog, gpk_status_enum_to_localised_text (status));
+
+ /* spin */
+ if (status == PK_STATUS_ENUM_WAIT)
+ gpk_modal_dialog_set_percentage (task->priv->dialog, PK_CLIENT_PERCENTAGE_INVALID);
+
+ /* do visual stuff when finished */
+ if (status == PK_STATUS_ENUM_FINISHED) {
+ /* make insensitive */
+ gpk_modal_dialog_set_allow_cancel (task->priv->dialog, FALSE);
+
+ /* stop spinning */
+ gpk_modal_dialog_set_percentage (task->priv->dialog, 100);
+ }
+ return TRUE;
+}
+
+/**
+ * gpk_dbus_task_progress_changed_cb:
+ **/
+static void
+gpk_dbus_task_progress_changed_cb (PkClient *client, guint percentage, guint subpercentage,
+ guint elapsed, guint remaining, GpkDbusTask *task)
+{
+ /* ignore */
+ gpk_modal_dialog_set_percentage (task->priv->dialog, percentage);
+ gpk_modal_dialog_set_remaining (task->priv->dialog, remaining);
+}
+
+/**
+ * gpk_dbus_task_status_changed_cb:
+ **/
+static void
+gpk_dbus_task_status_changed_cb (PkClient *client, PkStatusEnum status, GpkDbusTask *task)
+{
+ gpk_dbus_task_set_status (task, status);
+}
+
+/**
+ * gpk_dbus_task_error_code_cb:
+ **/
+static void
+gpk_dbus_task_error_code_cb (PkClient *client, PkErrorCodeEnum code, const gchar *details, GpkDbusTask *task)
+{
+ gboolean ret;
+ GError *error = NULL;
+ const gchar *title;
+ const gchar *message;
+ NotifyNotification *notification;
+ GtkWidget *widget;
+
+ g_return_if_fail (GPK_IS_DBUS_TASK (task));
+
+ /* save for later */
+ task->priv->last_exit_code = code;
+
+ /* have we handled? */
+ if (code == PK_ERROR_ENUM_GPG_FAILURE ||
+ code == PK_ERROR_ENUM_NO_LICENSE_AGREEMENT) {
+ egg_warning ("did not auth, but should be already handled");
+ return;
+ }
+
+ /* have we handled? */
+ if (code == PK_ERROR_ENUM_BAD_GPG_SIGNATURE ||
+ code == PK_ERROR_ENUM_MISSING_GPG_SIGNATURE) {
+ egg_warning ("will handled in finished");
+ return;
+ }
+
+ /* ignore some errors */
+ if (code == PK_ERROR_ENUM_PROCESS_KILL ||
+ code == PK_ERROR_ENUM_TRANSACTION_CANCELLED) {
+ egg_debug ("error ignored %s\n%s", pk_error_enum_to_text (code), details);
+ return;
+ }
+
+ egg_debug ("code was %s", pk_error_enum_to_text (code));
+
+ /* use a modal dialog if showing progress, else use libnotify */
+ title = gpk_error_enum_to_localised_text (code);
+ message = gpk_error_enum_to_localised_message (code);
+ if (task->priv->show_progress) {
+ widget = GTK_WIDGET (gpk_modal_dialog_get_window (task->priv->dialog));
+ gpk_error_dialog_modal (GTK_WINDOW (widget), title, message, details);
+ return;
+ }
+
+ /* save this globally */
+ g_free (task->priv->error_details);
+ task->priv->error_details = g_markup_escape_text (details, -1);
+
+ /* do the bubble */
+ notification = notify_notification_new (title, message, "help-browser", NULL);
+ notify_notification_set_timeout (notification, 15000);
+ notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
+ notify_notification_add_action (notification, "show-error-details",
+ /* TRANSLATORS: button: show details about the error */
+ _("Show details"), gpk_dbus_task_libnotify_cb, task, NULL);
+ ret = notify_notification_show (notification, &error);
+ if (!ret) {
+ egg_warning ("error: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+/**
+ * gpk_dbus_task_package_cb:
+ **/
+static void
+gpk_dbus_task_package_cb (PkClient *client, const PkPackageObj *obj, GpkDbusTask *task)
+{
+ gchar *text;
+ g_return_if_fail (GPK_IS_DBUS_TASK (task));
+
+ if (!task->priv->show_progress)
+ return;
+
+ text = gpk_package_id_format_twoline (obj->id, obj->summary);
+ gpk_modal_dialog_set_message (task->priv->dialog, text);
+ g_free (text);
+}
+
+/**
+ * gpk_dbus_task_allow_cancel_cb:
+ **/
+static void
+gpk_dbus_task_allow_cancel_cb (PkClient *client, gboolean allow_cancel, GpkDbusTask *task)
+{
+ gpk_modal_dialog_set_allow_cancel (task->priv->dialog, allow_cancel);
+}
+
+/**
+ * gpk_dbus_task_button_close_cb:
+ **/
+static void
+gpk_dbus_task_button_close_cb (GtkWidget *widget, GpkDbusTask *task)
+{
+ /* close, don't abort */
+ gpk_modal_dialog_close (task->priv->dialog);
+}
+
+/**
+ * gpk_dbus_task_button_cancel_cb:
+ **/
+static void
+gpk_dbus_task_button_cancel_cb (GtkWidget *widget, GpkDbusTask *task)
+{
+ gboolean ret;
+ GError *error = NULL;
+
+ /* we might have a transaction running */
+ ret = pk_client_cancel (task->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("failed to cancel client: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ ret = pk_client_cancel (task->priv->client_secondary, &error);
+ if (!ret) {
+ egg_warning ("failed to cancel client: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ return;
+}
+
+/**
+ * gpk_dbus_task_install_package_files_internal:
+ **/
+static void
+gpk_dbus_task_install_package_files_internal (GpkDbusTask *task, gboolean trusted)
+{
+ gboolean ret;
+ GError *error = NULL;
+ GError *error_local = NULL;
+ guint length;
+ const gchar *title;
+
+ /* FIXME: we need to move this into PkClient sooner or later */
+ task->priv->last_exit_code = PK_ERROR_ENUM_UNKNOWN;
+
+ /* reset */
+ ret = pk_client_reset (task->priv->client_primary, &error_local);
+ if (!ret) {
+ /* TRANSLATORS: this should never happen, low level failure */
+ gpk_dbus_task_error_msg (task, _("Failed to reset client to perform action"), error_local);
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "%s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* set timeout */
+ pk_client_set_timeout (task->priv->client_primary, task->priv->timeout, NULL);
+
+ /* install local file */
+ ret = pk_client_install_files (task->priv->client_primary, trusted, task->priv->files, &error_local);
+ if (!ret) {
+ length = g_strv_length (task->priv->files);
+ /* TRANSLATORS: title: detailed internal error why the file install failed */
+ title = ngettext ("Failed to install file", "Failed to install files", length);
+ gpk_dbus_task_error_msg (task, title, error_local);
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "%s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+out:
+ if (error != NULL)
+ g_error_free (error);
+ if (error_local != NULL)
+ g_error_free (error_local);
+}
+
+/**
+ * gpk_dbus_task_ptr_array_to_bullets:
+ *
+ * splits the strings up nicely
+ *
+ * Return value: a newly allocated string
+ **/
+static gchar *
+gpk_dbus_task_ptr_array_to_bullets (GPtrArray *array, const gchar *prefix)
+{
+ GString *string;
+ guint i;
+ gchar *text;
+
+ /* don't use a bullet for one item */
+ if (array->len == 1) {
+ if (prefix != NULL)
+ return g_strdup_printf ("%s\n\n%s", prefix, (const gchar *) g_ptr_array_index (array, 0));
+ else
+ return g_strdup (g_ptr_array_index (array, 0));
+ }
+
+ string = g_string_new (prefix);
+ if (prefix != NULL)
+ g_string_append (string, "\n\n");
+
+ /* prefix with bullet and suffix with newline */
+ for (i=0; i<array->len; i++) {
+ text = (gchar *) g_ptr_array_index (array, i);
+ g_string_append_printf (string, "â %s\n", text);
+ }
+
+ /* remove last \n */
+ g_string_set_size (string, string->len - 1);
+
+ text = g_string_free (string, FALSE);
+ return text;
+}
+
+/**
+ * gpk_dbus_task_install_package_files_get_user_temp:
+ *
+ * Return (and create if does not exist) a temporary directory
+ * that is writable only by the user, and readable by root.
+ *
+ * Return value: the temp directory, or %NULL for create error
+ **/
+static gchar *
+gpk_dbus_task_install_package_files_get_user_temp (GpkDbusTask *task, const gchar *subfolder, GError **error)
+{
+ GFile *file;
+ gboolean ret;
+ gchar *path = NULL;
+
+ /* build path in home folder */
+ path = g_build_filename (g_get_home_dir (), ".PackageKit", subfolder, NULL);
+
+ /* find if exists */
+ file = g_file_new_for_path (path);
+ ret = g_file_query_exists (file, NULL);
+ if (ret)
+ goto out;
+
+ /* create as does not exist */
+ ret = g_file_make_directory_with_parents (file, NULL, error);
+ g_object_unref (file);
+ if (!ret) {
+ /* return nothing.. */
+ g_free (path);
+ path = NULL;
+ }
+out:
+ return path;
+}
+
+GMainLoop *_loop = NULL;
+
+/**
+ * gpk_dbus_task_install_package_files_ready_callback:
+ **/
+static void
+gpk_dbus_task_install_package_files_ready_callback (GObject *source_object, GAsyncResult *res, GpkDbusTask *task)
+{
+ gboolean ret;
+ GError *error_local = NULL;
+
+ g_return_if_fail (GPK_IS_DBUS_TASK (task));
+
+ ret = g_file_copy_finish (G_FILE (source_object), res, &error_local);
+ if (!ret) {
+ egg_warning ("failed to copy file: %s", error_local->message);
+ g_error_free (error_local);
+ }
+
+ g_main_loop_quit (_loop);
+}
+
+/**
+ * gpk_dbus_task_install_package_files_progress_callback:
+ **/
+static void
+gpk_dbus_task_install_package_files_progress_callback (goffset current_num_bytes, goffset total_num_bytes, GpkDbusTask *task)
+{
+ guint percentage;
+ g_return_if_fail (GPK_IS_DBUS_TASK (task));
+ percentage = (current_num_bytes * 100) / total_num_bytes;
+ gpk_modal_dialog_set_percentage (task->priv->dialog, percentage);
+}
+
+/**
+ * gpk_dbus_task_install_package_files_copy_non_native:
+ *
+ * Copy the new file into a new file that can be read by packagekitd, and
+ * that can't be written into by other users.
+ *
+ * Return value: the new file path, or %NULL for copy error
+ **/
+static gchar *
+gpk_dbus_task_install_package_files_copy_non_native (GpkDbusTask *task, const gchar *filename, GError **error)
+{
+ GFile *file = NULL;
+ GFile *dest = NULL;
+ gchar *basename = NULL;
+ gchar *dest_path = NULL;
+ gchar *new_path = NULL;
+ gchar *cache_path = NULL;
+ GError *error_local = NULL;
+
+ /* create the non FUSE temp directory */
+ cache_path = gpk_dbus_task_install_package_files_get_user_temp (task, "native-cache", &error_local);
+ if (cache_path == NULL) {
+ *error = g_error_new (1, 0, "failed to create temp directory: %s", error_local->message);
+ g_error_free (error_local);
+ goto out;
+ }
+
+ /* get the final location */
+ file = g_file_new_for_path (filename);
+ basename = g_file_get_basename (file);
+ dest_path = g_build_filename (cache_path, basename, NULL);
+
+ /* copy the file */
+ dest = g_file_new_for_path (dest_path);
+ g_file_copy_async (file, dest, G_FILE_COPY_OVERWRITE, 0, NULL,
+ (GFileProgressCallback) gpk_dbus_task_install_package_files_progress_callback, task,
+ (GAsyncReadyCallback) gpk_dbus_task_install_package_files_ready_callback, task);
+ _loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (_loop);
+ g_main_loop_unref (_loop);
+
+ /* return the modified file item */
+ new_path = g_strdup (dest_path);
+
+out:
+ if (file != NULL)
+ g_object_unref (file);
+ if (dest != NULL)
+ g_object_unref (dest);
+ g_free (basename);
+ g_free (cache_path);
+ g_free (dest_path);
+ return new_path;
+}
+
+/**
+ * gpk_dbus_task_install_package_files_native_check:
+ *
+ * Allow the user to confirm the package copy to ~/.PackageKit/native-cache
+ * as we cannot access FUSE mounts as the root user.
+ *
+ * Return value: %TRUE if the method succeeded
+ **/
+static gboolean
+gpk_dbus_task_install_package_files_native_check (GpkDbusTask *task, GPtrArray *array, GError **error)
+{
+ guint i;
+ const gchar *data;
+ gchar *cache_path = NULL;
+ gchar *filename;
+ gboolean ret;
+ gboolean native;
+ GPtrArray *array_missing;
+ const gchar *message_part;
+ const gchar *title;
+ gchar *message;
+ GtkResponseType button;
+ GError *error_local = NULL;
+ GFile *file;
+
+ /* check if any files are non-native and need to be copied */
+ array_missing = g_ptr_array_new ();
+ for (i=0; i<array->len; i++) {
+ data = (const gchar *) g_ptr_array_index (array, i);
+ /* if file is non-native, it's on a FUSE mount (probably created by GVFS).
+ * See https://bugzilla.redhat.com/show_bug.cgi?id=456094 */
+ file = g_file_new_for_path (data);
+ native = g_file_is_native (file);
+ g_object_unref (file);
+ if (!native) {
+ egg_debug ("%s is non-native", data);
+ g_ptr_array_add (array_missing, g_strdup (data));
+ }
+ }
+
+ /* optional */
+ ret = gconf_client_get_bool (task->priv->gconf_client, GPK_CONF_SHOW_COPY_CONFIRM, NULL);
+ if (ret && array_missing->len > 0) {
+ /* TRANSLATORS: title: we have to copy the private files to a public location */
+ title = ngettext ("Do you want to copy this file?",
+ "Do you want to copy these files?", array_missing->len);
+ /* TRANSLATORS: message: explain to the user what we are doing */
+ message_part = ngettext ("This package file has to be copied from a private directory so it can be installed:",
+ "Several package files have to be copied from a private directory so they can be installed:",
+ array_missing->len);
+ message = gpk_dbus_task_ptr_array_to_bullets (array_missing, message_part);
+
+ /* show UI */
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_CONFIRM, 0);
+ gpk_modal_dialog_set_title (task->priv->dialog, title);
+ gpk_modal_dialog_set_message (task->priv->dialog, message);
+ gpk_modal_dialog_set_image (task->priv->dialog, "dialog-warning");
+ /* TRANSLATORS: button: copy file from one directory to another */
+ gpk_modal_dialog_set_action (task->priv->dialog, ngettext ("Copy file", "Copy files", array_missing->len));
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-installing-private-files");
+ g_free (message);
+
+ gpk_modal_dialog_present_with_time (task->priv->dialog, task->priv->timestamp);
+ button = gpk_modal_dialog_run (task->priv->dialog);
+ /* did we click no or exit the window? */
+ if (button != GTK_RESPONSE_OK) {
+ *error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_CANCELLED, "Aborted the copy");
+ ret = FALSE;
+ goto out;
+ }
+ }
+
+ /* setup UI */
+ if (array_missing->len > 0) {
+ /* TRANSLATORS: title: we are about to copy files, which may take a few seconds */
+ title = ngettext ("Copying file",
+ "Copying files", array_missing->len);
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_PROGRESS, 0);
+ gpk_modal_dialog_set_title (task->priv->dialog, title);
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-installing-private-files");
+ gpk_modal_dialog_present_with_time (task->priv->dialog, task->priv->timestamp);
+ }
+
+ /* now we have the okay to copy the files, do so */
+ ret = TRUE;
+ for (i=0; i<array->len; i++) {
+ data = (const gchar *) g_ptr_array_index (array, i);
+
+ /* check we are not on FUSE */
+ file = g_file_new_for_path (data);
+ native = g_file_is_native (file);
+ g_object_unref (file);
+ if (!native) {
+ /* copy the file */
+ filename = gpk_dbus_task_install_package_files_copy_non_native (task, data, &error_local);
+ if (filename == NULL) {
+ *error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_FAILED, "failed to copy file %s: %s", data, error_local->message);
+ ret = FALSE;
+ break;
+ }
+
+ /* show progress */
+ gpk_modal_dialog_set_message (task->priv->dialog, filename);
+
+ /* swap data in array */
+ g_free (array->pdata[i]);
+ array->pdata[i] = g_strdup (filename);
+ g_free (filename);
+ }
+ }
+
+ /* did we fail to copy the files */
+ if (!ret) {
+ /* TRANSLATORS: title: tell the user we failed */
+ title = ngettext ("The file could not be copied",
+ "The files could not be copied", array_missing->len);
+
+ /* show UI */
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, 0);
+ gpk_modal_dialog_set_title (task->priv->dialog, title);
+ gpk_modal_dialog_set_message (task->priv->dialog, error_local->message);
+ gpk_modal_dialog_present_with_time (task->priv->dialog, task->priv->timestamp);
+ gpk_modal_dialog_run (task->priv->dialog);
+ *error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_FAILED, "files not copied");
+ ret = FALSE;
+ g_error_free (error_local);
+ goto out;
+ }
+out:
+ g_free (cache_path);
+ g_ptr_array_foreach (array_missing, (GFunc) g_free, NULL);
+ g_ptr_array_free (array_missing, TRUE);
+ return ret;
+}
+
+/**
+ * gpk_dbus_task_install_package_files_verify:
+ *
+ * Allow the user to confirm the action
+ *
+ * Return value: %TRUE if the method succeeded
+ **/
+static gboolean
+gpk_dbus_task_install_package_files_verify (GpkDbusTask *task, GPtrArray *array, GError **error)
+{
+ GtkResponseType button;
+ const gchar *title;
+ gchar *message;
+ gboolean ret = TRUE;
+
+ /* TRANSLATORS: title: confirm the user want's to install a local file */
+ title = ngettext ("Do you want to install this file?",
+ "Do you want to install these files?", array->len);
+ message = gpk_dbus_task_ptr_array_to_bullets (array, NULL);
+
+ /* show UI */
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_CONFIRM, 0);
+ gpk_modal_dialog_set_title (task->priv->dialog, title);
+ gpk_modal_dialog_set_message (task->priv->dialog, message);
+ /* TRANSLATORS: title: installing local files */
+ gpk_modal_dialog_set_action (task->priv->dialog, _("Install"));
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-install-files");
+ gpk_modal_dialog_present_with_time (task->priv->dialog, task->priv->timestamp);
+ button = gpk_modal_dialog_run (task->priv->dialog);
+ g_free (message);
+
+ /* did we click no or exit the window? */
+ if (button != GTK_RESPONSE_OK) {
+ /* TRANSLATORS: title: the user cancelled the action */
+ title = ngettext ("The file was not installed",
+ "The files were not installed", array->len);
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, 0);
+ gpk_modal_dialog_set_title (task->priv->dialog, title);
+ gpk_modal_dialog_present_with_time (task->priv->dialog, task->priv->timestamp);
+ gpk_modal_dialog_run (task->priv->dialog);
+ *error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_CANCELLED, "Aborted");
+ ret = FALSE;
+ goto out;
+ }
+out:
+ return ret;
+}
+
+/**
+ * gpk_dbus_task_install_package_files_check_exists:
+ *
+ * Skip files that are not present
+ *
+ * Return value: %TRUE if the method succeeded
+ **/
+static gboolean
+gpk_dbus_task_install_package_files_check_exists (GpkDbusTask *task, GPtrArray *array, GError **error)
+{
+ guint i;
+ const gchar *data;
+ gboolean ret;
+ GPtrArray *array_missing;
+ const gchar *message_part;
+ const gchar *title;
+ gchar *message;
+
+ array_missing = g_ptr_array_new ();
+
+ /* find missing */
+ for (i=0; i<array->len; i++) {
+ data = (const gchar *) g_ptr_array_index (array, i);
+ ret = g_file_test (data, G_FILE_TEST_EXISTS);
+ if (!ret)
+ g_ptr_array_add (array_missing, g_strdup (data));
+ }
+
+ /* warn, set error and quit */
+ ret = TRUE;
+ if (array_missing->len > 0) {
+ /* TRANSLATORS: title: we couldn't find the file -- very hard to get this */
+ title = ngettext ("File was not found!",
+ "Files were not found!", array_missing->len);
+
+ /* TRANSLATORS: message: explain what went wrong */
+ message_part = ngettext ("The following file was not found:",
+ "The following files were not found:", array_missing->len);
+ message = gpk_dbus_task_ptr_array_to_bullets (array_missing, message_part);
+
+ /* show UI */
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, 0);
+ gpk_modal_dialog_set_title (task->priv->dialog, title);
+ gpk_modal_dialog_set_message (task->priv->dialog, message);
+ gpk_modal_dialog_present_with_time (task->priv->dialog, task->priv->timestamp);
+ gpk_modal_dialog_run (task->priv->dialog);
+
+ g_free (message);
+
+ ret = FALSE;
+ *error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_FAILED, "some files did not exist");
+ goto out;
+ }
+
+out:
+ g_ptr_array_foreach (array_missing, (GFunc) g_free, NULL);
+ g_ptr_array_free (array_missing, TRUE);
+ return ret;
+}
+
+/**
+ * gpk_dbus_task_confirm_action:
+ * @task: a valid #GpkDbusTask instance
+ **/
+static gboolean
+gpk_dbus_task_confirm_action (GpkDbusTask *task, const gchar *title, const gchar *message, const gchar *action)
+{
+ GtkResponseType button;
+
+ /* check the user wanted to call this method */
+ if (!task->priv->show_confirm_search)
+ return TRUE;
+
+ /* setup UI */
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_CONFIRM, 0);
+ gpk_modal_dialog_set_action (task->priv->dialog, action);
+
+ /* set icon */
+ if (task->priv->parent_icon_name != NULL)
+ gpk_modal_dialog_set_image (task->priv->dialog, task->priv->parent_icon_name);
+ else
+ gpk_modal_dialog_set_image (task->priv->dialog, "emblem-system");
+
+ gpk_modal_dialog_set_title (task->priv->dialog, title);
+ gpk_modal_dialog_set_message (task->priv->dialog, message);
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-application-confirm");
+ gpk_modal_dialog_present_with_time (task->priv->dialog, task->priv->timestamp);
+ button = gpk_modal_dialog_run (task->priv->dialog);
+
+ /* close, we're going to fail the method */
+ if (button != GTK_RESPONSE_OK) {
+ gpk_modal_dialog_close (task->priv->dialog);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * gpk_dbus_task_is_installed:
+ **/
+void
+gpk_dbus_task_is_installed (GpkDbusTask *task, const gchar *package_name)
+{
+ gboolean ret;
+ GError *error = NULL;
+ GError *error_local = NULL;
+ gchar **package_names = NULL;
+
+ task->priv->role = GPK_DBUS_TASK_ROLE_IS_INSTALLED;
+
+ /* reset */
+ ret = pk_client_reset (task->priv->client_primary, &error_local);
+ if (!ret) {
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "failed to reset: %s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* set timeout */
+ pk_client_set_timeout (task->priv->client_primary, task->priv->timeout, NULL);
+
+ /* get the package list for the installed packages */
+ package_names = g_strsplit (package_name, "|", 1);
+ egg_warning ("package_name=%s", package_name);
+ ret = pk_client_resolve (task->priv->client_primary, pk_bitfield_value (PK_FILTER_ENUM_INSTALLED), package_names, &error_local);
+ if (!ret) {
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "failed to get installed status: %s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* wait for async reply... */
+out:
+ g_strfreev (package_names);
+ if (error != NULL)
+ g_error_free (error);
+ if (error_local != NULL)
+ g_error_free (error_local);
+}
+
+/**
+ * gpk_dbus_task_search_file:
+ **/
+void
+gpk_dbus_task_search_file (GpkDbusTask *task, const gchar *search_file)
+{
+ gboolean ret;
+ GError *error = NULL;
+ GError *error_local = NULL;
+
+ task->priv->role = GPK_DBUS_TASK_ROLE_SEARCH_FILE;
+
+ /* reset */
+ ret = pk_client_reset (task->priv->client_primary, &error_local);
+ if (!ret) {
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "failed to reset: %s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* set timeout */
+ pk_client_set_timeout (task->priv->client_primary, task->priv->timeout, NULL);
+
+ /* get the package list for the installed packages */
+ egg_warning ("package_name=%s", search_file);
+ ret = pk_client_search_file (task->priv->client_primary, pk_bitfield_value (PK_FILTER_ENUM_INSTALLED), search_file, &error_local);
+ if (!ret) {
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "failed to get installed status: %s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* wait for async reply... */
+out:
+ if (error != NULL)
+ g_error_free (error);
+ if (error_local != NULL)
+ g_error_free (error_local);
+}
+
+/**
+ * gpk_dbus_task_install_package_files:
+ * @task: a valid #GpkDbusTask instance
+ * @file_rel: a file such as <literal>./hal-devel-0.10.0.rpm</literal>
+ * @error: a %GError to put the error code and message in, or %NULL
+ *
+ * Install a file locally, and get the deps from the repositories.
+ * This is useful for double clicking on a .rpm or .deb file.
+ *
+ * Return value: %TRUE if the method succeeded
+ **/
+void
+gpk_dbus_task_install_package_files (GpkDbusTask *task, gchar **files_rel)
+{
+ GError *error = NULL;
+ gboolean ret;
+ GPtrArray *array;
+// const gchar *title;
+
+ g_return_if_fail (GPK_IS_DBUS_TASK (task));
+ g_return_if_fail (files_rel != NULL);
+
+ array = pk_strv_to_ptr_array (files_rel);
+
+ /* check the user wanted to call this method */
+ if (task->priv->show_confirm_search) {
+ ret = gpk_dbus_task_install_package_files_verify (task, array, &error);
+ if (!ret) {
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+ }
+
+ /* check all files exist and are readable by the local user */
+ ret = gpk_dbus_task_install_package_files_check_exists (task, array, &error);
+ if (!ret) {
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* check all files exist and are readable by the local user */
+ ret = gpk_dbus_task_install_package_files_native_check (task, array, &error);
+ if (!ret) {
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_PROGRESS, 0);
+ /* TRANSLATORS: title: installing a local file */
+ gpk_modal_dialog_set_title (task->priv->dialog, ngettext ("Install local file", "Install local files", array->len));
+ if (task->priv->show_progress)
+ gpk_modal_dialog_present_with_time (task->priv->dialog, task->priv->timestamp);
+
+ task->priv->files = pk_ptr_array_to_strv (array);
+ gpk_dbus_task_install_package_files_internal (task, TRUE);
+out:
+ g_ptr_array_foreach (array, (GFunc) g_free, NULL);
+ g_ptr_array_free (array, TRUE);
+ if (error != NULL)
+ g_error_free (error);
+}
+
+/**
+ * gpk_dbus_task_install_package_names:
+ * @task: a valid #GpkDbusTask instance
+ * @package: a pakage name such as <literal>hal-info</literal>
+ * @error: a %GError to put the error code and message in, or %NULL
+ *
+ * Install a package of the newest and most correct version.
+ *
+ * Return value: %TRUE if the method succeeded
+ **/
+void
+gpk_dbus_task_install_package_names (GpkDbusTask *task, gchar **packages)
+{
+ gboolean ret;
+ GError *error = NULL;
+ GError *error_local = NULL;
+ gchar *message;
+ gchar *text;
+ guint len;
+ guint i;
+ GString *string;
+
+ g_return_if_fail (GPK_IS_DBUS_TASK (task));
+ g_return_if_fail (packages != NULL);
+
+ task->priv->role = GPK_DBUS_TASK_ROLE_INSTALL_PACKAGE_NAMES;
+
+ /* optional */
+ if (!task->priv->show_confirm_install) {
+ egg_debug ("skip confirm as not allowed to interact with user");
+ goto skip_checks;
+ }
+
+ string = g_string_new ("");
+ len = g_strv_length (packages);
+
+ /* don't use a bullet for one item */
+ if (len == 1) {
+ g_string_append_printf (string, "%s\n", packages[0]);
+ } else {
+ for (i=0; i<len; i++)
+ g_string_append_printf (string, "â %s\n", packages[i]);
+ }
+ /* display messagebox */
+ text = g_string_free (string, FALSE);
+
+ /* check user wanted operation */
+ message = g_strdup_printf ("%s\n\n%s\n%s",
+ /* TRANSLATORS: a program needs a package, for instance openoffice-clipart */
+ ngettext ("An additional package is required:", "Additional packages are required:", len),
+ text,
+ /* TRANSLATORS: ask the user if it's okay to search */
+ ngettext ("Do you want to search for and install this package now?", "Do you want to search for and install these packages now?", len));
+ g_free (text);
+
+ /* make title using application name */
+ if (task->priv->parent_title != NULL) {
+ /* TRANSLATORS: string is a program name, e.g. "Movie Player" */
+ text = g_strdup_printf (ngettext ("%s wants to install a package", "%s wants to install packages", len), task->priv->parent_title);
+ } else {
+ /* TRANSLATORS: a random program which we can't get the name wants to do something */
+ text = g_strdup (ngettext ("A program wants to install a package", "A program wants to install packages", len));
+ }
+
+ /* TRANSLATORS: button: confirm to search for packages */
+ ret = gpk_dbus_task_confirm_action (task, text, message, _("Install"));
+ g_free (text);
+ g_free (message);
+ if (!ret) {
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_CANCELLED, "did not agree to search");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+skip_checks:
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_PROGRESS, 0);
+ /* TRANSLATORS: title, searching */
+ gpk_modal_dialog_set_title (task->priv->dialog, _("Searching for packages"));
+ gpk_modal_dialog_set_image_status (task->priv->dialog, PK_STATUS_ENUM_WAIT);
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-finding-packages");
+ if (task->priv->show_progress)
+ gpk_modal_dialog_present (task->priv->dialog);
+
+ /* reset */
+ ret = pk_client_reset (task->priv->client_primary, &error_local);
+ if (!ret) {
+ /* TRANSLATORS: this is an internal error, and should not be seen */
+ gpk_dbus_task_error_msg (task, _("Failed to reset client"), error_local);
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "%s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* set timeout */
+ pk_client_set_timeout (task->priv->client_primary, task->priv->timeout, NULL);
+
+ /* find out if we can find a package */
+ ret = pk_client_resolve (task->priv->client_primary, PK_FILTER_ENUM_NONE, packages, &error_local);
+ if (!ret) {
+ /* TRANSLATORS: we failed to find the package, this shouldn't happen */
+ gpk_dbus_task_error_msg (task, _("Incorrect response from search"), error_local);
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "%s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+/*xxx*/
+ /* wait for async reply */
+out:
+ if (error != NULL)
+ g_error_free (error);
+ if (error_local != NULL)
+ g_error_free (error_local);
+}
+
+/**
+ * gpk_dbus_task_install_provide_files:
+ * @task: a valid #GpkDbusTask instance
+ * @full_path: a file path name such as <literal>/usr/sbin/packagekitd</literal>
+ * @error: a %GError to put the error code and message in, or %NULL
+ *
+ * Install a package which provides a file on the system.
+ *
+ * Return value: %TRUE if the method succeeded
+ **/
+void
+gpk_dbus_task_install_provide_files (GpkDbusTask *task, gchar **full_paths)
+{
+ gboolean ret;
+ GError *error = NULL;
+ GError *error_local = NULL;
+ guint len;
+ guint i;
+ gchar *text;
+ gchar *message;
+ GString *string;
+
+ g_return_if_fail (GPK_IS_DBUS_TASK (task));
+ g_return_if_fail (full_paths != NULL);
+
+ task->priv->role = GPK_DBUS_TASK_ROLE_INSTALL_PROVIDE_FILES;
+
+ /* optional */
+ if (!task->priv->show_confirm_search) {
+ egg_debug ("skip confirm as not allowed to interact with user");
+ goto skip_checks;
+ }
+
+ string = g_string_new ("");
+ len = g_strv_length (full_paths);
+
+ /* don't use a bullet for one item */
+ if (len == 1) {
+ g_string_append_printf (string, "%s\n", full_paths[0]);
+ } else {
+ for (i=0; i<len; i++)
+ g_string_append_printf (string, "â %s\n", full_paths[i]);
+ }
+ /* display messagebox */
+ text = g_string_free (string, FALSE);
+
+ /* check user wanted operation */
+ message = g_strdup_printf ("%s\n\n%s\n\n%s",
+ /* TRANSLATORS: a program wants to install a file, e.g. /lib/moo.so */
+ ngettext ("The following file is required:", "The following files are required:", len),
+ text,
+ /* TRANSLATORS: confirm with the user */
+ ngettext ("Do you want to search for this file now?", "Do you want to search for these files now:", len));
+
+ /* make title using application name */
+ if (task->priv->parent_title != NULL) {
+ /* TRANSLATORS: string is a program name, e.g. "Movie Player" */
+ text = g_strdup_printf (ngettext ("%s wants to install a file", "%s wants to install files", len), task->priv->parent_title);
+ } else {
+ /* TRANSLATORS: a random program which we can't get the name wants to do something */
+ text = g_strdup (ngettext ("A program wants to install a file", "A program wants to install files", len));
+ }
+
+ /* TRANSLATORS: button: confirm to search for packages */
+ ret = gpk_dbus_task_confirm_action (task, text, message, _("Install"));
+ g_free (text);
+ g_free (message);
+ if (!ret) {
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_CANCELLED, "did not agree to search");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+skip_checks:
+ /* TRANSLATORS: searching for the package that provides the file */
+ gpk_modal_dialog_set_title (task->priv->dialog, _("Searching for file"));
+ gpk_modal_dialog_set_image_status (task->priv->dialog, PK_STATUS_ENUM_WAIT);
+
+ /* reset */
+ ret = pk_client_reset (task->priv->client_primary, &error_local);
+ if (!ret) {
+ /* TRANSLATORS: this is an internal error, and should not be seen */
+ gpk_dbus_task_error_msg (task, _("Failed to reset client"), error_local);
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "%s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* set timeout */
+ pk_client_set_timeout (task->priv->client_primary, task->priv->timeout, NULL);
+
+ /* do search */
+ ret = pk_client_search_file (task->priv->client_primary, PK_FILTER_ENUM_NONE, full_paths[0], &error_local);
+ if (!ret) {
+ /* TRANSLATORS: we failed to find the package, this shouldn't happen */
+ gpk_dbus_task_error_msg (task, _("Failed to search for file"), error_local);
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "%s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* wait for async reply */
+out:
+ if (error != NULL)
+ g_error_free (error);
+ if (error_local != NULL)
+ g_error_free (error_local);
+}
+
+/**
+ * gpk_dbus_task_install_gstreamer_codec_part:
+ **/
+static PkPackageObj *
+gpk_dbus_task_install_gstreamer_codec_part (GpkDbusTask *task, const gchar *codec_name, const gchar *codec_desc, GError **error)
+{
+ PkPackageList *list = NULL;
+ gboolean ret;
+ PkPackageObj *new_obj = NULL;
+ const PkPackageObj *obj;
+ guint len;
+ gchar *title;
+
+ /* reset */
+ ret = pk_client_reset (task->priv->client_primary, error);
+ if (!ret)
+ return NULL;
+
+ /* set timeout */
+ pk_client_set_timeout (task->priv->client_primary, task->priv->timeout, NULL);
+
+ /* TRANSLATORS: title, searching for codecs */
+ title = g_strdup_printf (_("Searching for plugin: %s"), codec_name);
+ gpk_modal_dialog_set_message (task->priv->dialog, title);
+ g_free (title);
+
+ /* get codec packages, FIXME: synchronous! */
+ pk_client_set_synchronous (task->priv->client_primary, TRUE, NULL);
+ ret = pk_client_what_provides (task->priv->client_primary, pk_bitfield_value (PK_FILTER_ENUM_NOT_INSTALLED), PK_PROVIDES_ENUM_CODEC, codec_desc, error);
+ pk_client_set_synchronous (task->priv->client_primary, FALSE, NULL);
+ if (!ret)
+ return NULL;
+
+ list = pk_client_get_package_list (task->priv->client_primary);
+ len = pk_package_list_get_size (list);
+
+ /* found nothing? */
+ if (len == 0) {
+ *error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_NO_PACKAGES_FOUND, "failed to find: %s", codec_desc);
+ goto out;
+ }
+
+ /* gstreamer-ffmpeg and gstreamer-plugins-ugly both provide mp3 playback, choose one */
+ if (len > 1)
+ egg_warning ("choosing one of the provides as more than one match");
+
+ /* always use the first one */
+ obj = pk_package_list_get_obj (list, 0);
+ if (obj == NULL)
+ egg_error ("obj cannot be NULL");
+
+ /* copy the object */
+ new_obj = pk_package_obj_copy (obj);
+out:
+ if (list != NULL)
+ g_object_unref (list);
+ return new_obj;
+}
+
+/**
+ * gpk_dbus_task_install_gstreamer_resources_confirm:
+ **/
+static gboolean
+gpk_dbus_task_install_gstreamer_resources_confirm (GpkDbusTask *task, gchar **codec_names)
+{
+ guint i;
+ guint len;
+ gchar *text;
+ gchar *confirm_text;
+ gchar **parts;
+ gboolean ret;
+ GString *string;
+ const gchar *title;
+ const gchar *message;
+
+ len = g_strv_length (codec_names);
+ /* TRANSLATORS: title: we need a codec */
+ title = ngettext ("An additional plugin is required to play this content", "Additional plugins are required to play this content", len);
+ /* TRANSLATORS: we are listing the plugins in a box */
+ message = ngettext ("The following plugin is required:", "The following plugins are required:", len);
+
+ string = g_string_new ("");
+ g_string_append_printf (string, "%s\n%s\n\n", title, message);
+
+ /* don't use a bullet for one item */
+ if (len == 1) {
+ parts = g_strsplit (codec_names[0], "|", 2);
+ g_string_append_printf (string, "%s\n", parts[0]);
+ g_strfreev (parts);
+ } else {
+ for (i=0; i<len; i++) {
+ parts = g_strsplit (codec_names[i], "|", 2);
+ g_string_append_printf (string, "â %s\n", parts[0]);
+ g_strfreev (parts);
+ }
+ }
+
+ /* TRANSLATORS: ask for confirmation */
+ message = ngettext ("Do you want to search for this now?", "Do you want to search for these now?", len);
+ g_string_append_printf (string, "\n%s\n", message);
+
+ /* remove last \n */
+ g_string_set_size (string, string->len - 1);
+
+ /* display messagebox */
+ text = g_string_free (string, FALSE);
+
+ /* make title using application name */
+ if (task->priv->parent_title != NULL) {
+ /* TRANSLATORS: string is a program name, e.g. "Movie Player" */
+ confirm_text = g_strdup_printf (ngettext ("%s requires an additional plugin", "%s requires additional plugins", len), task->priv->parent_title);
+ } else {
+ /* TRANSLATORS: a random program which we can't get the name wants to do something */
+ confirm_text = g_strdup (ngettext ("A program requires an additional plugin", "A program requires additional plugins", len));
+ }
+
+ /* TRANSLATORS: button: confirm to search for packages */
+ ret = gpk_dbus_task_confirm_action (task, confirm_text, text, _("Search"));
+ g_free (confirm_text);
+ g_free (text);
+
+ return ret;
+}
+
+/**
+ * gpk_dbus_task_install_gstreamer_resources:
+ * @task: a valid #GpkDbusTask instance
+ * @codecs: a codec_type such as <literal>application/text</literal>
+ * @error: a %GError to put the error code and message in, or %NULL
+ *
+ * Install a application to handle a mime type
+ *
+ * Return value: %TRUE if the method succeeded
+ **/
+void
+gpk_dbus_task_install_gstreamer_resources (GpkDbusTask *task, gchar **codec_names)
+{
+ gboolean ret = TRUE;
+ GError *error = NULL;
+ GError *error_local = NULL;
+ guint i;
+ guint len;
+ PkPackageObj *obj_new;
+ gchar **parts;
+ GtkResponseType button;
+ gchar *info_url;
+ PkPackageList *list = NULL;
+ const gchar *title;
+ const gchar *message;
+
+ /* check it's not session wide banned in gconf */
+ ret = gconf_client_get_bool (task->priv->gconf_client, GPK_CONF_ENABLE_CODEC_HELPER, NULL);
+ if (!ret) {
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_FORBIDDEN, "not enabled in GConf : %s", GPK_CONF_ENABLE_CODEC_HELPER);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* optional */
+ if (!task->priv->show_confirm_search) {
+ egg_debug ("skip confirm as not allowed to interact with user");
+ goto skip_checks;
+ }
+
+ /* confirm */
+ ret = gpk_dbus_task_install_gstreamer_resources_confirm (task, codec_names);
+ if (!ret) {
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_CANCELLED, "did not agree to search");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+skip_checks:
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_PROGRESS, GPK_MODAL_DIALOG_PACKAGE_PADDING);
+ /* TRANSLATORS: search for codec */
+ gpk_modal_dialog_set_title (task->priv->dialog, _("Searching for plugins"));
+ gpk_modal_dialog_set_image_status (task->priv->dialog, PK_STATUS_ENUM_WAIT);
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-finding-packages");
+
+ /* setup the UI */
+ if (task->priv->show_progress)
+ gpk_modal_dialog_present (task->priv->dialog);
+
+ /* save the objects to download in a list */
+ list = pk_package_list_new ();
+
+ len = g_strv_length (codec_names);
+ for (i=0; i<len; i++) {
+ parts = g_strsplit (codec_names[i], "|", 2);
+ if (g_strv_length (parts) != 2) {
+ egg_warning ("invalid line '%s', expecting a | delimiter", codec_names[i]);
+ continue;
+ }
+ obj_new = gpk_dbus_task_install_gstreamer_codec_part (task, parts[0], parts[1], &error_local);
+ if (obj_new == NULL) {
+ if (task->priv->show_warning) {
+ info_url = gpk_vendor_get_not_found_url (task->priv->vendor, GPK_VENDOR_URL_TYPE_CODEC);
+ /* only show the "more info" button if there is a valid link */
+ if (info_url != NULL)
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, GPK_MODAL_DIALOG_BUTTON_ACTION);
+ else
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, 0);
+ /* TRANSLATORS: failed to search for codec */
+ gpk_modal_dialog_set_title (task->priv->dialog, _("Failed to search for plugin"));
+ /* TRANSLATORS: no software sources have the wanted codec */
+ gpk_modal_dialog_set_message (task->priv->dialog, _("Could not find plugin in any configured software source"));
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-package-not-found");
+
+ /* TRANSLATORS: button text */
+ gpk_modal_dialog_set_action (task->priv->dialog, _("More information"));
+ gpk_modal_dialog_present (task->priv->dialog);
+ button = gpk_modal_dialog_run (task->priv->dialog);
+ if (button == GTK_RESPONSE_OK)
+ gpk_gnome_open (info_url);
+ g_free (info_url);
+ }
+ error = g_error_new (GPK_DBUS_ERROR, error_local->code, "%s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+ pk_obj_list_add (PK_OBJ_LIST(list), obj_new);
+ pk_package_obj_free (obj_new);
+ g_strfreev (parts);
+ }
+
+ /* optional */
+ if (!task->priv->show_confirm_deps) {
+ egg_debug ("skip confirm as not allowed to interact with user");
+ goto skip_checks2;
+ }
+
+ title = ngettext ("Install the following plugin", "Install the following plugins", len);
+ message = ngettext ("Do you want to install this package now?", "Do you want to install these packages now?", len);
+
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_CONFIRM, GPK_MODAL_DIALOG_PACKAGE_LIST);
+ gpk_modal_dialog_set_package_list (task->priv->dialog, list);
+ gpk_modal_dialog_set_title (task->priv->dialog, title);
+ gpk_modal_dialog_set_message (task->priv->dialog, message);
+ gpk_modal_dialog_set_image (task->priv->dialog, "dialog-information");
+ /* TRANSLATORS: button: install codecs */
+ gpk_modal_dialog_set_action (task->priv->dialog, _("Install"));
+ gpk_modal_dialog_present_with_time (task->priv->dialog, task->priv->timestamp);
+ button = gpk_modal_dialog_run (task->priv->dialog);
+
+ /* close, we're going to fail the method */
+ if (button != GTK_RESPONSE_OK) {
+ gpk_modal_dialog_close (task->priv->dialog);
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_CANCELLED, "did not agree to download");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+skip_checks2:
+ /* install with deps */
+ task->priv->package_ids = pk_package_list_to_strv (list);
+ gpk_dbus_task_install_package_ids_dep_check (task);
+out:
+ if (list != NULL)
+ g_object_unref (list);
+ if (error != NULL)
+ g_error_free (error);
+ if (error_local != NULL)
+ g_error_free (error_local);
+}
+
+/**
+ * gpk_dbus_task_install_mime_types:
+ * @task: a valid #GpkDbusTask instance
+ * @mime_type: a mime_type such as <literal>application/text</literal>
+ * @error: a %GError to put the error code and message in, or %NULL
+ *
+ * Install a application to handle a mime type
+ *
+ * Return value: %TRUE if the method succeeded
+ **/
+void
+gpk_dbus_task_install_mime_types (GpkDbusTask *task, gchar **mime_types)
+{
+ gboolean ret;
+ GError *error = NULL;
+ GError *error_local = NULL;
+ guint len;
+ gchar *message;
+ gchar *text;
+
+ g_return_if_fail (GPK_IS_DBUS_TASK (task));
+ g_return_if_fail (mime_types != NULL);
+
+ task->priv->role = GPK_DBUS_TASK_ROLE_INSTALL_MIME_TYPES;
+
+ /* check it's not session wide banned in gconf */
+ ret = gconf_client_get_bool (task->priv->gconf_client, GPK_CONF_ENABLE_MIME_TYPE_HELPER, NULL);
+ if (!ret) {
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_FORBIDDEN, "not enabled in GConf : %s", GPK_CONF_ENABLE_MIME_TYPE_HELPER);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* optional */
+ if (!task->priv->show_confirm_search) {
+ egg_debug ("skip confirm as not allowed to interact with user");
+ goto skip_checks;
+ }
+
+ /* make sure the user wants to do action */
+ message = g_strdup_printf ("%s\n\n%s\n\n%s",
+ /* TRANSLATORS: message: mime type opener required */
+ _("An additional program is required to open this type of file:"),
+ mime_types[0],
+ /* TRANSLATORS: message: confirm with the user */
+ _("Do you want to search for a program to open this file type now?"));
+
+ /* hardcode for now as we only support one mime type at a time */
+ len = 1;
+
+ /* make title using application name */
+ if (task->priv->parent_title != NULL) {
+ /* TRANSLATORS: string is a program name, e.g. "Movie Player" */
+ text = g_strdup_printf (ngettext ("%s requires a new mime type", "%s requires new mime types", len), task->priv->parent_title);
+ } else {
+ /* TRANSLATORS: a random program which we can't get the name wants to do something */
+ text = g_strdup (ngettext ("A program requires a new mime type", "A program requires new mime types", len));
+ }
+
+ /* TRANSLATORS: button: confirm to search for packages */
+ ret = gpk_dbus_task_confirm_action (task, text, message, _("Search"));
+ g_free (text);
+ g_free (message);
+ if (!ret) {
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_CANCELLED, "did not agree to search");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+skip_checks:
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_PROGRESS, 0);
+ /* TRANSLATORS: title: searching for mime type handlers */
+ gpk_modal_dialog_set_title (task->priv->dialog, _("Searching for file handlers"));
+ gpk_modal_dialog_set_image_status (task->priv->dialog, PK_STATUS_ENUM_WAIT);
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-finding-packages");
+
+ /* setup the UI */
+ if (task->priv->show_progress)
+ gpk_modal_dialog_present (task->priv->dialog);
+
+ /* reset */
+ ret = pk_client_reset (task->priv->client_primary, &error_local);
+ if (!ret) {
+ /* TRANSLATORS: this is an internal error, and should not be seen */
+ gpk_dbus_task_error_msg (task, _("Failed to reset client"), error_local);
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "%s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* set timeout */
+ pk_client_set_timeout (task->priv->client_primary, task->priv->timeout, NULL);
+
+ /* action */
+ ret = pk_client_what_provides (task->priv->client_primary, 0,//pk_bitfield_value (PK_FILTER_ENUM_NOT_INSTALLED),
+ PK_PROVIDES_ENUM_MIMETYPE, mime_types[0], &error_local);
+ if (!ret) {
+ /* TRANSLATORS: we failed to find the package, this shouldn't happen */
+ gpk_dbus_task_error_msg (task, _("Failed to search for provides"), error_local);
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "%s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* wait for async reply */
+out:
+ if (error != NULL)
+ g_error_free (error);
+ if (error_local != NULL)
+ g_error_free (error_local);
+}
+
+/**
+ * gpk_dbus_task_font_tag_to_lang:
+ **/
+static gchar *
+gpk_dbus_task_font_tag_to_lang (const gchar *tag)
+{
+ gchar *lang = NULL;
+#if 0
+ *** We do not yet enable this code due to a few bugs in fontconfig ***
+ http://bugs.freedesktop.org/show_bug.cgi?id=18846 and
+ http://bugs.freedesktop.org/show_bug.cgi?id=18847
+
+ FcPattern *pat = NULL;
+ FcChar8 *fclang;
+ FcResult res;
+
+ /* parse the tag */
+ pat = FcNameParse ((FcChar8 *) tag);
+ if (pat == NULL) {
+ egg_warning ("cannot parse: '%s'", tag);
+ goto out;
+ }
+ FcPatternPrint (pat);
+ res = FcPatternGetString (pat, FC_LANG, 0, &fclang);
+ if (res != FcResultMatch) {
+ egg_warning ("failed to get string for: '%s': %i", tag, res);
+ goto out;
+ }
+ lang = g_strdup ((gchar *) fclang);
+out:
+ if (pat != NULL)
+ FcPatternDestroy (pat);
+#else
+ guint len;
+
+ /* verify we have enough to remove prefix */
+ len = strlen (tag);
+ if (len < 7)
+ goto out;
+ /* this is a bodge */
+ lang = g_strdup (&tag[6]);
+out:
+#endif
+ return lang;
+}
+
+
+/**
+ * gpk_dbus_task_font_tag_to_localised_name:
+ **/
+static gchar *
+gpk_dbus_task_font_tag_to_localised_name (GpkDbusTask *task, const gchar *tag)
+{
+ gchar *lang;
+ gchar *language = NULL;
+ gchar *name;
+
+ /* use fontconfig to get the language code */
+ lang = gpk_dbus_task_font_tag_to_lang (tag);
+ if (lang == NULL) {
+ /* TRANSLATORS: we could not parse the ISO639 code from the fontconfig tag name */
+ name = g_strdup_printf ("%s: %s", _("Language tag not parsed"), tag);
+ goto out;
+ }
+
+ /* convert to localisable name */
+ language = gpk_language_iso639_to_language (task->priv->language, lang);
+ if (language == NULL) {
+ /* TRANSLATORS: we could not find en_US string for ISO639 code */
+ name = g_strdup_printf ("%s: %s", _("Language code not matched"), lang);
+ goto out;
+ }
+
+ /* get translation, or return untranslated string */
+ name = g_strdup (dgettext("iso_639", language));
+ if (name == NULL)
+ name = g_strdup (language);
+out:
+ g_free (lang);
+ g_free (language);
+ return name;
+}
+
+/**
+ * gpk_dbus_task_install_fontconfig_resources:
+ * @task: a valid #GpkDbusTask instance
+ * @fonts: font description such as <literal>lang:fr</literal>
+ * @error: a %GError to put the error code and message in, or %NULL
+ *
+ * Install a application to handle a mime type
+ *
+ * Return value: %TRUE if the method succeeded
+ **/
+void
+gpk_dbus_task_install_fontconfig_resources (GpkDbusTask *task, gchar **fonts)
+{
+ gboolean ret;
+ PkPackageList *list = NULL;
+ PkPackageList *list_tmp = NULL;
+ GtkResponseType button;
+ gchar *info_url;
+ GError *error = NULL;
+ GError *error_local = NULL;
+ guint i;
+ guint len;
+ gchar *text;
+ gchar *message;
+ const gchar *title;
+ const gchar *title_part;
+ GString *string;
+
+ g_return_if_fail (GPK_IS_DBUS_TASK (task));
+ g_return_if_fail (fonts != NULL);
+
+ /* get number of fonts to install */
+ len = g_strv_length (fonts);
+
+ /* check it's not session wide banned in gconf */
+ ret = gconf_client_get_bool (task->priv->gconf_client, GPK_CONF_ENABLE_FONT_HELPER, NULL);
+ if (!ret) {
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_FORBIDDEN, "not enabled in GConf : %s", GPK_CONF_ENABLE_FONT_HELPER);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* optional */
+ if (!task->priv->show_confirm_search) {
+ egg_debug ("skip confirm as not allowed to interact with user");
+ goto skip_checks;
+ }
+
+ string = g_string_new ("");
+
+ /* don't use a bullet for one item */
+ if (len == 1) {
+ text = gpk_dbus_task_font_tag_to_localised_name (task, fonts[0]);
+ g_string_append_printf (string, "%s\n", text);
+ g_free (text);
+ } else {
+ for (i=0; i<len; i++) {
+ text = gpk_dbus_task_font_tag_to_localised_name (task, fonts[i]);
+ g_string_append_printf (string, "â %s\n", text);
+ g_free (text);
+ }
+ }
+ /* display messagebox */
+ text = g_string_free (string, FALSE);
+
+ /* TRANSLATORS: we need to download a new font package to display a document */
+ title = ngettext ("An additional font is required to view this document correctly.",
+ "Additional fonts are required to view this document correctly.", len);
+
+ /* TRANSLATORS: we need to download a new font package to display a document */
+ title_part = ngettext ("Do you want to search for a suitable package now?",
+ "Do you want to search for suitable packages now?", len);
+
+ /* check user wanted operation */
+ message = g_strdup_printf ("%s\n\n%s\n%s", title, text, title_part);
+ g_free (text);
+
+ /* make title using application name */
+ if (task->priv->parent_title != NULL) {
+ /* TRANSLATORS: string is a program name, e.g. "Movie Player" */
+ text = g_strdup_printf (ngettext ("%s wants to install a font", "%s wants to install fonts", len), task->priv->parent_title);
+ } else {
+ /* TRANSLATORS: a random program which we can't get the name wants to do something */
+ text = g_strdup (ngettext ("A program wants to install a font", "A program wants to install fonts", len));
+ }
+
+ /* TRANSLATORS: button: confirm to search for packages */
+ ret = gpk_dbus_task_confirm_action (task, text, message, _("Search"));
+ g_free (text);
+ g_free (message);
+ if (!ret) {
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_CANCELLED, "did not agree to search");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+skip_checks:
+ /* TRANSLATORS: title to show when searching for font files */
+ title = ngettext ("Searching for font", "Searching for fonts", len);
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_PROGRESS, 0);
+ gpk_modal_dialog_set_title (task->priv->dialog, title);
+ gpk_modal_dialog_set_image_status (task->priv->dialog, PK_STATUS_ENUM_WAIT);
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-finding-packages");
+
+ /* setup the UI */
+ if (task->priv->show_progress)
+ gpk_modal_dialog_present (task->priv->dialog);
+
+ /* do each one */
+ list = pk_package_list_new ();
+ for (i=0; i<len; i++) {
+
+ /* reset */
+ ret = pk_client_reset (task->priv->client_primary, &error_local);
+ if (!ret) {
+ /* TRANSLATORS: this is an internal error, and should not be seen */
+ gpk_dbus_task_error_msg (task, _("Failed to reset client"), error_local);
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "%s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* set timeout */
+ pk_client_set_timeout (task->priv->client_primary, task->priv->timeout, NULL);
+
+ /* action: FIXME: synchronous */
+ pk_client_set_synchronous (task->priv->client_primary, TRUE, NULL);
+ ret = pk_client_what_provides (task->priv->client_primary, pk_bitfield_value (PK_FILTER_ENUM_NOT_INSTALLED),
+ PK_PROVIDES_ENUM_FONT, fonts[i], &error_local);
+ pk_client_set_synchronous (task->priv->client_primary, FALSE, NULL);
+ if (!ret) {
+ /* TRANSLATORS: we failed to find the package, this shouldn't happen */
+ gpk_dbus_task_error_msg (task, _("Failed to search for provides"), error_local);
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "%s", error_local->message);
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* add to main list */
+ list_tmp = pk_client_get_package_list (task->priv->client_primary);
+ pk_obj_list_add_list (PK_OBJ_LIST (list), PK_OBJ_LIST (list_tmp));
+ g_object_unref (list_tmp);
+ }
+
+ /* found nothing? */
+ len = pk_package_list_get_size (list);
+ if (len == 0) {
+ if (task->priv->show_warning) {
+ info_url = gpk_vendor_get_not_found_url (task->priv->vendor, GPK_VENDOR_URL_TYPE_FONT);
+ /* TRANSLATORS: title: cannot find in sources */
+ title = ngettext ("Failed to find font", "Failed to find fonts", len);
+ /* only show the "more info" button if there is a valid link */
+ if (info_url != NULL)
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, GPK_MODAL_DIALOG_BUTTON_ACTION);
+ else
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, 0);
+ gpk_modal_dialog_set_title (task->priv->dialog, title);
+ /* TRANSLATORS: message: tell the user we suck */
+ gpk_modal_dialog_set_message (task->priv->dialog, _("No new fonts can be found for this document"));
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-package-not-found");
+ /* TRANSLATORS: button: show the user a button to get more help finding stuff */
+ gpk_modal_dialog_set_action (task->priv->dialog, _("More information"));
+ gpk_modal_dialog_present (task->priv->dialog);
+ button = gpk_modal_dialog_run (task->priv->dialog);
+ if (button == GTK_RESPONSE_OK)
+ gpk_gnome_open (info_url);
+ g_free (info_url);
+ }
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_NO_PACKAGES_FOUND, "failed to find font");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* optional */
+ if (!task->priv->show_confirm_deps) {
+ egg_debug ("skip confirm as not allowed to interact with user");
+ goto skip_checks2;
+ }
+
+ /* TRANSLATORS: title: show a list of fonts */
+ title = ngettext ("Do you want to install this package now?", "Do you want to install these packages now?", len);
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_CONFIRM, GPK_MODAL_DIALOG_PACKAGE_LIST);
+ gpk_modal_dialog_set_package_list (task->priv->dialog, list);
+ gpk_modal_dialog_set_title (task->priv->dialog, title);
+ gpk_modal_dialog_set_message (task->priv->dialog, title);
+ gpk_modal_dialog_set_image (task->priv->dialog, "dialog-information");
+ /* TRANSLATORS: button: install a font */
+ gpk_modal_dialog_set_action (task->priv->dialog, _("Install"));
+ gpk_modal_dialog_present_with_time (task->priv->dialog, task->priv->timestamp);
+ button = gpk_modal_dialog_run (task->priv->dialog);
+
+ /* close, we're going to fail the method */
+ if (button != GTK_RESPONSE_OK) {
+ gpk_modal_dialog_close (task->priv->dialog);
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_CANCELLED, "did not agree to download");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+skip_checks2:
+ /* convert to list of package id's */
+ task->priv->package_ids = pk_package_list_to_strv (list);
+ gpk_dbus_task_install_package_ids_dep_check (task);
+
+out:
+ if (error != NULL)
+ g_error_free (error);
+ if (error_local != NULL)
+ g_error_free (error_local);
+ if (list != NULL)
+ g_object_unref (list);
+}
+
+/**
+ * gpk_dbus_task_catalog_progress_cb:
+ **/
+static void
+gpk_dbus_task_catalog_progress_cb (PkCatalog *catalog, PkCatalogProgress mode, const gchar *text, GpkDbusTask *task)
+{
+ gchar *message = NULL;
+
+ g_return_if_fail (GPK_IS_DBUS_TASK (task));
+
+ if (mode == PK_CATALOG_PROGRESS_PACKAGES) {
+ /* TRANSLATORS: finding the package names for a catalog */
+ message = g_strdup_printf (_("Finding package name: %s"), text);
+ } else if (mode == PK_CATALOG_PROGRESS_FILES) {
+ /* TRANSLATORS: finding a package for a file for a catalog */
+ message = g_strdup_printf (_("Finding file name: %s"), text);
+ } else if (mode == PK_CATALOG_PROGRESS_PROVIDES) {
+ /* TRANSLATORS: finding a package which can provide a virtual provide */
+ message = g_strdup_printf (_("Finding a package to provide: %s"), text);
+ }
+ gpk_dbus_task_set_status (task, PK_STATUS_ENUM_QUERY);
+ gpk_modal_dialog_set_message (task->priv->dialog, message);
+ g_free (message);
+}
+
+/**
+ * gpk_dbus_task_install_catalogs:
+ **/
+void
+gpk_dbus_task_install_catalogs (GpkDbusTask *task, gchar **filenames)
+{
+ GError *error = NULL;
+ GtkResponseType button;
+ gchar *message;
+ const gchar *title;
+ const PkPackageObj *obj;
+ PkPackageList *list = NULL;
+ PkCatalog *catalog;
+ GString *string;
+ gchar *text;
+ guint len;
+ guint i;
+
+ len = g_strv_length (filenames);
+
+ /* optional */
+ if (!task->priv->show_confirm_search) {
+ egg_debug ("skip confirm as not allowed to interact with user");
+ goto skip_checks;
+ }
+
+ /* TRANSLATORS: title to install package catalogs */
+ title = ngettext ("Do you want to install this catalog?",
+ "Do you want to install these catalogs?", len);
+ message = g_strjoinv ("\n", filenames);
+
+ /* show UI */
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_CONFIRM, 0);
+ gpk_modal_dialog_set_title (task->priv->dialog, title);
+ gpk_modal_dialog_set_message (task->priv->dialog, message);
+ /* TRANSLATORS: button: install catalog */
+ gpk_modal_dialog_set_action (task->priv->dialog, _("Install"));
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-install-catalogs");
+ gpk_modal_dialog_present_with_time (task->priv->dialog, task->priv->timestamp);
+ button = gpk_modal_dialog_run (task->priv->dialog);
+ g_free (message);
+
+ /* did we click no or exit the window? */
+ if (button != GTK_RESPONSE_OK) {
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_CANCELLED, "did not agree to install");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+skip_checks:
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_PROGRESS, 0);
+ /* TRANSLATORS: title: install package catalogs, that is, instructions for installing */
+ gpk_modal_dialog_set_title (task->priv->dialog, _("Install catalogs"));
+ gpk_dbus_task_set_status (task, PK_STATUS_ENUM_WAIT);
+
+ /* setup the UI */
+ if (task->priv->show_progress)
+ gpk_modal_dialog_present (task->priv->dialog);
+
+ /* get files to be installed */
+ catalog = pk_catalog_new ();
+ g_signal_connect (catalog, "progress", G_CALLBACK (gpk_dbus_task_catalog_progress_cb), task);
+ list = pk_catalog_process_files (catalog, filenames);
+ g_object_unref (catalog);
+
+ /* nothing to do? */
+ len = pk_package_list_get_size (list);
+ if (len == 0) {
+ /* show UI */
+ if (task->priv->show_warning) {
+ /* TRANSLATORS: title: we've already got all these packages installed */
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_WARNING, 0);
+ gpk_modal_dialog_set_title (task->priv->dialog, _("No packages need to be installed"));
+ gpk_modal_dialog_set_help_id (task->priv->dialog, "dialog-catalog-none-required");
+ gpk_modal_dialog_present_with_time (task->priv->dialog, task->priv->timestamp);
+ gpk_modal_dialog_run (task->priv->dialog);
+ }
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_FAILED, "No packages need to be installed");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+ /* optional */
+ if (!task->priv->show_confirm_deps) {
+ egg_debug ("skip confirm as not allowed to interact with user");
+ goto skip_checks2;
+ }
+
+ /* TRANSLATORS: display a list of packages to install */
+ string = g_string_new (_("The following packages are marked to be installed from the catalog:"));
+ g_string_append (string, "\n\n");
+
+ /* process package list */
+ for (i=0; i<len; i++) {
+ obj = pk_package_list_get_obj (list, i);
+ text = gpk_package_id_format_oneline (obj->id, obj->summary);
+ g_string_append_printf (string, "%s\n", text);
+ g_free (text);
+ }
+ /* remove last \n */
+ g_string_set_size (string, string->len - 1);
+
+ /* display messagebox */
+ text = g_string_free (string, FALSE);
+
+ gpk_modal_dialog_setup (task->priv->dialog, GPK_MODAL_DIALOG_PAGE_CONFIRM, 0);
+ /* TRANSLATORS: title: allow user to confirm */
+ gpk_modal_dialog_set_title (task->priv->dialog, _("Install packages in catalog?"));
+ gpk_modal_dialog_set_message (task->priv->dialog, text);
+ gpk_modal_dialog_set_image (task->priv->dialog, "dialog-question");
+ /* TRANSLATORS: button: install packages in catalog */
+ gpk_modal_dialog_set_action (task->priv->dialog, _("Install"));
+ gpk_modal_dialog_present_with_time (task->priv->dialog, task->priv->timestamp);
+ button = gpk_modal_dialog_run (task->priv->dialog);
+
+ g_free (text);
+
+ /* did we click no or exit the window? */
+ if (button != GTK_RESPONSE_OK) {
+ error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_CANCELLED, "Action was cancelled");
+ dbus_g_method_return_error (task->priv->context, error);
+ goto out;
+ }
+
+skip_checks2:
+ /* convert to list of package id's */
+ task->priv->package_ids = pk_package_list_to_strv (list);
+ gpk_dbus_task_install_package_ids_dep_check (task);
+
+out:
+ if (error != NULL)
+ g_error_free (error);
+ if (list != NULL)
+ g_object_unref (list);
+}
+
+/**
+ * gpk_dbus_task_get_package_for_exec:
+ **/
+static gchar *
+gpk_dbus_task_get_package_for_exec (GpkDbusTask *task, const gchar *exec)
+{
+ gchar *package = NULL;
+ gboolean ret;
+ GError *error = NULL;
+ guint length;
+ PkPackageList *list = NULL;
+ const PkPackageObj *obj;
+
+ /* reset dbus_task */
+ ret = pk_client_reset (task->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("failed to reset client: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* set timeout */
+ pk_client_set_timeout (task->priv->client_primary, task->priv->timeout, NULL);
+
+ /* find the package name */
+ pk_client_set_synchronous (task->priv->client_primary, TRUE, NULL);
+ ret = pk_client_search_file (task->priv->client_primary, pk_bitfield_value (PK_FILTER_ENUM_INSTALLED), exec, &error);
+ pk_client_set_synchronous (task->priv->client_primary, FALSE, NULL);
+ if (!ret) {
+ egg_warning ("failed to search file: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* get the list of packages */
+ list = pk_client_get_package_list (task->priv->client_primary);
+ length = pk_package_list_get_size (list);
+
+ /* nothing found */
+ if (length == 0) {
+ egg_debug ("cannot find installed package that provides : %s", exec);
+ goto out;
+ }
+
+ /* check we have one */
+ if (length != 1)
+ egg_warning ("not one return, using first");
+
+ /* copy name */
+ obj = pk_package_list_get_obj (list, 0);
+ package = g_strdup (obj->id->name);
+ egg_debug ("got package %s", package);
+
+out:
+ /* use the exec name if we can't find an installed package */
+ if (list != NULL)
+ g_object_unref (list);
+ return package;
+}
+
+/**
+ * gpk_dbus_task_path_is_trusted:
+ **/
+static gboolean
+gpk_dbus_task_path_is_trusted (const gchar *exec)
+{
+ /* special case the plugin helper -- it's trusted */
+ if (egg_strequal (exec, "/usr/libexec/gst-install-plugins-helper") ||
+ egg_strequal (exec, "/usr/libexec/pk-gstreamer-install"))
+ return TRUE;
+ return FALSE;
+}
+
+/**
+ * gpk_dbus_task_set_exec:
+ *
+ * This sets the package name of the application that is trying to install
+ * software, e.g. "totem" and is used for the PkDesktop lookup to provide
+ * a translated name and icon.
+ **/
+gboolean
+gpk_dbus_task_set_exec (GpkDbusTask *task, const gchar *exec)
+{
+ GpkX11 *x11;
+ gchar *package = NULL;
+
+ g_return_val_if_fail (GPK_IS_DBUS_TASK (task), FALSE);
+
+ /* old values invalid */
+ g_free (task->priv->parent_title);
+ g_free (task->priv->parent_icon_name);
+ task->priv->parent_title = NULL;
+ task->priv->parent_icon_name = NULL;
+
+ /* is the binary trusted, i.e. can we probe it's window properties */
+ if (gpk_dbus_task_path_is_trusted (exec)) {
+ egg_debug ("using application window properties");
+ /* get from window properties */
+ x11 = gpk_x11_new ();
+ gpk_x11_set_window (x11, task->priv->parent_window);
+ task->priv->parent_title = gpk_x11_get_title (x11);
+ g_object_unref (x11);
+ goto out;
+ }
+
+ /* get from installed database */
+ package = gpk_dbus_task_get_package_for_exec (task, exec);
+ egg_debug ("got package %s", package);
+
+ /* try to get from PkDesktop */
+ if (package != NULL) {
+ task->priv->parent_title = gpk_desktop_guess_localised_name (task->priv->desktop, package);
+ task->priv->parent_icon_name = gpk_desktop_guess_icon_name (task->priv->desktop, package);
+ /* fallback to package name */
+ if (task->priv->parent_title == NULL) {
+ egg_debug ("did not get localised description for %s", package);
+ task->priv->parent_title = g_strdup (package);
+ }
+ }
+
+ /* fallback to exec - eugh... */
+ if (task->priv->parent_title == NULL) {
+ egg_debug ("did not get package for %s, using exec basename", package);
+ task->priv->parent_title = g_path_get_basename (exec);
+ }
+out:
+ g_free (package);
+ egg_debug ("got name=%s, icon=%s", task->priv->parent_title, task->priv->parent_icon_name);
+ return TRUE;
+}
+
+/**
+ * gpk_dbus_task_class_init:
+ * @klass: The #GpkDbusTaskClass
+ **/
+static void
+gpk_dbus_task_class_init (GpkDbusTaskClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gpk_dbus_task_finalize;
+ g_type_class_add_private (klass, sizeof (GpkDbusTaskPrivate));
+}
+
+/**
+ * gpk_dbus_task_init:
+ * @task: a valid #GpkDbusTask instance
+ **/
+static void
+gpk_dbus_task_init (GpkDbusTask *task)
+{
+ gboolean ret;
+ GtkWindow *main_window;
+
+ task->priv = GPK_DBUS_TASK_GET_PRIVATE (task);
+
+ task->priv->package_ids = NULL;
+ task->priv->files = NULL;
+ task->priv->parent_window = NULL;
+ task->priv->parent_title = NULL;
+ task->priv->parent_icon_name = NULL;
+ task->priv->error_details = NULL;
+ task->priv->context = NULL;
+ task->priv->exit = PK_EXIT_ENUM_FAILED;
+ task->priv->show_confirm_search = TRUE;
+ task->priv->show_confirm_deps = TRUE;
+ task->priv->show_confirm_install = TRUE;
+ task->priv->show_progress = TRUE;
+ task->priv->show_finished = TRUE;
+ task->priv->show_warning = TRUE;
+ task->priv->timestamp = 0;
+ task->priv->timeout = -1;
+ task->priv->last_exit_code = PK_ERROR_ENUM_UNKNOWN;
+ task->priv->role = GPK_DBUS_TASK_ROLE_UNKNOWN;
+
+ /* add application specific icons to search path */
+ gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
+ GPK_DATA G_DIR_SEPARATOR_S "icons");
+
+ /* only initialise if the application didn't do it before */
+ if (!notify_is_initted ())
+ notify_init ("gpk-dbus_task");
+
+ task->priv->vendor = gpk_vendor_new ();
+ task->priv->dialog = gpk_modal_dialog_new ();
+ main_window = gpk_modal_dialog_get_window (task->priv->dialog);
+ gpk_modal_dialog_set_window_icon (task->priv->dialog, "pk-package-installed");
+ g_signal_connect (task->priv->dialog, "cancel",
+ G_CALLBACK (gpk_dbus_task_button_cancel_cb), task);
+ g_signal_connect (task->priv->dialog, "close",
+ G_CALLBACK (gpk_dbus_task_button_close_cb), task);
+
+ /* helpers */
+ task->priv->helper_repo_signature = gpk_helper_repo_signature_new ();
+ g_signal_connect (task->priv->helper_repo_signature, "event", G_CALLBACK (gpk_dbus_task_repo_signature_event_cb), task);
+ gpk_helper_repo_signature_set_parent (task->priv->helper_repo_signature, main_window);
+
+ task->priv->helper_eula = gpk_helper_eula_new ();
+ g_signal_connect (task->priv->helper_eula, "event", G_CALLBACK (gpk_dbus_task_eula_event_cb), task);
+ gpk_helper_eula_set_parent (task->priv->helper_eula, main_window);
+
+ task->priv->helper_run = gpk_helper_run_new ();
+ gpk_helper_run_set_parent (task->priv->helper_run, main_window);
+
+ task->priv->helper_untrusted = gpk_helper_untrusted_new ();
+ g_signal_connect (task->priv->helper_untrusted, "event", G_CALLBACK (gpk_dbus_task_untrusted_event_cb), task);
+ gpk_helper_untrusted_set_parent (task->priv->helper_untrusted, main_window);
+
+ task->priv->helper_chooser = gpk_helper_chooser_new ();
+ g_signal_connect (task->priv->helper_chooser, "event", G_CALLBACK (gpk_dbus_task_chooser_event_cb), task);
+ gpk_helper_chooser_set_parent (task->priv->helper_chooser, main_window);
+
+ /* map ISO639 to language names */
+ task->priv->language = gpk_language_new ();
+ gpk_language_populate (task->priv->language, NULL);
+
+ /* use gconf for session settings */
+ task->priv->gconf_client = gconf_client_get_default ();
+
+ /* get actions */
+ task->priv->control = pk_control_new ();
+ task->priv->roles = pk_control_get_actions (task->priv->control, NULL);
+
+ task->priv->client_primary = pk_client_new ();
+ pk_client_set_use_buffer (task->priv->client_primary, TRUE, NULL);
+ g_signal_connect (task->priv->client_primary, "finished",
+ G_CALLBACK (gpk_dbus_task_finished_cb), task);
+ g_signal_connect (task->priv->client_primary, "progress-changed",
+ G_CALLBACK (gpk_dbus_task_progress_changed_cb), task);
+ g_signal_connect (task->priv->client_primary, "status-changed",
+ G_CALLBACK (gpk_dbus_task_status_changed_cb), task);
+ g_signal_connect (task->priv->client_primary, "error-code",
+ G_CALLBACK (gpk_dbus_task_error_code_cb), task);
+ g_signal_connect (task->priv->client_primary, "package",
+ G_CALLBACK (gpk_dbus_task_package_cb), task);
+ g_signal_connect (task->priv->client_primary, "allow-cancel",
+ G_CALLBACK (gpk_dbus_task_allow_cancel_cb), task);
+ g_signal_connect (task->priv->client_primary, "repo-signature-required",
+ G_CALLBACK (gpk_dbus_task_repo_signature_required_cb), task);
+ g_signal_connect (task->priv->client_primary, "eula-required",
+ G_CALLBACK (gpk_dbus_task_eula_required_cb), task);
+
+ /* this is asynchronous, else we get into livelock */
+ task->priv->client_secondary = pk_client_new ();
+ g_signal_connect (task->priv->client_secondary, "finished",
+ G_CALLBACK (gpk_dbus_task_finished_cb), task);
+ g_signal_connect (task->priv->client_secondary, "error-code",
+ G_CALLBACK (gpk_dbus_task_error_code_cb), task);
+ g_signal_connect (task->priv->client_secondary, "status-changed",
+ G_CALLBACK (gpk_dbus_task_status_changed_cb), task);
+
+ /* used for icons and translations */
+ task->priv->desktop = pk_desktop_new ();
+ ret = pk_desktop_open_database (task->priv->desktop, NULL);
+ if (!ret)
+ egg_warning ("failed to open desktop database");
+}
+
+/**
+ * gpk_dbus_task_finalize:
+ * @object: The object to finalize
+ **/
+static void
+gpk_dbus_task_finalize (GObject *object)
+{
+ GpkDbusTask *task;
+
+ g_return_if_fail (GPK_IS_DBUS_TASK (object));
+
+ task = GPK_DBUS_TASK (object);
+ g_return_if_fail (task->priv != NULL);
+
+ g_free (task->priv->parent_title);
+ g_free (task->priv->parent_icon_name);
+ g_free (task->priv->error_details);
+ g_strfreev (task->priv->files);
+ g_strfreev (task->priv->package_ids);
+ g_object_unref (task->priv->client_primary);
+ g_object_unref (task->priv->client_secondary);
+ g_object_unref (task->priv->control);
+ g_object_unref (task->priv->desktop);
+ g_object_unref (task->priv->gconf_client);
+ g_object_unref (task->priv->dialog);
+ g_object_unref (task->priv->vendor);
+ g_object_unref (task->priv->language);
+ g_object_unref (task->priv->helper_eula);
+ g_object_unref (task->priv->helper_run);
+ g_object_unref (task->priv->helper_untrusted);
+ g_object_unref (task->priv->helper_chooser);
+ g_object_unref (task->priv->helper_repo_signature);
+
+ G_OBJECT_CLASS (gpk_dbus_task_parent_class)->finalize (object);
+}
+
+/**
+ * gpk_dbus_task_new:
+ *
+ * PkClient is a nice GObject wrapper for gnome-packagekit and makes installing software easy
+ *
+ * Return value: A new %GpkDbusTask instance
+ **/
+GpkDbusTask *
+gpk_dbus_task_new (void)
+{
+ GpkDbusTask *task;
+ task = g_object_new (GPK_TYPE_DBUS_TASK, NULL);
+ return GPK_DBUS_TASK (task);
+}
+
+/***************************************************************************
+ *** MAKE CHECK TESTS ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+gpk_dbus_task_test (gpointer data)
+{
+ EggTest *test = (EggTest *) data;
+ GpkDbusTask *task;
+ gchar *lang;
+ gchar *language;
+ gchar *package;
+ gboolean ret;
+#if 0
+ const gchar *fonts[] = { ":lang=mn", NULL };
+ GError *error;
+#endif
+
+ if (egg_test_start (test, "GpkChooser") == FALSE)
+ return;
+
+ /************************************************************/
+ egg_test_title (test, "get GpkDbusTask object");
+ task = gpk_dbus_task_new ();
+ if (task != NULL)
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, NULL);
+
+ /************************************************************/
+ egg_test_title (test, "convert tag to lang");
+ lang = gpk_dbus_task_font_tag_to_lang (":lang=mn");
+ if (egg_strequal (lang, "mn"))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "lang '%s'", lang);
+ g_free (lang);
+
+ /************************************************************/
+ egg_test_title (test, "convert tag to language");
+ language = gpk_dbus_task_font_tag_to_localised_name (task, ":lang=mn");
+ if (egg_strequal (language, "Mongolian"))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "language '%s'", language);
+ g_free (language);
+
+ /************************************************************/
+ egg_test_title (test, "test trusted path");
+ ret = gpk_dbus_task_path_is_trusted ("/usr/libexec/gst-install-plugins-helper");
+ if (ret)
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed to identify trusted");
+
+ /************************************************************/
+ egg_test_title (test, "test trusted path");
+ ret = gpk_dbus_task_path_is_trusted ("/usr/bin/totem");
+ if (!ret)
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "identify untrusted as trusted!");
+
+ /************************************************************/
+ egg_test_title (test, "get package for exec");
+ package = gpk_dbus_task_get_package_for_exec (task, "/usr/bin/totem");
+ if (egg_strequal (package, "totem"))
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "package '%s'", package);
+ g_free (package);
+
+ /************************************************************/
+ egg_test_title (test, "set exec");
+ ret = gpk_dbus_task_set_exec (task, "/usr/bin/totem");
+ if (ret)
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "failed to set exec");
+
+#if 0
+ /************************************************************/
+ egg_test_title (test, "install fonts (no UI)");
+ error = NULL;
+ gpk_dbus_task_set_interaction (task, GPK_CLIENT_INTERACT_NEVER);
+ ret = gpk_dbus_task_install_fontconfig_resources (task, (gchar**)fonts, &error);
+ if (ret)
+ egg_test_success (test, NULL);
+ else {
+ /* success until we can do the server parts */
+ egg_test_success (test, "failed to install font : %s", error->message);
+ g_error_free (error);
+ }
+
+ /************************************************************/
+ egg_test_title (test, "install fonts (if found)");
+ error = NULL;
+ gpk_dbus_task_set_interaction (task, pk_bitfield_from_enums (GPK_CLIENT_INTERACT_CONFIRM_SEARCH, GPK_CLIENT_INTERACT_FINISHED, -1));
+ ret = gpk_dbus_task_install_fontconfig_resources (task, (gchar**)fonts, &error);
+ if (ret)
+ egg_test_success (test, NULL);
+ else {
+ /* success until we can do the server parts */
+ egg_test_success (test, "failed to install font : %s", error->message);
+ g_error_free (error);
+ }
+
+ /************************************************************/
+ egg_test_title (test, "install fonts (always)");
+ error = NULL;
+ gpk_dbus_task_set_interaction (task, GPK_CLIENT_INTERACT_ALWAYS);
+ ret = gpk_dbus_task_install_fontconfig_resources (task, (gchar**)fonts, &error);
+ if (ret)
+ egg_test_success (test, NULL);
+ else {
+ /* success until we can do the server parts */
+ egg_test_success (test, "failed to install font : %s", error->message);
+ g_error_free (error);
+ }
+#endif
+
+ egg_test_end (test);
+}
+#endif
+
Added: trunk/src/gpk-dbus-task.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-dbus-task.h Tue Apr 14 16:28:59 2009
@@ -0,0 +1,124 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GPK_DBUS_TASK_H
+#define __GPK_DBUS_TASK_H
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include <packagekit-glib/packagekit.h>
+
+G_BEGIN_DECLS
+
+#define GPK_TYPE_DBUS_TASK (gpk_dbus_task_get_type ())
+#define GPK_DBUS_TASK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GPK_TYPE_DBUS_TASK, GpkDbusTask))
+#define GPK_DBUS_TASK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GPK_TYPE_DBUS_TASK, GpkDbusTaskClass))
+#define GPK_IS_DBUS_TASK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GPK_TYPE_DBUS_TASK))
+#define GPK_IS_DBUS_TASK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GPK_TYPE_DBUS_TASK))
+#define GPK_DBUS_TASK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GPK_TYPE_DBUS_TASK, GpkDbusTaskClass))
+
+typedef struct _GpkDbusTaskPrivate GpkDbusTaskPrivate;
+typedef struct _GpkDbusTask GpkDbusTask;
+typedef struct _GpkDbusTaskClass GpkDbusTaskClass;
+
+struct _GpkDbusTask
+{
+ GObject parent;
+ GpkDbusTaskPrivate *priv;
+};
+
+struct _GpkDbusTaskClass
+{
+ GObjectClass parent_class;
+};
+
+/**
+ * GpkDbusTaskInteract:
+ */
+typedef enum
+{
+ GPK_CLIENT_INTERACT_CONFIRM_SEARCH,
+ GPK_CLIENT_INTERACT_CONFIRM_DEPS,
+ GPK_CLIENT_INTERACT_CONFIRM_INSTALL,
+ GPK_CLIENT_INTERACT_PROGRESS,
+ GPK_CLIENT_INTERACT_FINISHED,
+ GPK_CLIENT_INTERACT_WARNING,
+ GPK_CLIENT_INTERACT_UNKNOWN
+} GpkDbusTaskInteract;
+
+#define GPK_CLIENT_INTERACT_NEVER 0
+#define GPK_CLIENT_INTERACT_ALWAYS pk_bitfield_from_enums (GPK_CLIENT_INTERACT_WARNING, \
+ GPK_CLIENT_INTERACT_CONFIRM_SEARCH, \
+ GPK_CLIENT_INTERACT_CONFIRM_DEPS, \
+ GPK_CLIENT_INTERACT_CONFIRM_INSTALL, \
+ GPK_CLIENT_INTERACT_PROGRESS, \
+ GPK_CLIENT_INTERACT_FINISHED, -1)
+#define GPK_CLIENT_INTERACT_WARNING_CONFIRM_PROGRESS pk_bitfield_from_enums (GPK_CLIENT_INTERACT_WARNING, \
+ GPK_CLIENT_INTERACT_CONFIRM_SEARCH, \
+ GPK_CLIENT_INTERACT_CONFIRM_DEPS, \
+ GPK_CLIENT_INTERACT_CONFIRM_INSTALL, \
+ GPK_CLIENT_INTERACT_PROGRESS, -1)
+#define GPK_CLIENT_INTERACT_WARNING pk_bitfield_from_enums (GPK_CLIENT_INTERACT_WARNING, -1)
+#define GPK_CLIENT_INTERACT_WARNING_PROGRESS pk_bitfield_from_enums (GPK_CLIENT_INTERACT_WARNING, \
+ GPK_CLIENT_INTERACT_PROGRESS, -1)
+
+GQuark gpk_dbus_task_error_quark (void);
+GType gpk_dbus_task_get_type (void);
+GType gpk_dbus_task_error_get_type (void);
+GpkDbusTask *gpk_dbus_task_new (void);
+
+/* methods that expect a DBusGMethodInvocation return */
+void gpk_dbus_task_is_installed (GpkDbusTask *task,
+ const gchar *package_name);
+void gpk_dbus_task_search_file (GpkDbusTask *task,
+ const gchar *search_file);
+void gpk_dbus_task_install_package_files (GpkDbusTask *task,
+ gchar **files_rel);
+void gpk_dbus_task_install_provide_files (GpkDbusTask *task,
+ gchar **full_paths);
+void gpk_dbus_task_install_mime_types (GpkDbusTask *task,
+ gchar **mime_types);
+void gpk_dbus_task_install_gstreamer_resources (GpkDbusTask *task,
+ gchar **codec_names);
+void gpk_dbus_task_install_fontconfig_resources (GpkDbusTask *task,
+ gchar **fonts);
+void gpk_dbus_task_install_package_names (GpkDbusTask *task,
+ gchar **packages);
+void gpk_dbus_task_install_catalogs (GpkDbusTask *task,
+ gchar **filenames);
+
+/* set state */
+gboolean gpk_dbus_task_set_interaction (GpkDbusTask *task,
+ PkBitfield interact);
+gboolean gpk_dbus_task_set_timeout (GpkDbusTask *task,
+ gint timeout);
+gboolean gpk_dbus_task_set_timestamp (GpkDbusTask *task,
+ guint timeout);
+gboolean gpk_dbus_task_set_context (GpkDbusTask *task,
+ DBusGMethodInvocation *context);
+gboolean gpk_dbus_task_set_xid (GpkDbusTask *task,
+ guint xid);
+gboolean gpk_dbus_task_set_exec (GpkDbusTask *task,
+ const gchar *exec);
+
+G_END_DECLS
+
+#endif /* __GPK_DBUS_TASK_H */
Modified: trunk/src/gpk-dbus.c
==============================================================================
--- trunk/src/gpk-dbus.c (original)
+++ trunk/src/gpk-dbus.c Tue Apr 14 16:28:59 2009
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
- * Copyright (C) 2008 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2008-2009 Richard Hughes <richard hughsie com>
*
* Licensed under the GNU General Public License Version 2
*
@@ -47,8 +47,8 @@
#include "egg-string.h"
#include "gpk-dbus.h"
+#include "gpk-dbus-task.h"
#include "gpk-x11.h"
-#include "gpk-client.h"
#include "gpk-common.h"
static void gpk_dbus_finalize (GObject *object);
@@ -57,10 +57,10 @@
struct GpkDbusPrivate
{
- GpkClient *gclient;
- PkClient *client;
GConfClient *gconf_client;
- gint timeout;
+ gint timeout_tmp;
+ GpkX11 *x11;
+ GPtrArray *array;
};
G_DEFINE_TYPE (GpkDbus, gpk_dbus, G_TYPE_OBJECT)
@@ -152,429 +152,6 @@
}
/**
- * gpk_dbus_set_parent_window:
- **/
-static void
-gpk_dbus_set_parent_window (GpkDbus *dbus, guint32 xid, guint32 timestamp)
-{
- GpkX11 *x11;
-
- /* set the parent window */
- gpk_client_set_parent_xid (dbus->priv->gclient, xid);
-
- /* try to get the user time of the window if not provided */
- if (timestamp == 0 && xid != 0) {
- x11 = gpk_x11_new ();
- gpk_x11_set_xid (x11, xid);
- timestamp = gpk_x11_get_user_time (x11);
- g_object_unref (x11);
- }
-
- /* set the last interaction */
- gpk_client_update_timestamp (dbus->priv->gclient, timestamp);
-}
-
-/**
- * gpk_dbus_install_local_file:
- **/
-void
-gpk_dbus_install_local_file (GpkDbus *dbus, guint32 xid, guint32 timestamp, const gchar *full_path, DBusGMethodInvocation *context)
-{
- gboolean ret;
- GError *error;
- GError *error_local = NULL;
- gchar *sender;
- gchar **full_paths;
- gchar *exec;
-
- g_return_if_fail (PK_IS_DBUS (dbus));
-
- egg_debug ("InstallLocalFile method called: %s", full_path);
-
- /* check sender */
- sender = dbus_g_method_get_sender (context);
-
- /* just convert from char* to char** */
- full_paths = g_strsplit (full_path, "|", 1);
- gpk_dbus_set_parent_window (dbus, xid, timestamp);
-
- /* get the program name and set */
- exec = gpk_dbus_get_exec_for_sender (sender);
- gpk_client_set_parent_exec (dbus->priv->gclient, exec);
- g_free (sender);
- g_free (exec);
-
- /* do the action */
- ret = gpk_client_install_local_files (dbus->priv->gclient, full_paths, &error_local);
- g_strfreev (full_paths);
- if (!ret) {
- error = g_error_new (GPK_DBUS_ERROR, error_local->code,
- "Method failed: %s", error_local->message);
- g_error_free (error_local);
- dbus_g_method_return_error (context, error);
- return;
- }
-
- dbus_g_method_return (context);
-}
-
-/**
- * gpk_dbus_install_provide_file:
- **/
-void
-gpk_dbus_install_provide_file (GpkDbus *dbus, guint32 xid, guint32 timestamp, const gchar *full_path, DBusGMethodInvocation *context)
-{
- gboolean ret;
- GError *error;
- GError *error_local = NULL;
- gchar *sender;
- gchar *exec;
-
- g_return_if_fail (PK_IS_DBUS (dbus));
-
- egg_debug ("InstallProvideFile method called: %s", full_path);
-
- /* set modality */
- gpk_dbus_set_parent_window (dbus, xid, timestamp);
-
- /* get the program name and set */
- sender = dbus_g_method_get_sender (context);
- exec = gpk_dbus_get_exec_for_sender (sender);
- gpk_client_set_parent_exec (dbus->priv->gclient, exec);
- g_free (sender);
- g_free (exec);
-
- /* do the action */
- ret = gpk_client_install_provide_file (dbus->priv->gclient, full_path, &error_local);
- if (!ret) {
- error = g_error_new (GPK_DBUS_ERROR, error_local->code,
- "Method failed: %s", error_local->message);
- g_error_free (error_local);
- dbus_g_method_return_error (context, error);
- return;
- }
-
- dbus_g_method_return (context);
-}
-
-/**
- * gpk_dbus_install_package_name:
- **/
-void
-gpk_dbus_install_package_name (GpkDbus *dbus, guint32 xid, guint32 timestamp, const gchar *package_name, DBusGMethodInvocation *context)
-{
- gboolean ret;
- GError *error;
- GError *error_local = NULL;
- gchar *sender;
- gchar **package_names;
- gchar *exec;
-
- g_return_if_fail (PK_IS_DBUS (dbus));
-
- egg_debug ("InstallPackageName method called: %s", package_name);
-
- /* check sender */
- sender = dbus_g_method_get_sender (context);
-
- /* just convert from char* to char** */
- package_names = g_strsplit (package_name, "|", 1);
- gpk_dbus_set_parent_window (dbus, xid, timestamp);
-
- /* get the program name and set */
- exec = gpk_dbus_get_exec_for_sender (sender);
- gpk_client_set_parent_exec (dbus->priv->gclient, exec);
- g_free (sender);
- g_free (exec);
-
- /* do the action */
- ret = gpk_client_install_package_names (dbus->priv->gclient, package_names, &error_local);
- g_strfreev (package_names);
-
- if (!ret) {
- error = g_error_new (GPK_DBUS_ERROR, error_local->code,
- "Method failed: %s", error_local->message);
- g_error_free (error_local);
- dbus_g_method_return_error (context, error);
- return;
- }
-
- dbus_g_method_return (context);
-}
-
-#if 0
-/**
- * gpk_dbus_install_package_names:
- **/
-void
-gpk_dbus_install_package_names (GpkDbus *dbus, guint32 xid, guint32 timestamp, gchar **package_names, DBusGMethodInvocation *context)
-{
- gboolean ret;
- GError *error;
- GError *error_local = NULL;
- gchar *sender;
- gchar *exec;
-
- g_return_if_fail (PK_IS_DBUS (dbus));
-
- egg_debug ("InstallPackageNames method called: %s", package_names[0]);
-
- gpk_dbus_set_parent_window (dbus, xid, timestamp);
-
- /* get the program name and set */
- sender = dbus_g_method_get_sender (context);
- exec = gpk_dbus_get_exec_for_sender (sender);
- gpk_client_set_parent_exec (dbus->priv->gclient, exec);
- g_free (sender);
- g_free (exec);
-
- /* do the action */
- ret = gpk_client_install_package_names (dbus->priv->gclient, package_names, &error_local);
- if (!ret) {
- error = g_error_new (GPK_DBUS_ERROR, error_local->code,
- "Method failed: %s", error_local->message);
- g_error_free (error_local);
- dbus_g_method_return_error (context, error);
- return;
- }
-
- dbus_g_method_return (context);
-}
-#endif
-
-/**
- * gpk_dbus_install_mime_type:
- **/
-void
-gpk_dbus_install_mime_type (GpkDbus *dbus, guint32 xid, guint32 timestamp, const gchar *mime_type, DBusGMethodInvocation *context)
-{
- gboolean ret;
- GError *error;
- GError *error_local = NULL;
- gchar *sender;
- gchar *exec;
-
- g_return_if_fail (PK_IS_DBUS (dbus));
-
- egg_debug ("InstallMimeType method called: %s", mime_type);
-
- /* set modality */
- gpk_dbus_set_parent_window (dbus, xid, timestamp);
-
- /* get the program name and set */
- sender = dbus_g_method_get_sender (context);
- exec = gpk_dbus_get_exec_for_sender (sender);
- gpk_client_set_parent_exec (dbus->priv->gclient, exec);
- g_free (sender);
- g_free (exec);
-
- /* do the action */
- ret = gpk_client_install_mime_type (dbus->priv->gclient, mime_type, &error_local);
- if (!ret) {
- error = g_error_new (GPK_DBUS_ERROR, error_local->code,
- "Method failed: %s", error_local->message);
- g_error_free (error_local);
- dbus_g_method_return_error (context, error);
- return;
- }
-
- dbus_g_method_return (context);
-}
-
-/**
- * gpk_dbus_install_gstreamer_codecs:
- **/
-void
-gpk_dbus_install_gstreamer_codecs (GpkDbus *dbus, guint32 xid, guint32 timestamp, GPtrArray *codecs, DBusGMethodInvocation *context)
-{
- gboolean ret;
- GError *error;
- GError *error_local = NULL;
- gchar *sender;
- gchar *exec;
- guint i;
- GValue *value;
- gchar *description;
- gchar *detail;
- gchar *encoded;
- GPtrArray *array;
- GValueArray *varray;
- gchar **codec_strings;
-
- g_return_if_fail (PK_IS_DBUS (dbus));
-
- egg_debug ("InstallGStreamerCodecs method called");
-
- /* set modality */
- gpk_dbus_set_parent_window (dbus, xid, timestamp);
-
- /* get the program name and set */
- sender = dbus_g_method_get_sender (context);
- exec = gpk_dbus_get_exec_for_sender (sender);
- gpk_client_set_parent_exec (dbus->priv->gclient, exec);
- g_free (sender);
- g_free (exec);
-
- /* unwrap and turn into a GPtrArray */
- array = g_ptr_array_new ();
- for (i=0; i<codecs->len; i++) {
- varray = (GValueArray *) g_ptr_array_index (codecs, i);
- value = g_value_array_get_nth (varray, 0);
- description = g_value_dup_string (value);
- value = g_value_array_get_nth (varray, 1);
- detail = g_value_dup_string (value);
- encoded = g_strdup_printf ("%s|%s", description, detail);
- g_ptr_array_add (array, encoded);
- g_free (description);
- g_free (detail);
- }
-
- /* convert to an strv */
- codec_strings = pk_ptr_array_to_strv (array);
- g_ptr_array_foreach (array, (GFunc) g_free, NULL);
- g_ptr_array_free (array, TRUE);
-
- /* do the action */
- ret = gpk_client_install_gstreamer_codecs (dbus->priv->gclient, codec_strings, &error_local);
- g_strfreev (codec_strings);
-
- if (!ret) {
- error = g_error_new (GPK_DBUS_ERROR, error_local->code,
- "Method failed: %s", error_local->message);
- g_error_free (error_local);
- dbus_g_method_return_error (context, error);
- return;
- }
-
- dbus_g_method_return (context);
-}
-
-/**
- * gpk_dbus_install_fonts:
- **/
-void
-gpk_dbus_install_fonts (GpkDbus *dbus, guint32 xid, guint32 timestamp, gchar **fonts, DBusGMethodInvocation *context)
-{
- gboolean ret;
- GError *error;
- GError *error_local = NULL;
- gchar *sender;
- gchar *exec;
-
- g_return_if_fail (PK_IS_DBUS (dbus));
-
- egg_debug ("InstallFonts method called: %s", fonts[0]);
-
- gpk_dbus_set_parent_window (dbus, xid, timestamp);
-
- /* get the program name and set */
- sender = dbus_g_method_get_sender (context);
- exec = gpk_dbus_get_exec_for_sender (sender);
- gpk_client_set_parent_exec (dbus->priv->gclient, exec);
- g_free (sender);
- g_free (exec);
-
- /* do the action */
- ret = gpk_client_install_fonts (dbus->priv->gclient, fonts, &error_local);
- if (!ret) {
- error = g_error_new (GPK_DBUS_ERROR, error_local->code,
- "Method failed: %s", error_local->message);
- g_error_free (error_local);
- dbus_g_method_return_error (context, error);
- return;
- }
-
- dbus_g_method_return (context);
-}
-
-/**
- * gpk_dbus_install_font:
- **/
-void
-gpk_dbus_install_font (GpkDbus *dbus, guint32 xid, guint32 timestamp, const gchar *font, DBusGMethodInvocation *context)
-{
- gboolean ret;
- GError *error;
- GError *error_local = NULL;
- gchar *sender;
- gchar *exec;
- gchar **fonts;
-
- g_return_if_fail (PK_IS_DBUS (dbus));
-
- egg_debug ("InstallFont method called: %s", font);
-
- /* set modality */
- gpk_dbus_set_parent_window (dbus, xid, timestamp);
-
- /* get the program name and set */
- sender = dbus_g_method_get_sender (context);
- exec = gpk_dbus_get_exec_for_sender (sender);
- gpk_client_set_parent_exec (dbus->priv->gclient, exec);
- g_free (sender);
- g_free (exec);
-
- /* do the action */
- fonts = g_strsplit (font, "|", 1);
- ret = gpk_client_install_fonts (dbus->priv->gclient, fonts, &error_local);
- g_strfreev (fonts);
- if (!ret) {
- error = g_error_new (GPK_DBUS_ERROR, error_local->code,
- "Method failed: %s", error_local->message);
- g_error_free (error_local);
- dbus_g_method_return_error (context, error);
- return;
- }
-
- dbus_g_method_return (context);
-}
-
-/**
- * gpk_dbus_install_catalog:
- **/
-void
-gpk_dbus_install_catalog (GpkDbus *dbus, guint32 xid, guint32 timestamp, const gchar *catalog_file, DBusGMethodInvocation *context)
-{
- gboolean ret;
- GError *error;
- GError *error_local = NULL;
- gchar *sender;
- gchar **catalog_files;
- gchar *exec;
-
- g_return_if_fail (PK_IS_DBUS (dbus));
-
- egg_debug ("InstallCatalog method called: %s", catalog_file);
-
- /* check sender */
- sender = dbus_g_method_get_sender (context);
-
- /* just convert from char* to char** */
- catalog_files = g_strsplit (catalog_file, "|", 1);
- gpk_dbus_set_parent_window (dbus, xid, timestamp);
-
- /* get the program name and set */
- exec = gpk_dbus_get_exec_for_sender (sender);
- gpk_client_set_parent_exec (dbus->priv->gclient, exec);
- g_free (sender);
- g_free (exec);
-
- /* do the action */
- ret = gpk_client_install_catalogs (dbus->priv->gclient, catalog_files, &error_local);
- g_strfreev (catalog_files);
-
- if (!ret) {
- error = g_error_new (GPK_DBUS_ERROR, error_local->code,
- "Method failed: %s", error_local->message);
- g_error_free (error_local);
- dbus_g_method_return_error (context, error);
- return;
- }
-
- dbus_g_method_return (context);
-}
-
-/**
* gpk_dbus_set_interaction_from_text:
**/
static void
@@ -630,239 +207,122 @@
}
/**
- * gpk_dbus_set_interaction:
+ * gpk_dbus_parse_interaction:
**/
static void
-gpk_dbus_set_interaction (GpkDbus *dbus, const gchar *interaction)
+gpk_dbus_parse_interaction (GpkDbus *dbus, const gchar *interaction, PkBitfield *interact, gint *timeout)
{
- PkBitfield interact = 0;
gchar *policy;
- /* set default */
- dbus->priv->timeout = -1;
+ /* set temp default */
+ *interact = 0;
+ dbus->priv->timeout_tmp = -1;
/* get default policy from gconf */
policy = gconf_client_get_string (dbus->priv->gconf_client, GPK_CONF_DBUS_DEFAULT_INTERACTION, NULL);
if (policy != NULL) {
egg_debug ("default is %s", policy);
- gpk_dbus_set_interaction_from_text (&interact, &dbus->priv->timeout, policy);
+ gpk_dbus_set_interaction_from_text (interact, &dbus->priv->timeout_tmp, policy);
}
g_free (policy);
/* now override with policy from client */
- gpk_dbus_set_interaction_from_text (&interact, &dbus->priv->timeout, interaction);
+ gpk_dbus_set_interaction_from_text (interact, &dbus->priv->timeout_tmp, interaction);
egg_debug ("client is %s", interaction);
/* now override with enforced policy from gconf */
policy = gconf_client_get_string (dbus->priv->gconf_client, GPK_CONF_DBUS_ENFORCED_INTERACTION, NULL);
if (policy != NULL) {
egg_debug ("enforced is %s", policy);
- gpk_dbus_set_interaction_from_text (&interact, &dbus->priv->timeout, policy);
+ gpk_dbus_set_interaction_from_text (interact, &dbus->priv->timeout_tmp, policy);
}
g_free (policy);
- /* set the interaction mode */
- egg_debug ("interact=%i", (gint) interact);
- gpk_client_set_interaction (dbus->priv->gclient, interact);
-
- /* set the timeout locally and in the helper client */
- egg_debug ("timeout=%i", dbus->priv->timeout);
- gpk_client_set_timeout (dbus->priv->gclient, dbus->priv->timeout);
+ /* copy from temp */
+ *timeout = dbus->priv->timeout_tmp;
}
/**
- * gpk_dbus_set_context:
+ * gpk_dbus_create_task:
**/
-static void
-gpk_dbus_set_context (GpkDbus *dbus, DBusGMethodInvocation *context)
+static GpkDbusTask *
+gpk_dbus_create_task (GpkDbus *dbus, guint32 xid, const gchar *interaction, DBusGMethodInvocation *context)
{
+ GpkDbusTask *task;
+ PkBitfield interact = 0;
+ gint timeout = 0;
gchar *sender;
gchar *exec;
+ guint timestamp = 0;
- /* get the program name and set */
- sender = dbus_g_method_get_sender (context);
- exec = gpk_dbus_get_exec_for_sender (sender);
- gpk_client_set_parent_exec (dbus->priv->gclient, exec);
-
- g_free (sender);
- g_free (exec);
-}
+ task = gpk_dbus_task_new ();
-#if 0
-/**
- * gpk_dbus_is_package_installed:
- **/
-gboolean
-gpk_dbus_is_package_installed (GpkDbus *dbus, const gchar *package_name, gboolean *installed, GError **error)
-{
- gboolean ret;
- GError *error_local = NULL;
- PkPackageList *list = NULL;
- gchar **package_names = NULL;
-
- g_return_val_if_fail (PK_IS_DBUS (dbus), FALSE);
+ /* work out what interaction the task should use */
+ gpk_dbus_parse_interaction (dbus, interaction, &interact, &timeout);
- /* reset */
- ret = pk_client_reset (dbus->priv->client, &error_local);
- if (!ret) {
- *error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "failed to get installed status: %s", error_local->message);
- g_error_free (error_local);
- goto out;
- }
+ /* set interaction mode */
+ egg_debug ("interact=%i", (gint) interact);
+ gpk_dbus_task_set_interaction (task, interact);
/* set timeout */
- pk_client_set_timeout (dbus->priv->client, dbus->priv->timeout, NULL);
+ egg_debug ("timeout=%i", timeout);
+ gpk_dbus_task_set_timeout (task, timeout);
- /* get the package list for the installed packages */
- package_names = g_strsplit (package_name, "|", 1);
- ret = pk_client_resolve (dbus->priv->client, pk_bitfield_value (PK_FILTER_ENUM_INSTALLED), package_names, &error_local);
- if (!ret) {
- *error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "failed to get installed status: %s", error_local->message);
- g_error_free (error_local);
- goto out;
+ /* set the parent window */
+ gpk_dbus_task_set_xid (task, xid);
+
+ /* try to get the user time of the window */
+ if (xid != 0) {
+ gpk_x11_set_xid (dbus->priv->x11, xid);
+ timestamp = gpk_x11_get_user_time (dbus->priv->x11);
}
- /* more than one entry? */
- list = pk_client_get_package_list (dbus->priv->client);
- *installed = (PK_OBJ_LIST(list)->len > 0);
-out:
- if (list != NULL)
- g_object_unref (list);
- g_strfreev (package_names);
- return ret;
-}
-#endif
+ /* set the context for the return values */
+ gpk_dbus_task_set_context (task, context);
-/**
- * gpk_dbus_is_installed:
- **/
-gboolean
-gpk_dbus_is_installed (GpkDbus *dbus, const gchar *package_name, const gchar *interaction, gboolean *installed, GError **error)
-{
- gboolean ret;
- GError *error_local = NULL;
- PkPackageList *list = NULL;
- gchar **package_names = NULL;
+ /* set the last interaction */
+ gpk_dbus_task_set_timestamp (task, timestamp);
- g_return_val_if_fail (PK_IS_DBUS (dbus), FALSE);
+ /* set the window for the modal and timestamp */
+ gpk_dbus_task_set_xid (task, xid);
- /* process wait command */
- gpk_dbus_set_interaction (dbus, interaction);
+ /* get the program name and set */
+ sender = dbus_g_method_get_sender (context);
+ exec = gpk_dbus_get_exec_for_sender (sender);
+ gpk_dbus_task_set_exec (task, exec);
- /* reset */
- ret = pk_client_reset (dbus->priv->client, &error_local);
- if (!ret) {
- *error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "failed to get installed status: %s", error_local->message);
- g_error_free (error_local);
- goto out;
- }
+ /* unref on delete */
+ //g_signal_connect...
- /* set timeout */
- pk_client_set_timeout (dbus->priv->client, dbus->priv->timeout, NULL);
+ /* add to array */
+ g_ptr_array_add (dbus->priv->array, task);
- /* get the package list for the installed packages */
- package_names = g_strsplit (package_name, "|", 1);
- ret = pk_client_resolve (dbus->priv->client, pk_bitfield_value (PK_FILTER_ENUM_INSTALLED), package_names, &error_local);
- if (!ret) {
- *error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "failed to get installed status: %s", error_local->message);
- g_error_free (error_local);
- goto out;
- }
-
- /* more than one entry? */
- list = pk_client_get_package_list (dbus->priv->client);
- *installed = (PK_OBJ_LIST(list)->len > 0);
-out:
- if (list != NULL)
- g_object_unref (list);
- g_strfreev (package_names);
- return ret;
+ g_free (sender);
+ g_free (exec);
+ return task;
}
+
/**
- * gpk_dbus_search_file:
+ * gpk_dbus_is_installed:
**/
-gboolean
-gpk_dbus_search_file (GpkDbus *dbus, const gchar *file_name, const gchar *interaction, gboolean *installed, gchar **package_name, GError **error)
+void
+gpk_dbus_is_installed (GpkDbus *dbus, const gchar *package_name, const gchar *interaction, DBusGMethodInvocation *context)
{
- gboolean ret;
- GError *error_local = NULL;
- PkPackageList *list = NULL;
- const PkPackageObj *obj;
-
- g_return_val_if_fail (PK_IS_DBUS (dbus), FALSE);
-
- /* process wait command */
- gpk_dbus_set_interaction (dbus, interaction);
-
- /* reset */
- ret = pk_client_reset (dbus->priv->client, &error_local);
- if (!ret) {
- *error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "failed to get installed status: %s", error_local->message);
- g_error_free (error_local);
- goto out;
- }
-
- /* set timeout */
- pk_client_set_timeout (dbus->priv->client, dbus->priv->timeout, NULL);
-
- /* get the package list for the installed packages */
- ret = pk_client_search_file (dbus->priv->client, pk_bitfield_value (PK_FILTER_ENUM_INSTALLED), file_name, &error_local);
- if (!ret) {
- *error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_INTERNAL_ERROR, "failed to search for file: %s", error_local->message);
- g_error_free (error_local);
- goto out;
- }
-
- /* more than one entry? */
- list = pk_client_get_package_list (dbus->priv->client);
- if (PK_OBJ_LIST(list)->len < 1) {
- *error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_NO_PACKAGES_FOUND, "could not find package providing file");
- ret = FALSE;
- goto out;
- }
-
- /* get the package name too */
- *installed = TRUE;
- obj = pk_package_list_get_obj (list, 0);
- *package_name = g_strdup (obj->id->name);
-
-out:
- if (list != NULL)
- g_object_unref (list);
- return ret;
+ GpkDbusTask *task;
+ task = gpk_dbus_create_task (dbus, 0, interaction, context);
+ gpk_dbus_task_is_installed (task, package_name);
}
/**
- * gpk_dbus_install_provide_files:
+ * gpk_dbus_search_file:
**/
void
-gpk_dbus_install_provide_files (GpkDbus *dbus, guint32 xid, gchar **files, const gchar *interaction, DBusGMethodInvocation *context)
+gpk_dbus_search_file (GpkDbus *dbus, const gchar *file_name, const gchar *interaction, DBusGMethodInvocation *context)
{
- gboolean ret;
- GError *error;
- GError *error_local = NULL;
-
- g_return_if_fail (PK_IS_DBUS (dbus));
-
- egg_debug ("InstallProvideFiles method called: %s", files[0]);
-
- /* set common parameters */
- gpk_dbus_set_parent_window (dbus, xid, 0);
- gpk_dbus_set_interaction (dbus, interaction);
- gpk_dbus_set_context (dbus, context);
-
- /* do the action */
- ret = gpk_client_install_provide_file (dbus->priv->gclient, files[0], &error_local);
- if (!ret) {
- error = g_error_new (GPK_DBUS_ERROR, error_local->code,
- "Method failed: %s", error_local->message);
- g_error_free (error_local);
- dbus_g_method_return_error (context, error);
- return;
- }
-
- dbus_g_method_return (context);
+ GpkDbusTask *task;
+ task = gpk_dbus_create_task (dbus, 0, interaction, context);
+ gpk_dbus_task_search_file (task, file_name);
}
/**
@@ -871,30 +331,20 @@
void
gpk_dbus_install_package_files (GpkDbus *dbus, guint32 xid, gchar **files, const gchar *interaction, DBusGMethodInvocation *context)
{
- gboolean ret;
- GError *error;
- GError *error_local = NULL;
-
- g_return_if_fail (PK_IS_DBUS (dbus));
-
- egg_debug ("InstallPackageFiles method called: %s", files[0]);
-
- /* set common parameters */
- gpk_dbus_set_parent_window (dbus, xid, 0);
- gpk_dbus_set_interaction (dbus, interaction);
- gpk_dbus_set_context (dbus, context);
-
- /* do the action */
- ret = gpk_client_install_local_files (dbus->priv->gclient, files, &error_local);
- if (!ret) {
- error = g_error_new (GPK_DBUS_ERROR, error_local->code,
- "Method failed: %s", error_local->message);
- g_error_free (error_local);
- dbus_g_method_return_error (context, error);
- return;
- }
+ GpkDbusTask *task;
+ task = gpk_dbus_create_task (dbus, xid, interaction, context);
+ gpk_dbus_task_install_package_files (task, files);
+}
- dbus_g_method_return (context);
+/**
+ * gpk_dbus_install_provide_files:
+ **/
+void
+gpk_dbus_install_provide_files (GpkDbus *dbus, guint32 xid, gchar **files, const gchar *interaction, DBusGMethodInvocation *context)
+{
+ GpkDbusTask *task;
+ task = gpk_dbus_create_task (dbus, xid, interaction, context);
+ gpk_dbus_task_install_provide_files (task, files);
}
/**
@@ -903,30 +353,9 @@
void
gpk_dbus_install_package_names (GpkDbus *dbus, guint32 xid, gchar **packages, const gchar *interaction, DBusGMethodInvocation *context)
{
- gboolean ret;
- GError *error;
- GError *error_local = NULL;
-
- g_return_if_fail (PK_IS_DBUS (dbus));
-
- egg_debug ("InstallPackageNames method called: %s", packages[0]);
-
- /* set common parameters */
- gpk_dbus_set_parent_window (dbus, xid, 0);
- gpk_dbus_set_interaction (dbus, interaction);
- gpk_dbus_set_context (dbus, context);
-
- /* do the action */
- ret = gpk_client_install_package_names (dbus->priv->gclient, packages, &error_local);
- if (!ret) {
- error = g_error_new (GPK_DBUS_ERROR, error_local->code,
- "Method failed: %s", error_local->message);
- g_error_free (error_local);
- dbus_g_method_return_error (context, error);
- return;
- }
-
- dbus_g_method_return (context);
+ GpkDbusTask *task;
+ task = gpk_dbus_create_task (dbus, xid, interaction, context);
+ gpk_dbus_task_install_package_names (task, packages);
}
/**
@@ -935,30 +364,9 @@
void
gpk_dbus_install_mime_types (GpkDbus *dbus, guint32 xid, gchar **mime_types, const gchar *interaction, DBusGMethodInvocation *context)
{
- gboolean ret;
- GError *error;
- GError *error_local = NULL;
-
- g_return_if_fail (PK_IS_DBUS (dbus));
-
- egg_debug ("InstallMimeTypes method called: %s", mime_types[0]);
-
- /* set common parameters */
- gpk_dbus_set_parent_window (dbus, xid, 0);
- gpk_dbus_set_interaction (dbus, interaction);
- gpk_dbus_set_context (dbus, context);
-
- /* do the action */
- ret = gpk_client_install_mime_type (dbus->priv->gclient, mime_types[0], &error_local);
- if (!ret) {
- error = g_error_new (GPK_DBUS_ERROR, error_local->code,
- "Method failed: %s", error_local->message);
- g_error_free (error_local);
- dbus_g_method_return_error (context, error);
- return;
- }
-
- dbus_g_method_return (context);
+ GpkDbusTask *task;
+ task = gpk_dbus_create_task (dbus, xid, interaction, context);
+ gpk_dbus_task_install_mime_types (task, mime_types);
}
/**
@@ -967,30 +375,9 @@
void
gpk_dbus_install_fontconfig_resources (GpkDbus *dbus, guint32 xid, gchar **resources, const gchar *interaction, DBusGMethodInvocation *context)
{
- gboolean ret;
- GError *error;
- GError *error_local = NULL;
-
- g_return_if_fail (PK_IS_DBUS (dbus));
-
- egg_debug ("InstallFontconfigResources method called: %s", resources[0]);
-
- /* set common parameters */
- gpk_dbus_set_parent_window (dbus, xid, 0);
- gpk_dbus_set_interaction (dbus, interaction);
- gpk_dbus_set_context (dbus, context);
-
- /* do the action */
- ret = gpk_client_install_fonts (dbus->priv->gclient, resources, &error_local);
- if (!ret) {
- error = g_error_new (GPK_DBUS_ERROR, error_local->code,
- "Method failed: %s", error_local->message);
- g_error_free (error_local);
- dbus_g_method_return_error (context, error);
- return;
- }
-
- dbus_g_method_return (context);
+ GpkDbusTask *task;
+ task = gpk_dbus_create_task (dbus, xid, interaction, context);
+ gpk_dbus_task_install_fontconfig_resources (task, resources);
}
/**
@@ -999,30 +386,9 @@
void
gpk_dbus_install_gstreamer_resources (GpkDbus *dbus, guint32 xid, gchar **resources, const gchar *interaction, DBusGMethodInvocation *context)
{
- gboolean ret;
- GError *error;
- GError *error_local = NULL;
-
- g_return_if_fail (PK_IS_DBUS (dbus));
-
- egg_debug ("InstallGStreamerResources method called: %s", resources[0]);
-
- /* set common parameters */
- gpk_dbus_set_parent_window (dbus, xid, 0);
- gpk_dbus_set_interaction (dbus, interaction);
- gpk_dbus_set_context (dbus, context);
-
- /* do the action */
- ret = gpk_client_install_gstreamer_codecs (dbus->priv->gclient, resources, &error_local);
- if (!ret) {
- error = g_error_new (GPK_DBUS_ERROR, error_local->code,
- "Method failed: %s", error_local->message);
- g_error_free (error_local);
- dbus_g_method_return_error (context, error);
- return;
- }
-
- dbus_g_method_return (context);
+ GpkDbusTask *task;
+ task = gpk_dbus_create_task (dbus, xid, interaction, context);
+ gpk_dbus_task_install_gstreamer_resources (task, resources);
}
/**
@@ -1045,14 +411,10 @@
gpk_dbus_init (GpkDbus *dbus)
{
dbus->priv = GPK_DBUS_GET_PRIVATE (dbus);
- dbus->priv->timeout = -1;
+ dbus->priv->timeout_tmp = -1;
dbus->priv->gconf_client = gconf_client_get_default ();
- dbus->priv->client = pk_client_new ();
- pk_client_set_use_buffer (dbus->priv->client, TRUE, NULL);
- pk_client_set_synchronous (dbus->priv->client, TRUE, NULL);
-
- dbus->priv->gclient = gpk_client_new ();
- gpk_client_set_interaction (dbus->priv->gclient, GPK_CLIENT_INTERACT_WARNING_CONFIRM_PROGRESS);
+ dbus->priv->array = g_ptr_array_new ();
+ dbus->priv->x11 = gpk_x11_new ();
}
/**
@@ -1067,9 +429,10 @@
dbus = GPK_DBUS (object);
g_return_if_fail (dbus->priv != NULL);
- g_object_unref (dbus->priv->client);
- g_object_unref (dbus->priv->gclient);
+ g_ptr_array_foreach (dbus->priv->array, (GFunc) g_object_unref, NULL);
+ g_ptr_array_free (dbus->priv->array, TRUE);
g_object_unref (dbus->priv->gconf_client);
+ g_object_unref (dbus->priv->x11);
G_OBJECT_CLASS (gpk_dbus_parent_class)->finalize (object);
}
Modified: trunk/src/gpk-dbus.h
==============================================================================
--- trunk/src/gpk-dbus.h (original)
+++ trunk/src/gpk-dbus.h Tue Apr 14 16:28:59 2009
@@ -64,72 +64,21 @@
GType gpk_dbus_get_type (void);
GpkDbus *gpk_dbus_new (void);
-void gpk_dbus_install_local_file (GpkDbus *dbus,
- guint32 xid,
- guint32 timestamp,
- const gchar *full_path,
- DBusGMethodInvocation *context);
-void gpk_dbus_install_provide_file (GpkDbus *dbus,
- guint32 xid,
- guint32 timestamp,
- const gchar *full_path,
- DBusGMethodInvocation *context);
-void gpk_dbus_install_package_name (GpkDbus *dbus,
- guint32 xid,
- guint32 timestamp,
- const gchar *package_name,
- DBusGMethodInvocation *context);
-#if 0
-void gpk_dbus_install_package_names (GpkDbus *dbus,
- guint32 xid,
- guint32 timestamp,
- gchar **package_names,
- DBusGMethodInvocation *context);
-#endif
-void gpk_dbus_install_mime_type (GpkDbus *dbus,
- guint32 xid,
- guint32 timestamp,
- const gchar *mime_type,
- DBusGMethodInvocation *context);
-void gpk_dbus_install_gstreamer_codecs (GpkDbus *dbus,
- guint32 xid,
- guint32 timestamp,
- GPtrArray *codecs,
- DBusGMethodInvocation *context);
-void gpk_dbus_install_font (GpkDbus *dbus,
- guint32 xid,
- guint32 timestamp,
- const gchar *font_desc,
- DBusGMethodInvocation *context);
-void gpk_dbus_install_fonts (GpkDbus *dbus,
- guint32 xid,
- guint32 timestamp,
- gchar **font_descs,
- DBusGMethodInvocation *context);
-void gpk_dbus_install_catalog (GpkDbus *dbus,
- guint32 xid,
- guint32 timestamp,
- const gchar *catalog_file,
- DBusGMethodInvocation *context);
-#if 0
-gboolean gpk_dbus_is_package_installed (GpkDbus *dbus,
- const gchar *package_name,
- gboolean *installed,
- GError **error);
-#endif
+//void gpk_dbus_install_catalog (GpkDbus *dbus,
+// guint32 xid,
+// guint32 timestamp,
+// const gchar *catalog_file,
+// DBusGMethodInvocation *context);
/* org.freedesktop.PackageKit.Query */
-gboolean gpk_dbus_is_installed (GpkDbus *dbus,
+void gpk_dbus_is_installed (GpkDbus *dbus,
const gchar *package_name,
const gchar *interaction,
- gboolean *installed,
- GError **error);
-gboolean gpk_dbus_search_file (GpkDbus *dbus,
+ DBusGMethodInvocation *context);
+void gpk_dbus_search_file (GpkDbus *dbus,
const gchar *file_name,
const gchar *interaction,
- gboolean *installed,
- gchar **package_name,
- GError **error);
+ DBusGMethodInvocation *context);
/* org.freedesktop.PackageKit.Modify */
void gpk_dbus_install_provide_files (GpkDbus *dbus,
Modified: trunk/src/gpk-dialog.c
==============================================================================
--- trunk/src/gpk-dialog.c (original)
+++ trunk/src/gpk-dialog.c Tue Apr 14 16:28:59 2009
@@ -273,7 +273,7 @@
checked = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
egg_debug ("Changing %s to %i", key, checked);
gconf_client = gconf_client_get_default ();
- gconf_client_set_bool (gconf_client, key, checked, NULL);
+ gconf_client_set_bool (gconf_client, key, !checked, NULL);
g_object_unref (gconf_client);
}
@@ -284,11 +284,20 @@
gpk_dialog_embed_do_not_show_widget (GtkDialog *dialog, const gchar *key)
{
GtkWidget *widget;
+ gboolean checked;
+ GConfClient *gconf_client;
/* add a checkbutton for deps screen */
widget = gtk_check_button_new_with_label (_("Do not show this again"));
g_signal_connect (widget, "clicked", G_CALLBACK (gpk_client_checkbutton_show_depends_cb), (gpointer) key);
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), widget);
+
+ /* checked? */
+ gconf_client = gconf_client_get_default ();
+ checked = gconf_client_get_bool (gconf_client, key, NULL);
+ g_object_unref (gconf_client);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), !checked);
+
gtk_widget_show (widget);
return TRUE;
}
Modified: trunk/src/gpk-enum.c
==============================================================================
--- trunk/src/gpk-enum.c (original)
+++ trunk/src/gpk-enum.c Tue Apr 14 16:28:59 2009
@@ -310,6 +310,36 @@
}
/**
+ * gpk_media_type_enum_to_localised_text:
+ **/
+const gchar *
+gpk_media_type_enum_to_localised_text (PkMediaTypeEnum type)
+{
+ const gchar *text = NULL;
+ switch (type) {
+ case PK_MEDIA_TYPE_ENUM_CD:
+ /* TRANSLATORS: this is compact disk (CD) media */
+ text = _("CD");
+ break;
+ case PK_MEDIA_TYPE_ENUM_DVD:
+ /* TRANSLATORS: this is digital versatile disk (DVD) media */
+ text = _("DVD");
+ break;
+ case PK_MEDIA_TYPE_ENUM_DISC:
+ /* TRANSLATORS: this is either CD or DVD media */
+ text = _("disc");
+ break;
+ case PK_MEDIA_TYPE_ENUM_UNKNOWN:
+ /* TRANSLATORS: this is generic media of unknown type that we will install from */
+ text = _("media");
+ break;
+ default:
+ egg_warning ("Unknown media type");
+ }
+ return text;
+}
+
+/**
* gpk_error_enum_to_localised_text:
**/
const gchar *
@@ -455,6 +485,9 @@
case PK_ERROR_ENUM_NO_SPACE_ON_DEVICE:
text = _("No space is left on the disk");
break;
+ case PK_ERROR_ENUM_MEDIA_CHANGE_REQUIRED:
+ text = _("A media change is required");
+ break;
default:
egg_warning ("Unknown error");
}
@@ -638,6 +671,9 @@
text = _("There is insufficient space on the device.\n"
"Free some space on the system disk to perform this operation.");
break;
+ case PK_ERROR_ENUM_MEDIA_CHANGE_REQUIRED:
+ text = _("Additional media is required to complete the transaction.");
+ break;
default:
egg_warning ("Unknown error, please report a bug at " GPK_BUGZILLA_URL ".\n"
"More information is available in the detailed report.");
Modified: trunk/src/gpk-enum.h
==============================================================================
--- trunk/src/gpk-enum.h (original)
+++ trunk/src/gpk-enum.h Tue Apr 14 16:28:59 2009
@@ -78,6 +78,8 @@
GpkUpdateEnum gpk_update_enum_from_text (const gchar *update);
const gchar *gpk_update_enum_to_text (GpkUpdateEnum update);
const gchar *gpk_role_enum_to_icon_name (PkRoleEnum role);
+const gchar *gpk_media_type_enum_to_localised_text (PkMediaTypeEnum type)
+ G_GNUC_CONST;
const gchar *gpk_info_enum_to_localised_text (PkInfoEnum info)
G_GNUC_CONST;
const gchar *gpk_info_enum_to_localised_past (PkInfoEnum info)
Modified: trunk/src/gpk-error.c
==============================================================================
--- trunk/src/gpk-error.c (original)
+++ trunk/src/gpk-error.c Tue Apr 14 16:28:59 2009
@@ -71,7 +71,6 @@
guint retval;
GError *error = NULL;
- g_return_val_if_fail (title != NULL, FALSE);
g_return_val_if_fail (message != NULL, FALSE);
/* get UI */
Modified: trunk/src/gpk-firmware.c
==============================================================================
--- trunk/src/gpk-firmware.c (original)
+++ trunk/src/gpk-firmware.c Tue Apr 14 16:28:59 2009
@@ -42,7 +42,6 @@
#include "egg-debug.h"
#include "egg-string.h"
-#include "gpk-client.h"
#include "gpk-common.h"
#include "gpk-firmware.h"
@@ -55,7 +54,8 @@
struct GpkFirmwarePrivate
{
- GPtrArray *array_found;
+ PkClient *client_primary;
+ PkPackageList *packages_found;
GPtrArray *array_requested;
GConfClient *gconf_client;
};
@@ -68,28 +68,26 @@
static gboolean
gpk_firmware_install_file (GpkFirmware *firmware)
{
- guint i;
gboolean ret;
- GpkClient *gclient;
- GPtrArray *array;
GError *error = NULL;
- const gchar *filename;
+ gchar **package_ids;
- gclient = gpk_client_new ();
- array = firmware->priv->array_found;
-
- /* try to install each firmware file */
- for (i=0; i<array->len; i++) {
- filename = g_ptr_array_index (array, i);
- gpk_client_set_interaction (gclient, GPK_CLIENT_INTERACT_WARNING_PROGRESS);
- ret = gpk_client_install_provide_file (gclient, filename, &error);
- if (!ret) {
- egg_warning ("failed to install provide file: %s", error->message);
- g_error_free (error);
- error = NULL;
- }
+ /* install all of the firmware files */
+ package_ids = pk_package_list_to_strv (firmware->priv->packages_found);
+ ret = pk_client_reset (firmware->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("failed to reset: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+ ret = pk_client_install_packages (firmware->priv->client_primary, package_ids, &error);
+ if (!ret) {
+ egg_warning ("failed to install provide file: %s", error->message);
+ g_error_free (error);
+ goto out;
}
- g_object_unref (gclient);
+out:
+ g_strfreev (package_ids);
return ret;
}
@@ -116,39 +114,42 @@
* @firmware: This class instance
* @filename: Firmware to search for
**/
-static gboolean
+static PkPackageObj *
gpk_firmware_check_available (GpkFirmware *firmware, const gchar *filename)
{
gboolean ret;
guint length = 0;
- PkClient *client = NULL;
PkPackageList *list = NULL;
GError *error = NULL;
+ PkPackageObj *obj = NULL;
/* actually check we can provide the firmware */
- client = pk_client_new ();
- pk_client_set_synchronous (client, TRUE, NULL);
- pk_client_set_use_buffer (client, TRUE, NULL);
- ret = pk_client_search_file (client, pk_bitfield_value (PK_FILTER_ENUM_NOT_INSTALLED), filename, &error);
+ ret = pk_client_reset (firmware->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("failed to reset: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+ ret = pk_client_search_file (firmware->priv->client_primary, pk_bitfield_value (PK_FILTER_ENUM_NOT_INSTALLED), filename, &error);
if (!ret) {
egg_warning ("failed to search file %s: %s", filename, error->message);
g_error_free (error);
- error = NULL;
goto out;
}
/* make sure we have one package */
- list = pk_client_get_package_list (client);
+ list = pk_client_get_package_list (firmware->priv->client_primary);
length = pk_package_list_get_size (list);
- g_object_unref (list);
if (length == 0)
egg_debug ("no package providing %s found", filename);
else if (length != 1)
egg_warning ("not one package providing %s found (%i)", filename, length);
-
+ else
+ obj = pk_package_obj_copy (pk_package_list_get_obj (list, 0));
out:
- g_object_unref (client);
- return (length == 1);
+ if (list != NULL)
+ g_object_unref (list);
+ return obj;
}
/**
@@ -158,15 +159,15 @@
static gboolean
gpk_firmware_timeout_cb (gpointer data)
{
- guint i, j;
+ guint i;
gboolean ret;
const gchar *filename;
const gchar *message;
- gchar *duplicate;
GpkFirmware *firmware = GPK_FIRMWARE (data);
NotifyNotification *notification;
GPtrArray *array;
GError *error = NULL;
+ PkPackageObj *obj = NULL;
/* debug so we can catch polling */
egg_debug ("polling check");
@@ -176,35 +177,21 @@
for (i=0; i<array->len; i++) {
filename = g_ptr_array_index (array, i);
/* save to new array if we found one package for this file */
- ret = gpk_firmware_check_available (firmware, filename);
- if (ret)
- g_ptr_array_add (firmware->priv->array_found, g_strdup (filename));
+ obj = gpk_firmware_check_available (firmware, filename);
+ if (obj != NULL) {
+ pk_obj_list_add (PK_OBJ_LIST (firmware->priv->packages_found), obj);
+ pk_package_obj_free (obj);
+ }
}
/* nothing to do */
- array = firmware->priv->array_found;
- if (array->len == 0) {
+ if (pk_package_list_get_size (firmware->priv->packages_found) == 0) {
egg_debug ("no packages providing any of the missing firmware");
goto out;
}
/* check we don't want the same package more than once */
- for (i=0; i<array->len; i++) {
- for (j=0; j<array->len; j++) {
- duplicate = g_ptr_array_index (array, j);
- if (i != j && egg_strequal (g_ptr_array_index (array, i), duplicate)) {
- g_free (duplicate);
- g_ptr_array_remove_index_fast (array, j);
- }
- }
- }
-
- /* debugging */
- egg_debug ("need to install:");
- for (i=0; i<array->len; i++) {
- filename = g_ptr_array_index (array, i);
- egg_debug ("%s", filename);
- }
+ pk_obj_list_remove_duplicate (PK_OBJ_LIST (firmware->priv->packages_found));
/* TRANSLATORS: we need another package to keep udev quiet */
message = _("Additional firmware is required to make hardware in this computer function correctly.");
@@ -330,9 +317,12 @@
GPtrArray *array;
firmware->priv = GPK_FIRMWARE_GET_PRIVATE (firmware);
- firmware->priv->array_found = g_ptr_array_new ();
+ firmware->priv->packages_found = pk_package_list_new ();
firmware->priv->array_requested = g_ptr_array_new ();
firmware->priv->gconf_client = gconf_client_get_default ();
+ firmware->priv->client_primary = pk_client_new ();
+ pk_client_set_synchronous (firmware->priv->client_primary, TRUE, NULL);
+ pk_client_set_use_buffer (firmware->priv->client_primary, TRUE, NULL);
/* should we check and show the user */
ret = gconf_client_get_bool (firmware->priv->gconf_client, GPK_CONF_ENABLE_CHECK_FIRMWARE, NULL);
@@ -405,10 +395,10 @@
firmware = GPK_FIRMWARE (object);
g_return_if_fail (firmware->priv != NULL);
- g_ptr_array_foreach (firmware->priv->array_found, (GFunc) g_free, NULL);
- g_ptr_array_free (firmware->priv->array_found, TRUE);
g_ptr_array_foreach (firmware->priv->array_requested, (GFunc) g_free, NULL);
g_ptr_array_free (firmware->priv->array_requested, TRUE);
+ g_object_unref (firmware->priv->packages_found);
+ g_object_unref (firmware->priv->client_primary);
g_object_unref (firmware->priv->gconf_client);
G_OBJECT_CLASS (gpk_firmware_parent_class)->finalize (object);
Modified: trunk/src/gpk-hardware.c
==============================================================================
--- trunk/src/gpk-hardware.c (original)
+++ trunk/src/gpk-hardware.c Tue Apr 14 16:28:59 2009
@@ -44,7 +44,6 @@
#include "egg-debug.h"
#include "egg-string.h"
-#include "gpk-client.h"
#include "gpk-common.h"
#include "gpk-hardware.h"
@@ -74,19 +73,21 @@
gpk_hardware_install_package (GpkHardware *hardware)
{
GError *error = NULL;
- GpkClient *gclient = NULL;
+ PkClient *client = NULL;
gboolean ret;
- gclient = gpk_client_new ();
+ client = pk_client_new ();
- ret = gpk_client_install_package_ids (gclient, hardware->priv->package_ids, &error);
+ /* FIXME: this needs to be async and connect up to the repo signature stuff */
+ pk_client_set_synchronous (client, TRUE, NULL);
+ ret = pk_client_install_packages (client, hardware->priv->package_ids, &error);
if (!ret) {
egg_warning ("failed to install package: %s", error->message);
g_error_free (error);
error = NULL;
}
- g_object_unref (gclient);
+ g_object_unref (client);
return ret;
}
Added: trunk/src/gpk-helper-chooser.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-helper-chooser.c Tue Apr 14 16:28:59 2009
@@ -0,0 +1,355 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <packagekit-glib/packagekit.h>
+
+#include "gpk-helper-chooser.h"
+#include "gpk-marshal.h"
+#include "gpk-gnome.h"
+#include "gpk-common.h"
+#include "gpk-enum.h"
+#include "gpk-desktop.h"
+
+#include "egg-debug.h"
+
+static void gpk_helper_chooser_finalize (GObject *object);
+
+#define GPK_HELPER_CHOOSER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPK_TYPE_HELPER_CHOOSER, GpkHelperChooserPrivate))
+
+struct GpkHelperChooserPrivate
+{
+ GtkBuilder *builder;
+ PkDesktop *desktop;
+ gchar *package_id;
+ GtkListStore *list_store;
+};
+
+enum {
+ GPK_HELPER_CHOOSER_EVENT,
+ GPK_HELPER_CHOOSER_LAST_SIGNAL
+};
+
+enum {
+ GPK_CHOOSER_COLUMN_ICON,
+ GPK_CHOOSER_COLUMN_TEXT,
+ GPK_CHOOSER_COLUMN_ID,
+ GPK_CHOOSER_COLUMN_LAST
+};
+
+static guint signals [GPK_HELPER_CHOOSER_LAST_SIGNAL] = { 0 };
+G_DEFINE_TYPE (GpkHelperChooser, gpk_helper_chooser, G_TYPE_OBJECT)
+
+/**
+ * gpk_helper_chooser_button_install_cb:
+ **/
+static void
+gpk_helper_chooser_button_install_cb (GtkWidget *widget, GpkHelperChooser *helper)
+{
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_simple"));
+ gtk_widget_hide (widget);
+ g_signal_emit (helper, signals [GPK_HELPER_CHOOSER_EVENT], 0, GTK_RESPONSE_YES, helper->priv->package_id);
+}
+
+/**
+ * gpk_helper_chooser_button_cancel_cb:
+ **/
+static void
+gpk_helper_chooser_button_cancel_cb (GtkWidget *widget, GpkHelperChooser *helper)
+{
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_simple"));
+ gtk_widget_hide (widget);
+ g_signal_emit (helper, signals [GPK_HELPER_CHOOSER_EVENT], 0, GTK_RESPONSE_NO, helper->priv->package_id);
+}
+
+/**
+ * gpk_helper_chooser_button_help_cb:
+ **/
+static void
+gpk_helper_chooser_button_help_cb (GtkWidget *widget, GpkHelperChooser *helper)
+{
+ /* show the help */
+ gpk_gnome_help ("mime-types");
+}
+
+/**
+ * gpk_helper_chooser_treeview_clicked_cb:
+ **/
+static void
+gpk_helper_chooser_treeview_clicked_cb (GtkTreeSelection *selection, GpkHelperChooser *helper)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ /* This will only work in single or browse selection mode! */
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ g_free (helper->priv->package_id);
+ gtk_tree_model_get (model, &iter, GPK_CHOOSER_COLUMN_ID, &helper->priv->package_id, -1);
+
+ /* show package_id */
+ egg_debug ("selected row is: %s", helper->priv->package_id);
+ } else {
+ egg_debug ("no row selected");
+ }
+}
+
+/**
+ * pk_treeview_add_general_columns:
+ **/
+static void
+pk_treeview_add_general_columns (GtkTreeView *treeview)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ /* image */
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (renderer, "stock-size", GTK_ICON_SIZE_DIALOG, NULL);
+ /* TRANSLATORS: column for the application icon */
+ column = gtk_tree_view_column_new_with_attributes (_("Icon"), renderer,
+ "icon-name", GPK_CHOOSER_COLUMN_ICON, NULL);
+ gtk_tree_view_append_column (treeview, column);
+
+ /* column for text */
+ renderer = gtk_cell_renderer_text_new ();
+ /* TRANSLATORS: column for the application name */
+ column = gtk_tree_view_column_new_with_attributes (_("Package"), renderer,
+ "markup", GPK_CHOOSER_COLUMN_TEXT, NULL);
+ gtk_tree_view_column_set_sort_column_id (column, GPK_CHOOSER_COLUMN_TEXT);
+ gtk_tree_view_append_column (treeview, column);
+ gtk_tree_view_column_set_expand (column, TRUE);
+}
+
+/**
+ * gpk_helper_chooser_show:
+ *
+ * Return value: if we agreed
+ **/
+gboolean
+gpk_helper_chooser_show (GpkHelperChooser *helper, PkPackageList *list)
+{
+ GtkWidget *widget;
+ gchar *text;
+ const gchar *icon_name;
+ guint len;
+ guint i;
+ const PkPackageObj *obj;
+ gchar *package_id;
+ GtkTreeIter iter;
+
+ g_return_val_if_fail (GPK_IS_HELPER_CHOOSER (helper), FALSE);
+ g_return_val_if_fail (list != NULL, FALSE);
+
+ /* see what we've got already */
+ len = pk_package_list_get_size (list);
+ for (i=0; i<len; i++) {
+ obj = pk_package_list_get_obj (list, i);
+ egg_debug ("package '%s' got:", obj->id->name);
+
+ /* put formatted text into treeview */
+ gtk_list_store_append (helper->priv->list_store, &iter);
+ text = gpk_package_id_format_twoline (obj->id, obj->summary);
+
+ /* get the icon */
+ icon_name = gpk_desktop_guess_icon_name (helper->priv->desktop, obj->id->name);
+ if (icon_name == NULL)
+ icon_name = gpk_info_enum_to_icon_name (obj->info);
+
+ package_id = pk_package_id_to_string (obj->id);
+ gtk_list_store_set (helper->priv->list_store, &iter,
+ GPK_CHOOSER_COLUMN_TEXT, text,
+ GPK_CHOOSER_COLUMN_ID, package_id, -1);
+ g_free (package_id);
+ package_id = NULL;
+ gtk_list_store_set (helper->priv->list_store, &iter, GPK_CHOOSER_COLUMN_ICON, icon_name, -1);
+ g_free (text);
+ }
+
+ /* show window */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_simple"));
+ gtk_widget_show (widget);
+
+ return TRUE;
+}
+
+/**
+ * gpk_helper_chooser_set_parent:
+ **/
+gboolean
+gpk_helper_chooser_set_parent (GpkHelperChooser *helper, GtkWindow *window)
+{
+ GtkWindow *widget;
+
+ g_return_val_if_fail (GPK_IS_HELPER_CHOOSER (helper), FALSE);
+ g_return_val_if_fail (window != NULL, FALSE);
+
+ /* make modal if window set */
+ widget = GTK_WINDOW (gtk_builder_get_object (helper->priv->builder, "dialog_simple"));
+ gtk_window_set_transient_for (widget, window);
+ gtk_window_set_modal (widget, TRUE);
+
+ /* this is a modal popup, so don't show a window title */
+ gtk_window_set_title (widget, "");
+
+ return TRUE;
+}
+
+/**
+ * gpk_helper_chooser_class_init:
+ * @klass: The GpkHelperChooserClass
+ **/
+static void
+gpk_helper_chooser_class_init (GpkHelperChooserClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gpk_helper_chooser_finalize;
+ g_type_class_add_private (klass, sizeof (GpkHelperChooserPrivate));
+ signals [GPK_HELPER_CHOOSER_EVENT] =
+ g_signal_new ("event",
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GpkHelperChooserClass, event),
+ NULL, NULL, gpk_marshal_VOID__UINT_STRING,
+ G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_STRING);
+}
+
+/**
+ * gpk_helper_chooser_init:
+ **/
+static void
+gpk_helper_chooser_init (GpkHelperChooser *helper)
+{
+ GtkWidget *widget;
+ guint retval;
+ GError *error = NULL;
+ GtkWidget *button;
+ GtkTreeSelection *selection;
+
+ helper->priv = GPK_HELPER_CHOOSER_GET_PRIVATE (helper);
+
+ helper->priv->package_id = NULL;
+
+ /* get UI */
+ helper->priv->builder = gtk_builder_new ();
+ retval = gtk_builder_add_from_file (helper->priv->builder, GPK_DATA "/gpk-log.ui", &error);
+ if (error != NULL) {
+ egg_warning ("failed to load ui: %s", error->message);
+ g_error_free (error);
+ }
+
+ /* connect up default actions */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_simple"));
+ g_signal_connect (widget, "delete_event", G_CALLBACK (gpk_helper_chooser_button_cancel_cb), helper);
+
+ /* set icon name */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_simple"));
+ gtk_window_set_icon_name (GTK_WINDOW (widget), GPK_ICON_SOFTWARE_INSTALLER);
+ gtk_window_set_title (GTK_WINDOW (widget), _("Applications that can open this type of file"));
+
+ /* set a size, if the screen allows */
+ gpk_window_set_size_request (GTK_WINDOW (widget), 600, 300);
+
+ /* connect up buttons */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "button_help"));
+ g_signal_connect (widget, "clicked", G_CALLBACK (gpk_helper_chooser_button_help_cb), helper);
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "button_close"));
+ g_signal_connect (widget, "clicked", G_CALLBACK (gpk_helper_chooser_button_cancel_cb), helper);
+
+ /* TRANSLATORS: button label, install */
+ button = gtk_button_new_with_mnemonic (_("_Install"));
+ g_signal_connect (button, "clicked", G_CALLBACK (gpk_helper_chooser_button_install_cb), helper);
+
+ /* TRANSLATORS: button tooltip */
+ gtk_widget_set_tooltip_text (button, _("Install package"));
+
+ /* add to box */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_simple"));
+ widget = gtk_dialog_get_action_area (GTK_DIALOG(widget));
+ gtk_box_pack_start (GTK_BOX (widget), button, FALSE, FALSE, 0);
+ gtk_widget_show (button);
+
+ /* hide the filter box */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "hbox_filter"));
+ gtk_widget_hide (widget);
+
+ /* hide the refresh button */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "button_refresh"));
+ gtk_widget_hide (widget);
+
+ /* create list stores */
+ helper->priv->list_store = gtk_list_store_new (GPK_CHOOSER_COLUMN_LAST, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+ /* create package_id tree view */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "treeview_simple"));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (widget),
+ GTK_TREE_MODEL (helper->priv->list_store));
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (gpk_helper_chooser_treeview_clicked_cb), helper);
+
+ /* add columns to the tree view */
+ pk_treeview_add_general_columns (GTK_TREE_VIEW (widget));
+ gtk_tree_view_columns_autosize (GTK_TREE_VIEW (widget));
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (widget), FALSE);
+
+ /* use PkDesktop to get better icon */
+ helper->priv->desktop = pk_desktop_new ();
+}
+
+/**
+ * gpk_helper_chooser_finalize:
+ **/
+static void
+gpk_helper_chooser_finalize (GObject *object)
+{
+ GtkWidget *widget;
+ GpkHelperChooser *helper;
+
+ g_return_if_fail (GPK_IS_HELPER_CHOOSER (object));
+
+ helper = GPK_HELPER_CHOOSER (object);
+
+ /* hide window */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_simple"));
+ if (GTK_IS_WIDGET (widget))
+ gtk_widget_hide (widget);
+ g_free (helper->priv->package_id);
+ g_object_unref (helper->priv->builder);
+ g_object_unref (helper->priv->desktop);
+
+ G_OBJECT_CLASS (gpk_helper_chooser_parent_class)->finalize (object);
+}
+
+/**
+ * gpk_helper_chooser_new:
+ **/
+GpkHelperChooser *
+gpk_helper_chooser_new (void)
+{
+ GpkHelperChooser *helper;
+ helper = g_object_new (GPK_TYPE_HELPER_CHOOSER, NULL);
+ return GPK_HELPER_CHOOSER (helper);
+}
+
Added: trunk/src/gpk-helper-chooser.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-helper-chooser.h Tue Apr 14 16:28:59 2009
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GPK_HELPER_CHOOSER_H
+#define __GPK_HELPER_CHOOSER_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <packagekit-glib/packagekit.h>
+
+G_BEGIN_DECLS
+
+#define GPK_TYPE_HELPER_CHOOSER (gpk_helper_chooser_get_type ())
+#define GPK_HELPER_CHOOSER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GPK_TYPE_HELPER_CHOOSER, GpkHelperChooser))
+#define GPK_HELPER_CHOOSER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GPK_TYPE_HELPER_CHOOSER, GpkHelperChooserClass))
+#define GPK_IS_HELPER_CHOOSER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GPK_TYPE_HELPER_CHOOSER))
+#define GPK_IS_HELPER_CHOOSER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GPK_TYPE_HELPER_CHOOSER))
+#define GPK_HELPER_CHOOSER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GPK_TYPE_HELPER_CHOOSER, GpkHelperChooserClass))
+#define GPK_HELPER_CHOOSER_ERROR (gpk_helper_chooser_error_quark ())
+#define GPK_HELPER_CHOOSER_TYPE_ERROR (gpk_helper_chooser_error_get_type ())
+
+typedef struct GpkHelperChooserPrivate GpkHelperChooserPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GpkHelperChooserPrivate *priv;
+} GpkHelperChooser;
+
+typedef struct
+{
+ void (* event) (GpkHelperChooser *helper,
+ GtkResponseType type,
+ const gchar *package_id);
+ GObjectClass parent_class;
+} GpkHelperChooserClass;
+
+GType gpk_helper_chooser_get_type (void);
+GpkHelperChooser *gpk_helper_chooser_new (void);
+gboolean gpk_helper_chooser_set_parent (GpkHelperChooser *helper,
+ GtkWindow *window);
+gboolean gpk_helper_chooser_show (GpkHelperChooser *helper,
+ PkPackageList *list);
+
+G_END_DECLS
+
+#endif /* __GPK_HELPER_CHOOSER_H */
Added: trunk/src/gpk-helper-deps-install.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-helper-deps-install.c Tue Apr 14 16:28:59 2009
@@ -0,0 +1,198 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gconf/gconf-client.h>
+
+#include "gpk-helper-deps-install.h"
+#include "gpk-marshal.h"
+#include "gpk-gnome.h"
+#include "gpk-common.h"
+#include "gpk-dialog.h"
+
+#include "egg-debug.h"
+
+static void gpk_helper_deps_install_finalize (GObject *object);
+
+#define GPK_HELPER_DEPS_INSTALL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPK_TYPE_HELPER_DEPS_INSTALL, GpkHelperDepsInstallPrivate))
+
+struct GpkHelperDepsInstallPrivate
+{
+ GtkWindow *window;
+ GConfClient *gconf_client;
+};
+
+enum {
+ GPK_HELPER_DEPS_INSTALL_EVENT,
+ GPK_HELPER_DEPS_INSTALL_LAST_SIGNAL
+};
+
+static guint signals [GPK_HELPER_DEPS_INSTALL_LAST_SIGNAL] = { 0 };
+G_DEFINE_TYPE (GpkHelperDepsInstall, gpk_helper_deps_install, G_TYPE_OBJECT)
+
+/**
+ * gpk_helper_deps_install_show:
+ *
+ * Return value: if we agreed
+ **/
+gboolean
+gpk_helper_deps_install_show (GpkHelperDepsInstall *helper, GPtrArray *packages, PkPackageList *deps_list)
+{
+ gchar *name = NULL;
+ gchar *title = NULL;
+ gchar *message = NULL;
+ gchar **package_ids = NULL;
+ guint length;
+ gboolean ret;
+ GtkWidget *dialog;
+ GtkResponseType response;
+
+ /* empty list */
+ length = pk_package_list_get_size (deps_list);
+ if (length == 0) {
+ g_signal_emit (helper, signals [GPK_HELPER_DEPS_INSTALL_EVENT], 0, GTK_RESPONSE_YES);
+ goto out;
+ }
+
+ /* have we previously said we don't want to be shown the confirmation */
+ ret = gconf_client_get_bool (helper->priv->gconf_client, GPK_CONF_SHOW_DEPENDS, NULL);
+ if (!ret) {
+ egg_debug ("we've said we don't want the dep dialog");
+ g_signal_emit (helper, signals [GPK_HELPER_DEPS_INSTALL_EVENT], 0, GTK_RESPONSE_YES);
+ goto out;
+ }
+
+ /* TRANSLATORS: title: tell the user we have to install additional packages */
+ title = g_strdup_printf (ngettext ("%i additional package also has to be installed",
+ "%i additional packages also have to be installed",
+ length), length);
+
+ package_ids = pk_ptr_array_to_strv (packages);
+ name = gpk_dialog_package_id_name_join_locale (package_ids);
+
+ /* TRANSLATORS: message: describe in detail why it must happen */
+ message = g_strdup_printf (ngettext ("To install %s, an additional package also has to be downloaded.",
+ "To install %s, additional packages also have to be downloaded.",
+ length), name);
+
+ dialog = gtk_message_dialog_new (helper->priv->window, GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO, GTK_BUTTONS_CANCEL, "%s", title);
+ gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", message);
+ gpk_dialog_embed_package_list_widget (GTK_DIALOG (dialog), deps_list);
+ gpk_dialog_embed_do_not_show_widget (GTK_DIALOG (dialog), GPK_CONF_SHOW_DEPENDS);
+// gtk_dialog_add_button (GTK_DIALOG (dialog), "help", GTK_RESPONSE_HELP);
+ /* TRANSLATORS: this is button text */
+ gtk_dialog_add_button (GTK_DIALOG (dialog), _("Install"), GTK_RESPONSE_YES);
+
+ /* set icon name */
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), GPK_ICON_SOFTWARE_INSTALLER);
+
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+
+ /* yes / no */
+ if (response == GTK_RESPONSE_YES) {
+ g_signal_emit (helper, signals [GPK_HELPER_DEPS_INSTALL_EVENT], 0, response);
+// } else if (response == GTK_RESPONSE_HELP) {
+// gpk_gnome_help ("dialog-install-other-packages");
+ } else {
+ g_signal_emit (helper, signals [GPK_HELPER_DEPS_INSTALL_EVENT], 0, GTK_RESPONSE_NO);
+ }
+out:
+ g_strfreev (package_ids);
+ g_free (name);
+ g_free (title);
+ g_free (message);
+ return TRUE;
+}
+
+/**
+ * gpk_helper_deps_install_set_parent:
+ **/
+gboolean
+gpk_helper_deps_install_set_parent (GpkHelperDepsInstall *helper, GtkWindow *window)
+{
+ g_return_val_if_fail (GPK_IS_HELPER_DEPS_INSTALL (helper), FALSE);
+ g_return_val_if_fail (window != NULL, FALSE);
+
+ helper->priv->window = window;
+ return TRUE;
+}
+
+/**
+ * gpk_helper_deps_install_class_init:
+ * @klass: The GpkHelperDepsInstallClass
+ **/
+static void
+gpk_helper_deps_install_class_init (GpkHelperDepsInstallClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gpk_helper_deps_install_finalize;
+ g_type_class_add_private (klass, sizeof (GpkHelperDepsInstallPrivate));
+ signals [GPK_HELPER_DEPS_INSTALL_EVENT] =
+ g_signal_new ("event",
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GpkHelperDepsInstallClass, event),
+ NULL, NULL, g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
+}
+
+/**
+ * gpk_helper_deps_install_init:
+ **/
+static void
+gpk_helper_deps_install_init (GpkHelperDepsInstall *helper)
+{
+ helper->priv = GPK_HELPER_DEPS_INSTALL_GET_PRIVATE (helper);
+ helper->priv->window = NULL;
+ helper->priv->gconf_client = gconf_client_get_default ();
+}
+
+/**
+ * gpk_helper_deps_install_finalize:
+ **/
+static void
+gpk_helper_deps_install_finalize (GObject *object)
+{
+ GpkHelperDepsInstall *helper;
+
+ g_return_if_fail (GPK_IS_HELPER_DEPS_INSTALL (object));
+
+ helper = GPK_HELPER_DEPS_INSTALL (object);
+ g_object_unref (helper->priv->gconf_client);
+
+ G_OBJECT_CLASS (gpk_helper_deps_install_parent_class)->finalize (object);
+}
+
+/**
+ * gpk_helper_deps_install_new:
+ **/
+GpkHelperDepsInstall *
+gpk_helper_deps_install_new (void)
+{
+ GpkHelperDepsInstall *helper;
+ helper = g_object_new (GPK_TYPE_HELPER_DEPS_INSTALL, NULL);
+ return GPK_HELPER_DEPS_INSTALL (helper);
+}
+
Added: trunk/src/gpk-helper-deps-install.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-helper-deps-install.h Tue Apr 14 16:28:59 2009
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GPK_HELPER_DEPS_INSTALL_H
+#define __GPK_HELPER_DEPS_INSTALL_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <packagekit-glib/packagekit.h>
+
+G_BEGIN_DECLS
+
+#define GPK_TYPE_HELPER_DEPS_INSTALL (gpk_helper_deps_install_get_type ())
+#define GPK_HELPER_DEPS_INSTALL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GPK_TYPE_HELPER_DEPS_INSTALL, GpkHelperDepsInstall))
+#define GPK_HELPER_DEPS_INSTALL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GPK_TYPE_HELPER_DEPS_INSTALL, GpkHelperDepsInstallClass))
+#define GPK_IS_HELPER_DEPS_INSTALL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GPK_TYPE_HELPER_DEPS_INSTALL))
+#define GPK_IS_HELPER_DEPS_INSTALL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GPK_TYPE_HELPER_DEPS_INSTALL))
+#define GPK_HELPER_DEPS_INSTALL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GPK_TYPE_HELPER_DEPS_INSTALL, GpkHelperDepsInstallClass))
+#define GPK_HELPER_DEPS_INSTALL_ERROR (gpk_helper_deps_install_error_quark ())
+#define GPK_HELPER_DEPS_INSTALL_TYPE_ERROR (gpk_helper_deps_install_error_get_type ())
+
+typedef struct GpkHelperDepsInstallPrivate GpkHelperDepsInstallPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GpkHelperDepsInstallPrivate *priv;
+} GpkHelperDepsInstall;
+
+typedef struct
+{
+ void (* event) (GpkHelperDepsInstall *helper,
+ GtkResponseType type);
+ GObjectClass parent_class;
+} GpkHelperDepsInstallClass;
+
+GType gpk_helper_deps_install_get_type (void);
+GpkHelperDepsInstall *gpk_helper_deps_install_new (void);
+gboolean gpk_helper_deps_install_set_parent (GpkHelperDepsInstall *helper,
+ GtkWindow *window);
+gboolean gpk_helper_deps_install_show (GpkHelperDepsInstall *helper,
+ GPtrArray *packages,
+ PkPackageList *deps_list);
+
+G_END_DECLS
+
+#endif /* __GPK_HELPER_DEPS_INSTALL_H */
Added: trunk/src/gpk-helper-deps-remove.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-helper-deps-remove.c Tue Apr 14 16:28:59 2009
@@ -0,0 +1,185 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gpk-helper-deps-remove.h"
+#include "gpk-marshal.h"
+#include "gpk-gnome.h"
+#include "gpk-common.h"
+#include "gpk-dialog.h"
+
+#include "egg-debug.h"
+
+static void gpk_helper_deps_remove_finalize (GObject *object);
+
+#define GPK_HELPER_DEPS_REMOVE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPK_TYPE_HELPER_DEPS_REMOVE, GpkHelperDepsRemovePrivate))
+
+struct GpkHelperDepsRemovePrivate
+{
+ GtkWindow *window;
+};
+
+enum {
+ GPK_HELPER_DEPS_REMOVE_EVENT,
+ GPK_HELPER_DEPS_REMOVE_LAST_SIGNAL
+};
+
+static guint signals [GPK_HELPER_DEPS_REMOVE_LAST_SIGNAL] = { 0 };
+G_DEFINE_TYPE (GpkHelperDepsRemove, gpk_helper_deps_remove, G_TYPE_OBJECT)
+
+/**
+ * gpk_helper_deps_remove_show:
+ *
+ * Return value: if we agreed
+ **/
+gboolean
+gpk_helper_deps_remove_show (GpkHelperDepsRemove *helper, GPtrArray *packages, PkPackageList *deps_list)
+{
+ gchar *name = NULL;
+ gchar *title = NULL;
+ gchar *message = NULL;
+ gchar **package_ids = NULL;
+ guint length;
+ GtkWidget *dialog;
+ GtkResponseType response;
+
+ /* empty list */
+ length = pk_package_list_get_size (deps_list);
+ if (length == 0) {
+ g_signal_emit (helper, signals [GPK_HELPER_DEPS_REMOVE_EVENT], 0, GTK_RESPONSE_YES);
+ goto out;
+ }
+
+ /* TRANSLATORS: title: show the number of other packages we depend on */
+ title = g_strdup_printf (ngettext ("%i additional package also has to be removed",
+ "%i additional packages also have to be removed",
+ length), length);
+
+ package_ids = pk_ptr_array_to_strv (packages);
+ name = gpk_dialog_package_id_name_join_locale (package_ids);
+
+ /* TRANSLATORS: message: describe in detail why it must happen */
+ message = g_strdup_printf (ngettext ("To remove %s other packages that depend on it must also be removed.",
+ "To remove %s other packages that depend on them must also be removed.",
+ packages->len), name);
+
+ dialog = gtk_message_dialog_new (helper->priv->window, GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO, GTK_BUTTONS_CANCEL, "%s", title);
+ gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", message);
+ gpk_dialog_embed_package_list_widget (GTK_DIALOG (dialog), deps_list);
+
+// gtk_dialog_add_button (GTK_DIALOG (dialog), "help", GTK_RESPONSE_HELP);
+ /* TRANSLATORS: this is button text */
+ gtk_dialog_add_button (GTK_DIALOG (dialog), _("Remove"), GTK_RESPONSE_YES);
+
+ /* set icon name */
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), GPK_ICON_SOFTWARE_INSTALLER);
+
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+
+ /* yes / no */
+ if (response == GTK_RESPONSE_YES) {
+ g_signal_emit (helper, signals [GPK_HELPER_DEPS_REMOVE_EVENT], 0, response);
+// } else if (response == GTK_RESPONSE_HELP) {
+// gpk_gnome_help ("dialog-remove-other-packages");
+ } else {
+ g_signal_emit (helper, signals [GPK_HELPER_DEPS_REMOVE_EVENT], 0, GTK_RESPONSE_NO);
+ }
+out:
+ g_strfreev (package_ids);
+ g_free (name);
+ g_free (title);
+ g_free (message);
+ return TRUE;
+}
+
+/**
+ * gpk_helper_deps_remove_set_parent:
+ **/
+gboolean
+gpk_helper_deps_remove_set_parent (GpkHelperDepsRemove *helper, GtkWindow *window)
+{
+ g_return_val_if_fail (GPK_IS_HELPER_DEPS_REMOVE (helper), FALSE);
+ g_return_val_if_fail (window != NULL, FALSE);
+
+ helper->priv->window = window;
+ return TRUE;
+}
+
+/**
+ * gpk_helper_deps_remove_class_init:
+ * @klass: The GpkHelperDepsRemoveClass
+ **/
+static void
+gpk_helper_deps_remove_class_init (GpkHelperDepsRemoveClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gpk_helper_deps_remove_finalize;
+ g_type_class_add_private (klass, sizeof (GpkHelperDepsRemovePrivate));
+ signals [GPK_HELPER_DEPS_REMOVE_EVENT] =
+ g_signal_new ("event",
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GpkHelperDepsRemoveClass, event),
+ NULL, NULL, g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
+}
+
+/**
+ * gpk_helper_deps_remove_init:
+ **/
+static void
+gpk_helper_deps_remove_init (GpkHelperDepsRemove *helper)
+{
+ helper->priv = GPK_HELPER_DEPS_REMOVE_GET_PRIVATE (helper);
+ helper->priv->window = NULL;
+}
+
+/**
+ * gpk_helper_deps_remove_finalize:
+ **/
+static void
+gpk_helper_deps_remove_finalize (GObject *object)
+{
+ GpkHelperDepsRemove *helper;
+
+ g_return_if_fail (GPK_IS_HELPER_DEPS_REMOVE (object));
+
+ helper = GPK_HELPER_DEPS_REMOVE (object);
+
+ G_OBJECT_CLASS (gpk_helper_deps_remove_parent_class)->finalize (object);
+}
+
+/**
+ * gpk_helper_deps_remove_new:
+ **/
+GpkHelperDepsRemove *
+gpk_helper_deps_remove_new (void)
+{
+ GpkHelperDepsRemove *helper;
+ helper = g_object_new (GPK_TYPE_HELPER_DEPS_REMOVE, NULL);
+ return GPK_HELPER_DEPS_REMOVE (helper);
+}
+
Added: trunk/src/gpk-helper-deps-remove.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-helper-deps-remove.h Tue Apr 14 16:28:59 2009
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GPK_HELPER_DEPS_REMOVE_H
+#define __GPK_HELPER_DEPS_REMOVE_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <packagekit-glib/packagekit.h>
+
+G_BEGIN_DECLS
+
+#define GPK_TYPE_HELPER_DEPS_REMOVE (gpk_helper_deps_remove_get_type ())
+#define GPK_HELPER_DEPS_REMOVE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GPK_TYPE_HELPER_DEPS_REMOVE, GpkHelperDepsRemove))
+#define GPK_HELPER_DEPS_REMOVE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GPK_TYPE_HELPER_DEPS_REMOVE, GpkHelperDepsRemoveClass))
+#define GPK_IS_HELPER_DEPS_REMOVE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GPK_TYPE_HELPER_DEPS_REMOVE))
+#define GPK_IS_HELPER_DEPS_REMOVE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GPK_TYPE_HELPER_DEPS_REMOVE))
+#define GPK_HELPER_DEPS_REMOVE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GPK_TYPE_HELPER_DEPS_REMOVE, GpkHelperDepsRemoveClass))
+#define GPK_HELPER_DEPS_REMOVE_ERROR (gpk_helper_deps_remove_error_quark ())
+#define GPK_HELPER_DEPS_REMOVE_TYPE_ERROR (gpk_helper_deps_remove_error_get_type ())
+
+typedef struct GpkHelperDepsRemovePrivate GpkHelperDepsRemovePrivate;
+
+typedef struct
+{
+ GObject parent;
+ GpkHelperDepsRemovePrivate *priv;
+} GpkHelperDepsRemove;
+
+typedef struct
+{
+ void (* event) (GpkHelperDepsRemove *helper,
+ GtkResponseType type);
+ GObjectClass parent_class;
+} GpkHelperDepsRemoveClass;
+
+GType gpk_helper_deps_remove_get_type (void);
+GpkHelperDepsRemove *gpk_helper_deps_remove_new (void);
+gboolean gpk_helper_deps_remove_set_parent (GpkHelperDepsRemove *helper,
+ GtkWindow *window);
+gboolean gpk_helper_deps_remove_show (GpkHelperDepsRemove *helper,
+ GPtrArray *packages,
+ PkPackageList *deps_list);
+
+G_END_DECLS
+
+#endif /* __GPK_HELPER_DEPS_REMOVE_H */
Modified: trunk/src/gpk-helper-eula.c
==============================================================================
--- trunk/src/gpk-helper-eula.c (original)
+++ trunk/src/gpk-helper-eula.c Tue Apr 14 16:28:59 2009
@@ -133,17 +133,18 @@
gboolean
gpk_helper_eula_set_parent (GpkHelperEula *helper, GtkWindow *window)
{
- GtkWidget *widget;
+ GtkWindow *widget;
g_return_val_if_fail (GPK_IS_HELPER_EULA (helper), FALSE);
g_return_val_if_fail (window != NULL, FALSE);
/* make modal if window set */
- widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_eula"));
- gtk_window_set_transient_for (GTK_WINDOW (widget), window);
+ widget = GTK_WINDOW (gtk_builder_get_object (helper->priv->builder, "dialog_eula"));
+ gtk_window_set_transient_for (widget, window);
+ gtk_window_set_modal (widget, TRUE);
/* this is a modal popup, so don't show a window title */
- gtk_window_set_title (GTK_WINDOW (widget), "");
+ gtk_window_set_title (widget, "");
return TRUE;
}
Added: trunk/src/gpk-helper-media-change.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-helper-media-change.c Tue Apr 14 16:28:59 2009
@@ -0,0 +1,187 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gpk-helper-media-change.h"
+#include "gpk-enum.h"
+#include "gpk-common.h"
+
+#include "egg-debug.h"
+
+static void gpk_helper_media_change_finalize (GObject *object);
+
+#define GPK_HELPER_MEDIA_CHANGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPK_TYPE_HELPER_MEDIA_CHANGE, GpkHelperMediaChangePrivate))
+
+struct GpkHelperMediaChangePrivate
+{
+ GtkWindow *window;
+ guint idle_id;
+ PkMediaTypeEnum type;
+ gchar *media_id;
+ gchar *media_text;
+};
+
+enum {
+ GPK_HELPER_MEDIA_CHANGE_EVENT,
+ GPK_HELPER_MEDIA_CHANGE_LAST_SIGNAL
+};
+
+static guint signals [GPK_HELPER_MEDIA_CHANGE_LAST_SIGNAL] = { 0 };
+G_DEFINE_TYPE (GpkHelperMediaChange, gpk_helper_media_change, G_TYPE_OBJECT)
+
+/**
+ * gpk_helper_media_change_show_idle_cb:
+ *
+ * Return value: if we agreed
+ **/
+gboolean
+gpk_helper_media_change_show_idle_cb (GpkHelperMediaChange *helper)
+{
+ const gchar *name = NULL;
+ gchar *message = NULL;
+ GtkWidget *dialog;
+ GtkResponseType response;
+
+ name = gpk_media_type_enum_to_localised_text (helper->priv->type);
+ /* TRANSLATORS: dialog body, explains to the user that they need to insert a disk to continue. The first replacement is DVD, CD etc */
+ message = g_strdup_printf (_("Additional media is required. Please insert the %s labeled '%s' and click continue"), name, helper->priv->media_text);
+
+ dialog = gtk_message_dialog_new (helper->priv->window, GTK_DIALOG_DESTROY_WITH_PARENT,
+ /* TRANSLATORS: this is the window title when a new cd or dvd is required */
+ GTK_MESSAGE_INFO, GTK_BUTTONS_CANCEL, _("A media change is required"));
+ gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", message);
+
+ /* TRANSLATORS: this is button text */
+ gtk_dialog_add_button (GTK_DIALOG (dialog), _("Continue"), GTK_RESPONSE_YES);
+
+ /* set icon name */
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), GPK_ICON_SOFTWARE_INSTALLER);
+
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+
+ /* yes / no */
+ if (response == GTK_RESPONSE_YES) {
+ g_signal_emit (helper, signals [GPK_HELPER_MEDIA_CHANGE_EVENT], 0, response);
+ } else {
+ g_signal_emit (helper, signals [GPK_HELPER_MEDIA_CHANGE_EVENT], 0, GTK_RESPONSE_NO);
+ }
+ g_free (message);
+
+ /* never repeat */
+ helper->priv->media_id = 0;
+ return FALSE;
+}
+
+/**
+ * gpk_helper_media_change_show:
+ *
+ * Return value: if we agreed
+ **/
+gboolean
+gpk_helper_media_change_show (GpkHelperMediaChange *helper, PkMediaTypeEnum type, const gchar *media_id, const gchar *media_text)
+{
+ g_return_val_if_fail (GPK_IS_HELPER_MEDIA_CHANGE (helper), FALSE);
+ g_return_val_if_fail (helper->priv->media_id == 0, FALSE);
+
+ helper->priv->type = type;
+ helper->priv->media_id = g_strdup (media_id);
+ helper->priv->media_text = g_strdup (media_text);
+ helper->priv->idle_id = g_idle_add ((GSourceFunc) gpk_helper_media_change_show_idle_cb, helper);
+ return TRUE;
+}
+
+/**
+ * gpk_helper_media_change_set_parent:
+ **/
+gboolean
+gpk_helper_media_change_set_parent (GpkHelperMediaChange *helper, GtkWindow *window)
+{
+ g_return_val_if_fail (GPK_IS_HELPER_MEDIA_CHANGE (helper), FALSE);
+ g_return_val_if_fail (window != NULL, FALSE);
+
+ helper->priv->window = window;
+ return TRUE;
+}
+
+/**
+ * gpk_helper_media_change_class_init:
+ * @klass: The GpkHelperMediaChangeClass
+ **/
+static void
+gpk_helper_media_change_class_init (GpkHelperMediaChangeClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gpk_helper_media_change_finalize;
+ g_type_class_add_private (klass, sizeof (GpkHelperMediaChangePrivate));
+ signals [GPK_HELPER_MEDIA_CHANGE_EVENT] =
+ g_signal_new ("event",
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GpkHelperMediaChangeClass, event),
+ NULL, NULL, g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
+}
+
+/**
+ * gpk_helper_media_change_init:
+ **/
+static void
+gpk_helper_media_change_init (GpkHelperMediaChange *helper)
+{
+ helper->priv = GPK_HELPER_MEDIA_CHANGE_GET_PRIVATE (helper);
+ helper->priv->window = NULL;
+ helper->priv->idle_id = 0;
+}
+
+/**
+ * gpk_helper_media_change_finalize:
+ **/
+static void
+gpk_helper_media_change_finalize (GObject *object)
+{
+ GpkHelperMediaChange *helper;
+
+ g_return_if_fail (GPK_IS_HELPER_MEDIA_CHANGE (object));
+
+ helper = GPK_HELPER_MEDIA_CHANGE (object);
+ if (helper->priv->idle_id != 0)
+ g_source_remove (helper->priv->idle_id);
+ g_free (helper->priv->media_id);
+ g_free (helper->priv->media_text);
+
+ G_OBJECT_CLASS (gpk_helper_media_change_parent_class)->finalize (object);
+}
+
+/**
+ * gpk_helper_media_change_new:
+ **/
+GpkHelperMediaChange *
+gpk_helper_media_change_new (void)
+{
+ GpkHelperMediaChange *helper;
+ helper = g_object_new (GPK_TYPE_HELPER_MEDIA_CHANGE, NULL);
+ return GPK_HELPER_MEDIA_CHANGE (helper);
+}
+
Added: trunk/src/gpk-helper-media-change.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-helper-media-change.h Tue Apr 14 16:28:59 2009
@@ -0,0 +1,66 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GPK_HELPER_MEDIA_CHANGE_H
+#define __GPK_HELPER_MEDIA_CHANGE_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <packagekit-glib/packagekit.h>
+
+G_BEGIN_DECLS
+
+#define GPK_TYPE_HELPER_MEDIA_CHANGE (gpk_helper_media_change_get_type ())
+#define GPK_HELPER_MEDIA_CHANGE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GPK_TYPE_HELPER_MEDIA_CHANGE, GpkHelperMediaChange))
+#define GPK_HELPER_MEDIA_CHANGE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GPK_TYPE_HELPER_MEDIA_CHANGE, GpkHelperMediaChangeClass))
+#define GPK_IS_HELPER_MEDIA_CHANGE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GPK_TYPE_HELPER_MEDIA_CHANGE))
+#define GPK_IS_HELPER_MEDIA_CHANGE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GPK_TYPE_HELPER_MEDIA_CHANGE))
+#define GPK_HELPER_MEDIA_CHANGE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GPK_TYPE_HELPER_MEDIA_CHANGE, GpkHelperMediaChangeClass))
+#define GPK_HELPER_MEDIA_CHANGE_ERROR (gpk_helper_media_change_error_quark ())
+#define GPK_HELPER_MEDIA_CHANGE_TYPE_ERROR (gpk_helper_media_change_error_get_type ())
+
+typedef struct GpkHelperMediaChangePrivate GpkHelperMediaChangePrivate;
+
+typedef struct
+{
+ GObject parent;
+ GpkHelperMediaChangePrivate *priv;
+} GpkHelperMediaChange;
+
+typedef struct
+{
+ void (* event) (GpkHelperMediaChange *helper,
+ GtkResponseType type);
+ GObjectClass parent_class;
+} GpkHelperMediaChangeClass;
+
+GType gpk_helper_media_change_get_type (void);
+GpkHelperMediaChange *gpk_helper_media_change_new (void);
+gboolean gpk_helper_media_change_set_parent (GpkHelperMediaChange *helper,
+ GtkWindow *window);
+gboolean gpk_helper_media_change_show (GpkHelperMediaChange *helper,
+ PkMediaTypeEnum type,
+ const gchar *media_id,
+ const gchar *media_text);
+
+G_END_DECLS
+
+#endif /* __GPK_HELPER_MEDIA_CHANGE_H */
Modified: trunk/src/gpk-helper-repo-signature.c
==============================================================================
--- trunk/src/gpk-helper-repo-signature.c (original)
+++ trunk/src/gpk-helper-repo-signature.c Tue Apr 14 16:28:59 2009
@@ -128,17 +128,18 @@
gboolean
gpk_helper_repo_signature_set_parent (GpkHelperRepoSignature *helper, GtkWindow *window)
{
- GtkWidget *widget;
+ GtkWindow *widget;
g_return_val_if_fail (GPK_IS_HELPER_REPO_SIGNATURE (helper), FALSE);
g_return_val_if_fail (window != NULL, FALSE);
/* make modal if window set */
- widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_gpg"));
- gtk_window_set_transient_for (GTK_WINDOW (widget), window);
+ widget = GTK_WINDOW (gtk_builder_get_object (helper->priv->builder, "dialog_gpg"));
+ gtk_window_set_transient_for (widget, window);
+ gtk_window_set_modal (widget, TRUE);
/* this is a modal popup, so don't show a window title */
- gtk_window_set_title (GTK_WINDOW (widget), "");
+ gtk_window_set_title (widget, "");
return TRUE;
}
Added: trunk/src/gpk-helper-run.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-helper-run.c Tue Apr 14 16:28:59 2009
@@ -0,0 +1,530 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <packagekit-glib/packagekit.h>
+
+#include "gpk-helper-run.h"
+#include "gpk-marshal.h"
+#include "gpk-gnome.h"
+#include "gpk-common.h"
+#include "gpk-desktop.h"
+#include "gpk-enum.h"
+
+#include "egg-debug.h"
+
+static void gpk_helper_run_finalize (GObject *object);
+
+#define GPK_HELPER_RUN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPK_TYPE_HELPER_RUN, GpkHelperRunPrivate))
+
+struct GpkHelperRunPrivate
+{
+ GtkBuilder *builder;
+ GtkListStore *list_store;
+ gchar *full_path;
+};
+
+enum {
+ GPK_CHOOSER_COLUMN_ICON,
+ GPK_CHOOSER_COLUMN_TEXT,
+ GPK_CHOOSER_COLUMN_FULL_PATH,
+ GPK_CHOOSER_COLUMN_LAST
+};
+
+G_DEFINE_TYPE (GpkHelperRun, gpk_helper_run, G_TYPE_OBJECT)
+
+/**
+ * gpk_helper_run_path:
+ **/
+static gboolean
+gpk_helper_run_path (GpkHelperRun *helper)
+{
+ gboolean ret = FALSE;
+ GError *error = NULL;
+
+ /* check have value */
+ if (helper->priv->full_path == NULL) {
+ egg_warning ("no full path");
+ goto out;
+ }
+
+ ret = g_spawn_command_line_async (helper->priv->full_path, &error);
+ if (!ret) {
+ egg_warning ("failed to run: %s", error->message);
+ g_error_free (error);
+ }
+out:
+ return ret;
+}
+
+/**
+ * gpk_helper_run_button_run_cb:
+ **/
+static void
+gpk_helper_run_button_run_cb (GtkWidget *widget, GpkHelperRun *helper)
+{
+ gpk_helper_run_path (helper);
+}
+
+/**
+ * gpk_helper_run_button_close_cb:
+ **/
+static void
+gpk_helper_run_button_close_cb (GtkWidget *widget, GpkHelperRun *helper)
+{
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_simple"));
+ gtk_widget_hide (widget);
+}
+
+/**
+ * gpk_helper_run_button_help_cb:
+ **/
+static void
+gpk_helper_run_button_help_cb (GtkWidget *widget, GpkHelperRun *helper)
+{
+ /* show the help */
+ gpk_gnome_help ("run");
+}
+
+/**
+ * gpk_helper_run_delete_event_cb:
+ **/
+static gboolean
+gpk_helper_run_delete_event_cb (GtkWidget *widget, GdkEvent *event, GpkHelperRun *helper)
+{
+ /* clear full_path */
+ g_free (helper->priv->full_path);
+ helper->priv->full_path = NULL;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_simple"));
+ gtk_widget_hide (widget);
+ return FALSE;
+}
+
+
+/**
+ * gpk_helper_run_treeview_clicked_cb:
+ **/
+static void
+gpk_helper_run_treeview_clicked_cb (GtkTreeSelection *selection, GpkHelperRun *helper)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ /* This will only work in single or browse selection mode! */
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ g_free (helper->priv->full_path);
+ gtk_tree_model_get (model, &iter, GPK_CHOOSER_COLUMN_FULL_PATH, &helper->priv->full_path, -1);
+
+ /* show full path */
+ egg_debug ("selected row is: %s", helper->priv->full_path);
+ } else {
+ egg_debug ("no row selected");
+ }
+}
+
+/**
+ * gpk_helper_run_row_activated_cb:
+ **/
+static void
+gpk_helper_run_row_activated_cb (GtkTreeView *treeview, GtkTreePath *path,
+ GtkTreeViewColumn *col, GpkHelperRun *helper)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gboolean ret;
+
+ /* get selection */
+ model = gtk_tree_view_get_model (treeview);
+ ret = gtk_tree_model_get_iter (model, &iter, path);
+ if (!ret) {
+ egg_warning ("failed to get selection");
+ return;
+ }
+
+ g_free (helper->priv->full_path);
+ gtk_tree_model_get (model, &iter, GPK_CHOOSER_COLUMN_FULL_PATH, &helper->priv->full_path, -1);
+ gpk_helper_run_path (helper);
+}
+
+/**
+ * pk_treeview_add_general_columns:
+ **/
+static void
+pk_treeview_add_general_columns (GtkTreeView *treeview)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ /* image */
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (renderer, "stock-size", GTK_ICON_SIZE_DIALOG, NULL);
+ /* TRANSLATORS: column for the application icon */
+ column = gtk_tree_view_column_new_with_attributes (_("Icon"), renderer,
+ "icon-name", GPK_CHOOSER_COLUMN_ICON, NULL);
+ gtk_tree_view_append_column (treeview, column);
+
+ /* column for text */
+ renderer = gtk_cell_renderer_text_new ();
+ /* TRANSLATORS: column for the package name */
+ column = gtk_tree_view_column_new_with_attributes (_("Package"), renderer,
+ "markup", GPK_CHOOSER_COLUMN_TEXT, NULL);
+ gtk_tree_view_column_set_sort_column_id (column, GPK_CHOOSER_COLUMN_TEXT);
+ gtk_tree_view_append_column (treeview, column);
+ gtk_tree_view_column_set_expand (column, TRUE);
+}
+
+/**
+ * gpk_helper_run_add_desktop_file:
+ **/
+static gboolean
+gpk_helper_run_add_desktop_file (GpkHelperRun *helper, const gchar *package_id, const gchar *filename)
+{
+ gboolean ret;
+ gchar *icon = NULL;
+ gchar *text = NULL;
+ gchar *fulltext = NULL;
+ gchar *name = NULL;
+ gchar *exec = NULL;
+ gchar *summary = NULL;
+ gchar *joint = NULL;
+ gchar *menu_path = NULL;
+ GtkTreeIter iter;
+ GKeyFile *file;
+ PkPackageId *id;
+ gint weight;
+
+ /* get weight */
+ weight = gpk_desktop_get_file_weight (filename);
+ if (weight < 0) {
+ egg_debug ("ignoring %s", filename);
+ goto out;
+ }
+
+ /* get some data from the desktop file */
+ file = g_key_file_new ();
+ ret = g_key_file_load_from_file (file, filename, G_KEY_FILE_NONE, NULL);
+ if (!ret) {
+ egg_debug ("failed to load %s", filename);
+ goto out;
+ }
+
+ /* get exec */
+ exec = g_key_file_get_string (file, G_KEY_FILE_DESKTOP_GROUP, "TryExec", NULL);
+ if (exec == NULL)
+ exec = g_key_file_get_string (file, G_KEY_FILE_DESKTOP_GROUP, "Exec", NULL);
+
+ /* abandon attempt */
+ if (exec == NULL) {
+ ret = FALSE;
+ goto out;
+ }
+
+ /* get name */
+ text = g_key_file_get_locale_string (file, G_KEY_FILE_DESKTOP_GROUP, "Name", NULL, NULL);
+ if (text != NULL)
+ name = g_markup_escape_text (text, -1);
+ g_free (text);
+
+ /* get icon */
+ icon = g_key_file_get_string (file, G_KEY_FILE_DESKTOP_GROUP, "Icon", NULL);
+ if (icon == NULL || !gpk_desktop_check_icon_valid (icon)) {
+ g_free (icon);
+ icon = g_strdup (gpk_info_enum_to_icon_name (PK_INFO_ENUM_AVAILABLE));
+ }
+
+ /* get summary */
+ text = g_key_file_get_locale_string (file, G_KEY_FILE_DESKTOP_GROUP, "Comment", NULL, NULL);
+ if (text == NULL)
+ text = g_key_file_get_locale_string (file, G_KEY_FILE_DESKTOP_GROUP, "GenericName", NULL, NULL);
+ if (text != NULL)
+ summary = g_markup_escape_text (text, -1);
+ g_free (text);
+
+ /* get application path */
+ text = gpk_desktop_get_menu_path (filename);
+ if (text != NULL)
+ menu_path = g_markup_escape_text (text, -1);
+ g_free (text);
+
+ /* put formatted text into treeview */
+ gtk_list_store_append (helper->priv->list_store, &iter);
+ joint = g_strdup_printf ("%s - %s", name, summary);
+ id = pk_package_id_new_from_string (package_id);
+ text = gpk_package_id_format_twoline (id, joint);
+ if (menu_path != NULL) {
+ /* TRANSLATORS: the path in the menu, e.g. Applications -> Games -> Dave */
+ fulltext = g_strdup_printf("%s\n\n<i>%s</i>", text, menu_path);
+ g_free (text);
+ text = fulltext;
+ }
+ pk_package_id_free (id);
+
+ gtk_list_store_set (helper->priv->list_store, &iter,
+ GPK_CHOOSER_COLUMN_TEXT, fulltext,
+ GPK_CHOOSER_COLUMN_FULL_PATH, exec,
+ GPK_CHOOSER_COLUMN_ICON, icon, -1);
+out:
+ if (file != NULL)
+ g_key_file_free (file);
+ g_free (exec);
+ g_free (icon);
+ g_free (name);
+ g_free (text);
+ g_free (menu_path);
+ g_free (joint);
+ g_free (summary);
+
+ return ret;
+}
+
+/**
+ * gpk_helper_run_add_package_ids:
+ **/
+static guint
+gpk_helper_run_add_package_ids (GpkHelperRun *helper, gchar **package_ids)
+{
+ guint i, j;
+ guint length;
+ guint added = 0;
+ const gchar *filename;
+ GPtrArray *array;
+ gchar **parts;
+ gboolean ret;
+ PkDesktop *desktop;
+
+ /* open database */
+ desktop = pk_desktop_new ();
+ ret = pk_desktop_open_database (desktop, NULL);
+ if (!ret) {
+ egg_debug ("failed to open desktop DB");
+ goto out;
+ }
+
+ /* add each package */
+ length = g_strv_length (package_ids);
+ for (i=0; i<length; i++) {
+ parts = g_strsplit (package_ids[i], ";", 0);
+ array = pk_desktop_get_files_for_package (desktop, parts[0], NULL);
+ if (array != NULL) {
+ for (j=0; j<array->len; j++) {
+ filename = g_ptr_array_index (array, j);
+ ret = gpk_helper_run_add_desktop_file (helper, package_ids[i], filename);
+ if (ret)
+ added++;
+ }
+ g_ptr_array_foreach (array, (GFunc) g_free, NULL);
+ g_ptr_array_free (array, TRUE);
+ }
+ g_strfreev (parts);
+ }
+ g_object_unref (desktop);
+out:
+ return added;
+}
+
+/**
+ * gpk_helper_run_show:
+ *
+ * Return value: if we agreed
+ **/
+gboolean
+gpk_helper_run_show (GpkHelperRun *helper, gchar **package_ids)
+{
+ GtkWidget *widget;
+ guint len;
+
+ g_return_val_if_fail (GPK_IS_HELPER_RUN (helper), FALSE);
+ g_return_val_if_fail (package_ids != NULL, FALSE);
+
+ /* clear old list */
+ gtk_list_store_clear (helper->priv->list_store);
+
+ /* add all the apps */
+ len = gpk_helper_run_add_package_ids (helper, package_ids);
+ if (len == 0) {
+ egg_debug ("no executable file for %s", package_ids[0]);
+ goto out;
+ }
+
+ /* show window */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_simple"));
+ gtk_widget_show (widget);
+out:
+ return TRUE;
+}
+
+/**
+ * gpk_helper_run_set_parent:
+ **/
+gboolean
+gpk_helper_run_set_parent (GpkHelperRun *helper, GtkWindow *window)
+{
+ GtkWindow *widget;
+
+ g_return_val_if_fail (GPK_IS_HELPER_RUN (helper), FALSE);
+ g_return_val_if_fail (window != NULL, FALSE);
+
+ /* make modal if window set */
+ widget = GTK_WINDOW (gtk_builder_get_object (helper->priv->builder, "dialog_simple"));
+ gtk_window_set_transient_for (widget, window);
+ gtk_window_set_modal (widget, TRUE);
+
+ /* this is a modal popup, so don't show a window title */
+ gtk_window_set_title (widget, "");
+
+ return TRUE;
+}
+
+/**
+ * gpk_helper_run_class_init:
+ * @klass: The GpkHelperRunClass
+ **/
+static void
+gpk_helper_run_class_init (GpkHelperRunClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gpk_helper_run_finalize;
+ g_type_class_add_private (klass, sizeof (GpkHelperRunPrivate));
+}
+
+/**
+ * gpk_helper_run_init:
+ **/
+static void
+gpk_helper_run_init (GpkHelperRun *helper)
+{
+ GtkWidget *widget;
+ GtkWidget *button;
+ guint retval;
+ GError *error = NULL;
+ GtkTreeSelection *selection;
+ GtkBox *box;
+
+ helper->priv = GPK_HELPER_RUN_GET_PRIVATE (helper);
+
+ /* initially nothing */
+ helper->priv->full_path = NULL;
+
+ /* get UI */
+ helper->priv->builder = gtk_builder_new ();
+ retval = gtk_builder_add_from_file (helper->priv->builder, GPK_DATA "/gpk-log.ui", &error);
+ if (error != NULL) {
+ egg_warning ("failed to load ui: %s", error->message);
+ g_error_free (error);
+ }
+
+ /* connect up default actions */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_simple"));
+ g_signal_connect (widget, "delete_event", G_CALLBACK (gpk_helper_run_delete_event_cb), helper);
+
+ /* set icon name */
+ gtk_window_set_icon_name (GTK_WINDOW (widget), GPK_ICON_SOFTWARE_INSTALLER);
+
+ /* set a size, if the screen allows */
+ gpk_window_set_size_request (GTK_WINDOW (widget), 600, 300);
+
+ /* connect up buttons */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "button_close"));
+ g_signal_connect (widget, "clicked", G_CALLBACK (gpk_helper_run_button_close_cb), helper);
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "button_help"));
+ g_signal_connect (widget, "clicked", G_CALLBACK (gpk_helper_run_button_help_cb), helper);
+
+ /* hide the filter box */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "hbox_filter"));
+ gtk_widget_hide (widget);
+
+ /* hide the refresh button */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "button_refresh"));
+ gtk_widget_hide (widget);
+
+ /* set icon name */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_simple"));
+ gtk_window_set_icon_name (GTK_WINDOW (widget), GPK_ICON_SOFTWARE_INSTALLER);
+ /* TRANSLATORS: window title: do we want to execute a program we just installed? */
+ gtk_window_set_title (GTK_WINDOW (widget), _("Run new application?"));
+
+ /* add run button */
+ button = gtk_button_new_with_mnemonic (_("_Run"));
+ box = GTK_BOX (gtk_dialog_get_action_area (GTK_DIALOG (widget)));
+ gtk_box_pack_start (box, button, FALSE, FALSE, 0);
+ gtk_widget_show (button);
+ g_signal_connect (button, "clicked", G_CALLBACK (gpk_helper_run_button_run_cb), helper);
+
+ /* create list stores */
+ helper->priv->list_store = gtk_list_store_new (GPK_CHOOSER_COLUMN_LAST, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+ /* create package_id tree view */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "treeview_simple"));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (widget),
+ GTK_TREE_MODEL (helper->priv->list_store));
+ g_signal_connect (GTK_TREE_VIEW (widget), "row-activated",
+ G_CALLBACK (gpk_helper_run_row_activated_cb), helper);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (gpk_helper_run_treeview_clicked_cb), helper);
+
+ /* add columns to the tree view */
+ pk_treeview_add_general_columns (GTK_TREE_VIEW (widget));
+ gtk_tree_view_columns_autosize (GTK_TREE_VIEW (widget));
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (widget), FALSE);
+}
+
+/**
+ * gpk_helper_run_finalize:
+ **/
+static void
+gpk_helper_run_finalize (GObject *object)
+{
+ GtkWidget *widget;
+ GpkHelperRun *helper;
+
+ g_return_if_fail (GPK_IS_HELPER_RUN (object));
+
+ helper = GPK_HELPER_RUN (object);
+
+ /* hide window */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_simple"));
+ if (GTK_IS_WIDGET (widget))
+ gtk_widget_hide (widget);
+ g_free (helper->priv->full_path);
+ g_object_unref (helper->priv->builder);
+ g_object_unref (helper->priv->list_store);
+
+ G_OBJECT_CLASS (gpk_helper_run_parent_class)->finalize (object);
+}
+
+/**
+ * gpk_helper_run_new:
+ **/
+GpkHelperRun *
+gpk_helper_run_new (void)
+{
+ GpkHelperRun *helper;
+ helper = g_object_new (GPK_TYPE_HELPER_RUN, NULL);
+ return GPK_HELPER_RUN (helper);
+}
+
Added: trunk/src/gpk-helper-run.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-helper-run.h Tue Apr 14 16:28:59 2009
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GPK_HELPER_RUN_H
+#define __GPK_HELPER_RUN_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GPK_TYPE_HELPER_RUN (gpk_helper_run_get_type ())
+#define GPK_HELPER_RUN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GPK_TYPE_HELPER_RUN, GpkHelperRun))
+#define GPK_HELPER_RUN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GPK_TYPE_HELPER_RUN, GpkHelperRunClass))
+#define GPK_IS_HELPER_RUN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GPK_TYPE_HELPER_RUN))
+#define GPK_IS_HELPER_RUN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GPK_TYPE_HELPER_RUN))
+#define GPK_HELPER_RUN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GPK_TYPE_HELPER_RUN, GpkHelperRunClass))
+#define GPK_HELPER_RUN_ERROR (gpk_helper_run_error_quark ())
+#define GPK_HELPER_RUN_TYPE_ERROR (gpk_helper_run_error_get_type ())
+
+typedef struct GpkHelperRunPrivate GpkHelperRunPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GpkHelperRunPrivate *priv;
+} GpkHelperRun;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} GpkHelperRunClass;
+
+GType gpk_helper_run_get_type (void);
+GpkHelperRun *gpk_helper_run_new (void);
+gboolean gpk_helper_run_set_parent (GpkHelperRun *helper,
+ GtkWindow *window);
+gboolean gpk_helper_run_show (GpkHelperRun *helper,
+ gchar **package_ids);
+
+G_END_DECLS
+
+#endif /* __GPK_HELPER_RUN_H */
Added: trunk/src/gpk-helper-untrusted.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-helper-untrusted.c Tue Apr 14 16:28:59 2009
@@ -0,0 +1,240 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gpk-helper-untrusted.h"
+#include "gpk-marshal.h"
+#include "gpk-gnome.h"
+#include "gpk-common.h"
+#include "gpk-enum.h"
+
+#include "egg-debug.h"
+
+static void gpk_helper_untrusted_finalize (GObject *object);
+
+#define GPK_HELPER_UNTRUSTED_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPK_TYPE_HELPER_UNTRUSTED, GpkHelperUntrustedPrivate))
+
+struct GpkHelperUntrustedPrivate
+{
+ GtkBuilder *builder;
+};
+
+enum {
+ GPK_HELPER_UNTRUSTED_EVENT,
+ GPK_HELPER_UNTRUSTED_LAST_SIGNAL
+};
+
+static guint signals [GPK_HELPER_UNTRUSTED_LAST_SIGNAL] = { 0 };
+G_DEFINE_TYPE (GpkHelperUntrusted, gpk_helper_untrusted, G_TYPE_OBJECT)
+
+/**
+ * gpk_helper_untrusted_button_force_install_cb:
+ **/
+static void
+gpk_helper_untrusted_button_force_install_cb (GtkWidget *widget, GpkHelperUntrusted *helper)
+{
+ g_signal_emit (helper, signals [GPK_HELPER_UNTRUSTED_EVENT], 0, GTK_RESPONSE_YES);
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_error"));
+ gtk_widget_hide (widget);
+}
+
+/**
+ * gpk_helper_untrusted_button_cancel_cb:
+ **/
+static void
+gpk_helper_untrusted_button_cancel_cb (GtkWidget *widget, GpkHelperUntrusted *helper)
+{
+ g_signal_emit (helper, signals [GPK_HELPER_UNTRUSTED_EVENT], 0, GTK_RESPONSE_NO);
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_error"));
+ gtk_widget_hide (widget);
+}
+
+/**
+ * gpk_helper_untrusted_show:
+ *
+ * Return value: if we agreed
+ **/
+gboolean
+gpk_helper_untrusted_show (GpkHelperUntrusted *helper, PkErrorCodeEnum code)
+{
+ GtkWidget *widget;
+ gchar *text;
+ const gchar *title;
+ gchar *message;
+
+ g_return_val_if_fail (GPK_IS_HELPER_UNTRUSTED (helper), FALSE);
+
+ /* title */
+ title = gpk_error_enum_to_localised_text (code);
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "label_title"));
+ text = g_strdup_printf ("<b><big>%s</big></b>", title);
+ gtk_label_set_label (GTK_LABEL (widget), text);
+ g_free (text);
+
+ /* message */
+ message = g_strdup_printf ("%s\n%s\n\n%s\n%s",
+ /* TRANSLATORS: is not GPG signed */
+ _("The package is not signed by a trusted provider."),
+ /* TRANSLATORS: user has to trust provider -- I know, this sucks */
+ _("Do not install this package unless you are sure it is safe to do so."),
+ /* TRANSLATORS: warn the user that all bets are off */
+ _("Malicious software can damage your computer or cause other harm."),
+ /* TRANSLATORS: ask if they are absolutely sure they want to do this */
+ _("Are you <b>sure</b> you want to install this package?"));
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "label_message"));
+ gtk_label_set_markup (GTK_LABEL (widget), message);
+ g_free (message);
+
+ /* show window */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_error"));
+ gtk_widget_show (widget);
+
+ return TRUE;
+}
+
+/**
+ * gpk_helper_untrusted_set_parent:
+ **/
+gboolean
+gpk_helper_untrusted_set_parent (GpkHelperUntrusted *helper, GtkWindow *window)
+{
+ GtkWindow *widget;
+
+ g_return_val_if_fail (GPK_IS_HELPER_UNTRUSTED (helper), FALSE);
+ g_return_val_if_fail (window != NULL, FALSE);
+
+ /* make modal if window set */
+ widget = GTK_WINDOW (gtk_builder_get_object (helper->priv->builder, "dialog_error"));
+ gtk_window_set_transient_for (widget, window);
+ gtk_window_set_modal (widget, TRUE);
+
+ /* this is a modal popup, so don't show a window title */
+ gtk_window_set_title (widget, "");
+
+ return TRUE;
+}
+
+/**
+ * gpk_helper_untrusted_class_init:
+ * @klass: The GpkHelperUntrustedClass
+ **/
+static void
+gpk_helper_untrusted_class_init (GpkHelperUntrustedClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gpk_helper_untrusted_finalize;
+ g_type_class_add_private (klass, sizeof (GpkHelperUntrustedPrivate));
+ signals [GPK_HELPER_UNTRUSTED_EVENT] =
+ g_signal_new ("event",
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GpkHelperUntrustedClass, event),
+ NULL, NULL, g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
+}
+
+/**
+ * gpk_helper_untrusted_init:
+ **/
+static void
+gpk_helper_untrusted_init (GpkHelperUntrusted *helper)
+{
+ GtkWidget *widget;
+ GtkWidget *button;
+ guint retval;
+ GError *error = NULL;
+
+ helper->priv = GPK_HELPER_UNTRUSTED_GET_PRIVATE (helper);
+
+ /* get UI */
+ helper->priv->builder = gtk_builder_new ();
+ retval = gtk_builder_add_from_file (helper->priv->builder, GPK_DATA "/gpk-error.ui", &error);
+ if (error != NULL) {
+ egg_warning ("failed to load ui: %s", error->message);
+ g_error_free (error);
+ }
+
+ /* connect up default actions */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_error"));
+ g_signal_connect (widget, "delete_event", G_CALLBACK (gpk_helper_untrusted_button_cancel_cb), helper);
+
+ /* set icon name */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_error"));
+ gtk_window_set_icon_name (GTK_WINDOW (widget), GPK_ICON_SOFTWARE_INSTALLER);
+
+ /* connect up buttons */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "button_close"));
+ g_signal_connect (widget, "clicked", G_CALLBACK (gpk_helper_untrusted_button_cancel_cb), helper);
+
+ /* don't show text in the expander */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "expander_details"));
+ gtk_widget_hide (widget);
+
+ /* TRANSLATORS: button label, force the install, even though it's untrusted */
+ button = gtk_button_new_with_mnemonic (_("_Force install"));
+ g_signal_connect (button, "clicked", G_CALLBACK (gpk_helper_untrusted_button_force_install_cb), helper);
+
+ /* TRANSLATORS: button tooltip */
+ gtk_widget_set_tooltip_text (button, _("Force installing package"));
+
+ /* add to box */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_error"));
+ widget = gtk_dialog_get_action_area (GTK_DIALOG(widget));
+ gtk_box_pack_start (GTK_BOX (widget), button, FALSE, FALSE, 0);
+ gtk_widget_show (button);
+}
+
+/**
+ * gpk_helper_untrusted_finalize:
+ **/
+static void
+gpk_helper_untrusted_finalize (GObject *object)
+{
+ GtkWidget *widget;
+ GpkHelperUntrusted *helper;
+
+ g_return_if_fail (GPK_IS_HELPER_UNTRUSTED (object));
+
+ helper = GPK_HELPER_UNTRUSTED (object);
+
+ /* hide window */
+ widget = GTK_WIDGET (gtk_builder_get_object (helper->priv->builder, "dialog_error"));
+ if (GTK_IS_WIDGET (widget))
+ gtk_widget_hide (widget);
+ g_object_unref (helper->priv->builder);
+
+ G_OBJECT_CLASS (gpk_helper_untrusted_parent_class)->finalize (object);
+}
+
+/**
+ * gpk_helper_untrusted_new:
+ **/
+GpkHelperUntrusted *
+gpk_helper_untrusted_new (void)
+{
+ GpkHelperUntrusted *helper;
+ helper = g_object_new (GPK_TYPE_HELPER_UNTRUSTED, NULL);
+ return GPK_HELPER_UNTRUSTED (helper);
+}
+
Added: trunk/src/gpk-helper-untrusted.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-helper-untrusted.h Tue Apr 14 16:28:59 2009
@@ -0,0 +1,64 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GPK_HELPER_UNTRUSTED_H
+#define __GPK_HELPER_UNTRUSTED_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <packagekit-glib/packagekit.h>
+
+G_BEGIN_DECLS
+
+#define GPK_TYPE_HELPER_UNTRUSTED (gpk_helper_untrusted_get_type ())
+#define GPK_HELPER_UNTRUSTED(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GPK_TYPE_HELPER_UNTRUSTED, GpkHelperUntrusted))
+#define GPK_HELPER_UNTRUSTED_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GPK_TYPE_HELPER_UNTRUSTED, GpkHelperUntrustedClass))
+#define GPK_IS_HELPER_UNTRUSTED(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GPK_TYPE_HELPER_UNTRUSTED))
+#define GPK_IS_HELPER_UNTRUSTED_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GPK_TYPE_HELPER_UNTRUSTED))
+#define GPK_HELPER_UNTRUSTED_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GPK_TYPE_HELPER_UNTRUSTED, GpkHelperUntrustedClass))
+#define GPK_HELPER_UNTRUSTED_ERROR (gpk_helper_untrusted_error_quark ())
+#define GPK_HELPER_UNTRUSTED_TYPE_ERROR (gpk_helper_untrusted_error_get_type ())
+
+typedef struct GpkHelperUntrustedPrivate GpkHelperUntrustedPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GpkHelperUntrustedPrivate *priv;
+} GpkHelperUntrusted;
+
+typedef struct
+{
+ void (* event) (GpkHelperUntrusted *helper,
+ GtkResponseType type);
+ GObjectClass parent_class;
+} GpkHelperUntrustedClass;
+
+GType gpk_helper_untrusted_get_type (void);
+GpkHelperUntrusted *gpk_helper_untrusted_new (void);
+gboolean gpk_helper_untrusted_set_parent (GpkHelperUntrusted *helper,
+ GtkWindow *window);
+gboolean gpk_helper_untrusted_show (GpkHelperUntrusted *helper,
+ PkErrorCodeEnum code);
+
+G_END_DECLS
+
+#endif /* __GPK_HELPER_UNTRUSTED_H */
Modified: trunk/src/gpk-install-catalog.c
==============================================================================
--- trunk/src/gpk-install-catalog.c (original)
+++ trunk/src/gpk-install-catalog.c Tue Apr 14 16:28:59 2009
@@ -26,12 +26,12 @@
#include <gtk/gtk.h>
#include <locale.h>
#include <packagekit-glib/packagekit.h>
+#include <dbus/dbus-glib.h>
#include "egg-debug.h"
#include "gpk-common.h"
#include "gpk-error.h"
-#include "gpk-client.h"
/**
* main:
@@ -40,7 +40,9 @@
main (int argc, char *argv[])
{
GOptionContext *context;
- GpkClient *gclient;
+ DBusGConnection *connection;
+ DBusGProxy *proxy = NULL;
+ GError *error = NULL;
gboolean ret;
gboolean verbose = FALSE;
gchar **files = NULL;
@@ -78,24 +80,52 @@
/* are we running privileged */
ret = gpk_check_privileged_user (_("Catalog installer"), TRUE);
if (!ret)
- return 1;
+ goto out;
if (files == NULL) {
gpk_error_dialog (_("Failed to install catalog"),
/* TRANSLATORS: no filename was supplied */
_("You need to specify a file name to install"), NULL);
- return 1;
+ goto out;
}
- /* find the file list */
- gclient = gpk_client_new ();
- gpk_client_set_interaction (gclient, GPK_CLIENT_INTERACT_ALWAYS);
- /* install all the catalogs */
- ret = gpk_client_install_catalogs (gclient, files, NULL);
+ /* check dbus connections, exit if not valid */
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if (connection == NULL) {
+ egg_warning ("%s", error->message);
+ g_error_free (error);
+ goto out;
+ }
- g_object_unref (gclient);
- g_strfreev (files);
+ /* get a connection */
+ proxy = dbus_g_proxy_new_for_name (connection,
+ "org.freedesktop.PackageKit",
+ "/org/freedesktop/PackageKit",
+ "org.freedesktop.PackageKit.Modify");
+ if (proxy == NULL) {
+ egg_warning ("Cannot connect to session service");
+ goto out;
+ }
+ /* don't timeout, as dbus-glib sets the timeout ~25 seconds */
+ dbus_g_proxy_set_default_timeout (proxy, INT_MAX);
+
+ /* do method */
+ ret = dbus_g_proxy_call (proxy, "InstallCatalogs", &error,
+ G_TYPE_UINT, 0, /* xid */
+ G_TYPE_STRV, files, /* data */
+ G_TYPE_STRING, "", /* interaction */
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ if (!ret) {
+ egg_warning ("%s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ if (proxy != NULL)
+ g_object_unref (proxy);
+ g_strfreev (files);
return !ret;
}
Modified: trunk/src/gpk-install-local-file.c
==============================================================================
--- trunk/src/gpk-install-local-file.c (original)
+++ trunk/src/gpk-install-local-file.c Tue Apr 14 16:28:59 2009
@@ -25,11 +25,11 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <locale.h>
+#include <dbus/dbus-glib.h>
#include "egg-debug.h"
#include "gpk-common.h"
-#include "gpk-client.h"
#include "gpk-error.h"
/**
@@ -41,9 +41,10 @@
GOptionContext *context;
gboolean ret;
gboolean verbose = FALSE;
- GError *error;
- GpkClient *gclient;
+ GError *error = NULL;
gchar **files = NULL;
+ DBusGConnection *connection;
+ DBusGProxy *proxy = NULL;
const GOptionEntry options[] = {
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
@@ -78,22 +79,52 @@
/* TRANSLATORS: title to pass to to the user if there are not enough privs */
ret = gpk_check_privileged_user (_("Local file installer"), TRUE);
if (!ret)
- return 1;
+ goto out;
if (files == NULL) {
/* TRANSLATORS: could not install a package that contained the file we wanted */
gpk_error_dialog (_("Failed to install a package to provide a file"),
/* TRANSLATORS: nothing selected */
_("You need to specify a file to install"), NULL);
- return 1;
+ goto out;
}
- error = NULL;
- gclient = gpk_client_new ();
- gpk_client_set_interaction (gclient, GPK_CLIENT_INTERACT_ALWAYS);
- ret = gpk_client_install_local_files (gclient, files, NULL);
- g_strfreev (files);
- g_object_unref (gclient);
+ /* check dbus connections, exit if not valid */
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if (connection == NULL) {
+ egg_warning ("%s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* get a connection */
+ proxy = dbus_g_proxy_new_for_name (connection,
+ "org.freedesktop.PackageKit",
+ "/org/freedesktop/PackageKit",
+ "org.freedesktop.PackageKit.Modify");
+ if (proxy == NULL) {
+ egg_warning ("Cannot connect to session service");
+ goto out;
+ }
+ /* don't timeout, as dbus-glib sets the timeout ~25 seconds */
+ dbus_g_proxy_set_default_timeout (proxy, INT_MAX);
+
+ /* do method */
+ ret = dbus_g_proxy_call (proxy, "InstallPackageFiles", &error,
+ G_TYPE_UINT, 0, /* xid */
+ G_TYPE_STRV, files, /* data */
+ G_TYPE_STRING, "hide-finished", /* interaction */
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ if (!ret) {
+ egg_warning ("%s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ if (proxy != NULL)
+ g_object_unref (proxy);
+ g_strfreev (files);
return !ret;
}
Modified: trunk/src/gpk-install-mime-type.c
==============================================================================
--- trunk/src/gpk-install-mime-type.c (original)
+++ trunk/src/gpk-install-mime-type.c Tue Apr 14 16:28:59 2009
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
- * Copyright (C) 2008 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2008-2009 Richard Hughes <richard hughsie com>
*
* Licensed under the GNU General Public License Version 2
*
@@ -25,11 +25,11 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <locale.h>
+#include <dbus/dbus-glib.h>
#include "egg-debug.h"
#include "gpk-common.h"
-#include "gpk-client.h"
#include "gpk-error.h"
/**
@@ -41,12 +41,17 @@
GOptionContext *context;
gboolean ret;
gboolean verbose = FALSE;
- GError *error;
- GpkClient *gclient;
+ GError *error = NULL;
+ DBusGConnection *connection;
+ DBusGProxy *proxy = NULL;
+ gchar **types = NULL;
const GOptionEntry options[] = {
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
_("Show extra debugging information"), NULL },
+ { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &types,
+ /* TRANSLATORS: command line option: a list of catalogs to install */
+ _("Mime types to install"), NULL },
{ NULL}
};
@@ -74,28 +79,52 @@
/* TRANSLATORS: title to pass to to the user if there are not enough privs */
ret = gpk_check_privileged_user (_("Mime type installer"), TRUE);
if (!ret)
- return 1;
+ goto out;
- if (argc < 2) {
+ if (types == NULL) {
/* TRANSLATORS: could not install program supporting this type */
gpk_error_dialog (_("Failed to install a program to handle this file type"),
/* TRANSLATORS: no type given */
_("You need to specify a mime-type to install"), NULL);
- return 1;
+ goto out;
}
- if (argc > 2) {
- /* TRANSLATORS: could not install program supporting this type */
- gpk_error_dialog (_("Failed to install a program to handle this file type"),
- /* TRANSLATORS: more than one type given */
- _("You can only specify one mime-type to install"), NULL);
- return 1;
+
+ /* check dbus connections, exit if not valid */
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if (connection == NULL) {
+ egg_warning ("%s", error->message);
+ g_error_free (error);
+ goto out;
}
- error = NULL;
- gclient = gpk_client_new ();
- gpk_client_set_interaction (gclient, GPK_CLIENT_INTERACT_ALWAYS);
- ret = gpk_client_install_mime_type (gclient, argv[1], NULL);
- g_object_unref (gclient);
+ /* get a connection */
+ proxy = dbus_g_proxy_new_for_name (connection,
+ "org.freedesktop.PackageKit",
+ "/org/freedesktop/PackageKit",
+ "org.freedesktop.PackageKit.Modify");
+ if (proxy == NULL) {
+ egg_warning ("Cannot connect to session service");
+ goto out;
+ }
+
+ /* don't timeout, as dbus-glib sets the timeout ~25 seconds */
+ dbus_g_proxy_set_default_timeout (proxy, INT_MAX);
+ /* do method */
+ ret = dbus_g_proxy_call (proxy, "InstallMimeTypes", &error,
+ G_TYPE_UINT, 0, /* xid */
+ G_TYPE_STRV, types, /* data */
+ G_TYPE_STRING, "", /* interaction */
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ if (!ret) {
+ egg_warning ("%s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ if (proxy != NULL)
+ g_object_unref (proxy);
+ g_strfreev (types);
return !ret;
}
Modified: trunk/src/gpk-install-package-name.c
==============================================================================
--- trunk/src/gpk-install-package-name.c (original)
+++ trunk/src/gpk-install-package-name.c Tue Apr 14 16:28:59 2009
@@ -25,11 +25,11 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <locale.h>
+#include <dbus/dbus-glib.h>
#include "egg-debug.h"
#include "gpk-common.h"
-#include "gpk-client.h"
#include "gpk-error.h"
/**
@@ -41,9 +41,10 @@
GOptionContext *context;
gboolean ret;
gboolean verbose = FALSE;
- GError *error;
- GpkClient *gclient;
+ GError *error = NULL;
gchar **packages = NULL;
+ DBusGConnection *connection;
+ DBusGProxy *proxy = NULL;
const GOptionEntry options[] = {
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
@@ -77,22 +78,52 @@
/* TRANSLATORS: application name to pass to to the user if there are not enough privs */
ret = gpk_check_privileged_user (_("Package Name Installer"), TRUE);
if (!ret)
- return 1;
+ goto out;
if (packages == NULL) {
/* TRANSLATORS: failed */
gpk_error_dialog (_("Failed to install package from name"),
/* TRANSLATORS: nothing was specified */
_("You need to specify a package to install"), NULL);
- return 1;
+ goto out;
}
- error = NULL;
- gclient = gpk_client_new ();
- gpk_client_set_interaction (gclient, GPK_CLIENT_INTERACT_ALWAYS);
- ret = gpk_client_install_package_names (gclient, packages, NULL);
- g_strfreev (packages);
- g_object_unref (gclient);
+ /* check dbus connections, exit if not valid */
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if (connection == NULL) {
+ egg_warning ("%s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* get a connection */
+ proxy = dbus_g_proxy_new_for_name (connection,
+ "org.freedesktop.PackageKit",
+ "/org/freedesktop/PackageKit",
+ "org.freedesktop.PackageKit.Modify");
+ if (proxy == NULL) {
+ egg_warning ("Cannot connect to session service");
+ goto out;
+ }
+ /* don't timeout, as dbus-glib sets the timeout ~25 seconds */
+ dbus_g_proxy_set_default_timeout (proxy, INT_MAX);
+
+ /* do method */
+ ret = dbus_g_proxy_call (proxy, "InstallPackageNames", &error,
+ G_TYPE_UINT, 0, /* xid */
+ G_TYPE_STRV, packages, /* data */
+ G_TYPE_STRING, "", /* interaction */
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ if (!ret) {
+ egg_warning ("%s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ if (proxy != NULL)
+ g_object_unref (proxy);
+ g_strfreev (packages);
return !ret;
}
Modified: trunk/src/gpk-install-provide-file.c
==============================================================================
--- trunk/src/gpk-install-provide-file.c (original)
+++ trunk/src/gpk-install-provide-file.c Tue Apr 14 16:28:59 2009
@@ -25,11 +25,11 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <locale.h>
+#include <dbus/dbus-glib.h>
#include "egg-debug.h"
#include "gpk-common.h"
-#include "gpk-client.h"
#include "gpk-error.h"
/**
@@ -41,12 +41,17 @@
GOptionContext *context;
gboolean ret;
gboolean verbose = FALSE;
- GError *error;
- GpkClient *gclient;
+ GError *error = NULL;
+ DBusGConnection *connection;
+ DBusGProxy *proxy = NULL;
+ gchar **files = NULL;
const GOptionEntry options[] = {
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
_("Show extra debugging information"), NULL },
+ { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &files,
+ /* TRANSLATORS: command line option: a list of files to install */
+ _("Local files to install"), NULL },
{ NULL}
};
@@ -74,28 +79,52 @@
/* TRANSLATORS: application name to pass to to the user if there are not enough privs */
ret = gpk_check_privileged_user (_("Single File Installer"), TRUE);
if (!ret)
- return 1;
+ goto out;
- if (argc < 2) {
+ if (files == NULL) {
/* TRANSLATORS: nothing done */
gpk_error_dialog (_("Failed to install a package to provide a file"),
/* TRANSLATORS: nothig was specified */
_("You need to specify a filename to install"), NULL);
- return 1;
+ goto out;
}
- if (argc > 2) {
- /* TRANSLATORS: nothing done */
- gpk_error_dialog (_("Failed to install packages to provide files"),
- /* TRANSLATORS: more than one thing was specified */
- _("You can only specify one filename to install"), NULL);
- return 1;
+
+ /* check dbus connections, exit if not valid */
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if (connection == NULL) {
+ egg_warning ("%s", error->message);
+ g_error_free (error);
+ goto out;
}
- error = NULL;
- gclient = gpk_client_new ();
- gpk_client_set_interaction (gclient, GPK_CLIENT_INTERACT_ALWAYS);
- ret = gpk_client_install_provide_file (gclient, argv[1], NULL);
- g_object_unref (gclient);
+ /* get a connection */
+ proxy = dbus_g_proxy_new_for_name (connection,
+ "org.freedesktop.PackageKit",
+ "/org/freedesktop/PackageKit",
+ "org.freedesktop.PackageKit.Modify");
+ if (proxy == NULL) {
+ egg_warning ("Cannot connect to session service");
+ goto out;
+ }
+ /* don't timeout, as dbus-glib sets the timeout ~25 seconds */
+ dbus_g_proxy_set_default_timeout (proxy, INT_MAX);
+
+ /* do method */
+ ret = dbus_g_proxy_call (proxy, "InstallProvideFiles", &error,
+ G_TYPE_UINT, 0, /* xid */
+ G_TYPE_STRV, files, /* data */
+ G_TYPE_STRING, "", /* interaction */
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ if (!ret) {
+ egg_warning ("%s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+out:
+ if (proxy != NULL)
+ g_object_unref (proxy);
+ g_strfreev (files);
return !ret;
}
Added: trunk/src/gpk-modal-dialog.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-modal-dialog.c Tue Apr 14 16:28:59 2009
@@ -0,0 +1,1022 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <string.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <glib/gi18n.h>
+#include <packagekit-glib/packagekit.h>
+
+#include "egg-debug.h"
+#include "egg-string.h"
+
+#include "gpk-animated-icon.h"
+#include "gpk-modal-dialog.h"
+#include "gpk-common.h"
+#include "gpk-gnome.h"
+#include "gpk-enum.h"
+#include "gpk-desktop.h"
+
+static void gpk_modal_dialog_finalize (GObject *object);
+
+#define GPK_MODAL_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPK_TYPE_CLIENT_DIALOG, GpkModalDialogPrivate))
+
+struct _GpkModalDialogPrivate
+{
+ GtkBuilder *builder;
+ guint pulse_timer_id;
+ gboolean show_progress_files;
+ gboolean has_parent;
+ GMainLoop *loop;
+ GtkResponseType response;
+ GtkListStore *store;
+ gchar *help_id;
+ gchar *title;
+ gboolean set_image;
+ GpkModalDialogPage page;
+ PkBitfield options;
+ GtkWidget *image_status;
+};
+
+enum {
+ GPK_MODAL_DIALOG_CLOSE,
+ GPK_MODAL_DIALOG_QUIT,
+ GPK_MODAL_DIALOG_ACTION,
+ GPK_MODAL_DIALOG_HELP,
+ GPK_MODAL_DIALOG_CANCEL,
+ LAST_SIGNAL
+};
+
+enum {
+ GPK_MODAL_DIALOG_STORE_IMAGE,
+ GPK_MODAL_DIALOG_STORE_ID,
+ GPK_MODAL_DIALOG_STORE_TEXT,
+ GPK_MODAL_DIALOG_STORE_LAST
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+G_DEFINE_TYPE (GpkModalDialog, gpk_modal_dialog, G_TYPE_OBJECT)
+
+/**
+ * gpk_modal_dialog_show_widget:
+ **/
+static void
+gpk_modal_dialog_show_widget (GpkModalDialog *dialog, const gchar *name, gboolean enabled)
+{
+ GtkWidget *widget;
+ widget = GTK_WIDGET (gtk_builder_get_object (dialog->priv->builder, name));
+ if (enabled)
+ gtk_widget_show (widget);
+ else
+ gtk_widget_hide (widget);
+}
+
+/**
+ * gpk_modal_dialog_setup:
+ **/
+gboolean
+gpk_modal_dialog_setup (GpkModalDialog *dialog, GpkModalDialogPage page, PkBitfield options)
+{
+ GtkLabel *label;
+ g_return_val_if_fail (GPK_IS_CLIENT_DIALOG (dialog), FALSE);
+
+ /* reset state */
+ g_free (dialog->priv->help_id);
+ dialog->priv->help_id = NULL;
+ dialog->priv->set_image = FALSE;
+ dialog->priv->page = page;
+ dialog->priv->options = options;
+ label = GTK_LABEL (gtk_builder_get_object (dialog->priv->builder, "label_message"));
+ gtk_label_set_label (label, "");
+ gpk_modal_dialog_set_action (dialog, NULL);
+ return TRUE;
+}
+
+/**
+ * gpk_modal_dialog_present_with_time:
+ **/
+gboolean
+gpk_modal_dialog_present_with_time (GpkModalDialog *dialog, guint32 timestamp)
+{
+ GtkWidget *widget;
+ PkBitfield bitfield = 0;
+
+ g_return_val_if_fail (GPK_IS_CLIENT_DIALOG (dialog), FALSE);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (dialog->priv->builder, "label_title"));
+ gtk_widget_show (widget);
+ gtk_widget_show (dialog->priv->image_status);
+ /* helper */
+ if (dialog->priv->page == GPK_MODAL_DIALOG_PAGE_CONFIRM) {
+ if (!dialog->priv->set_image)
+ gpk_modal_dialog_set_image (dialog, "dialog-question");
+ bitfield = pk_bitfield_from_enums (GPK_MODAL_DIALOG_WIDGET_BUTTON_CLOSE,
+ GPK_MODAL_DIALOG_WIDGET_BUTTON_ACTION,
+ GPK_MODAL_DIALOG_WIDGET_BUTTON_HELP,
+ GPK_MODAL_DIALOG_WIDGET_MESSAGE,
+ -1);
+ } else if (dialog->priv->page == GPK_MODAL_DIALOG_PAGE_FINISHED) {
+ if (!dialog->priv->set_image)
+ gpk_modal_dialog_set_image (dialog, "dialog-information");
+ bitfield = pk_bitfield_from_enums (GPK_MODAL_DIALOG_WIDGET_BUTTON_CLOSE,
+ GPK_MODAL_DIALOG_WIDGET_MESSAGE,
+ -1);
+ } else if (dialog->priv->page == GPK_MODAL_DIALOG_PAGE_CONFIRM) {
+ if (!dialog->priv->set_image)
+ gpk_modal_dialog_set_image (dialog, "dialog-question");
+ bitfield = pk_bitfield_from_enums (GPK_MODAL_DIALOG_WIDGET_BUTTON_CLOSE,
+ GPK_MODAL_DIALOG_WIDGET_BUTTON_ACTION,
+ GPK_MODAL_DIALOG_WIDGET_BUTTON_HELP,
+ GPK_MODAL_DIALOG_WIDGET_MESSAGE,
+ -1);
+ } else if (dialog->priv->page == GPK_MODAL_DIALOG_PAGE_WARNING) {
+ if (!dialog->priv->set_image)
+ gpk_modal_dialog_set_image (dialog, "dialog-warning");
+ bitfield = pk_bitfield_from_enums (GPK_MODAL_DIALOG_WIDGET_BUTTON_CLOSE,
+ GPK_MODAL_DIALOG_WIDGET_MESSAGE,
+ -1);
+ } else if (dialog->priv->page == GPK_MODAL_DIALOG_PAGE_PROGRESS) {
+ if (!dialog->priv->set_image)
+ gpk_modal_dialog_set_image (dialog, "dialog-warning");
+ bitfield = pk_bitfield_from_enums (GPK_MODAL_DIALOG_WIDGET_BUTTON_CLOSE,
+ GPK_MODAL_DIALOG_WIDGET_BUTTON_CANCEL,
+ GPK_MODAL_DIALOG_WIDGET_BUTTON_HELP,
+ GPK_MODAL_DIALOG_WIDGET_PROGRESS_BAR,
+ -1);
+ }
+
+ /* we can specify extras */
+ bitfield += dialog->priv->options;
+
+ gpk_modal_dialog_show_widget (dialog, "button_help", pk_bitfield_contain (bitfield, GPK_MODAL_DIALOG_WIDGET_BUTTON_HELP));
+ gpk_modal_dialog_show_widget (dialog, "button_cancel", pk_bitfield_contain (bitfield, GPK_MODAL_DIALOG_WIDGET_BUTTON_CANCEL));
+ gpk_modal_dialog_show_widget (dialog, "button_close", pk_bitfield_contain (bitfield, GPK_MODAL_DIALOG_WIDGET_BUTTON_CLOSE));
+ gpk_modal_dialog_show_widget (dialog, "button_action", pk_bitfield_contain (bitfield, GPK_MODAL_DIALOG_WIDGET_BUTTON_ACTION));
+ gpk_modal_dialog_show_widget (dialog, "progressbar_percent", pk_bitfield_contain (bitfield, GPK_MODAL_DIALOG_WIDGET_PROGRESS_BAR));
+ gpk_modal_dialog_show_widget (dialog, "label_message", pk_bitfield_contain (bitfield, GPK_MODAL_DIALOG_WIDGET_MESSAGE));
+ gpk_modal_dialog_show_widget (dialog, "scrolledwindow_packages", pk_bitfield_contain (bitfield, GPK_MODAL_DIALOG_WIDGET_PACKAGE_LIST));
+ gpk_modal_dialog_show_widget (dialog, "label_force_height", pk_bitfield_contain (bitfield, GPK_MODAL_DIALOG_WIDGET_PADDING));
+
+ /* always force width */
+ gpk_modal_dialog_show_widget (dialog, "label_force_width", TRUE);
+
+ /* show */
+ widget = GTK_WIDGET (gtk_builder_get_object (dialog->priv->builder, "dialog_client"));
+ gtk_widget_realize (widget);
+ gtk_window_present_with_time (GTK_WINDOW (widget), timestamp);
+
+
+ return TRUE;
+}
+
+/**
+ * gpk_modal_dialog_present:
+ **/
+gboolean
+gpk_modal_dialog_present (GpkModalDialog *dialog)
+{
+ return gpk_modal_dialog_present_with_time (dialog, 0);
+}
+
+/**
+ * gpk_modal_dialog_set_parent:
+ **/
+gboolean
+gpk_modal_dialog_set_parent (GpkModalDialog *dialog, GdkWindow *window)
+{
+ GtkWidget *widget;
+ g_return_val_if_fail (GPK_IS_CLIENT_DIALOG (dialog), FALSE);
+
+ /* never set, and nothing now */
+ if (window == NULL && !dialog->priv->has_parent)
+ return TRUE;
+
+ /* not sure what to do here, should probably unparent somehow */
+ if (window == NULL) {
+ egg_warning ("parent set NULL when already modal with another window, setting non-modal");
+ widget = GTK_WIDGET (gtk_builder_get_object (dialog->priv->builder, "dialog_client"));
+ gtk_window_set_modal (GTK_WINDOW (widget), FALSE);
+ dialog->priv->has_parent = FALSE;
+
+ /* use the saved title if it exists */
+ if (dialog->priv->title != NULL)
+ gpk_modal_dialog_set_title (dialog, dialog->priv->title);
+
+ return FALSE;
+ }
+
+ /* check we are a valid window */
+ if (!GDK_WINDOW (window)) {
+ egg_warning ("not a valid GdkWindow!");
+ return FALSE;
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (dialog->priv->builder, "dialog_client"));
+ gtk_widget_realize (widget);
+ gtk_window_set_modal (GTK_WINDOW (widget), TRUE);
+ gdk_window_set_transient_for (GTK_WIDGET (widget)->window, window);
+ dialog->priv->has_parent = TRUE;
+ return TRUE;
+}
+
+/**
+ * gpk_modal_dialog_set_window_title:
+ **/
+static gboolean
+gpk_modal_dialog_set_window_title (GpkModalDialog *dialog, const gchar *title)
+{
+ GtkWindow *window;
+
+ g_return_val_if_fail (GPK_IS_CLIENT_DIALOG (dialog), FALSE);
+ g_return_val_if_fail (title != NULL, FALSE);
+
+ egg_debug ("setting window title: %s", title);
+ window = GTK_WINDOW (gtk_builder_get_object (dialog->priv->builder, "dialog_client"));
+ gtk_window_set_title (window, title);
+ return TRUE;
+}
+
+/**
+ * gpk_modal_dialog_set_window_icon:
+ **/
+gboolean
+gpk_modal_dialog_set_window_icon (GpkModalDialog *dialog, const gchar *icon)
+{
+ GtkWindow *window;
+
+ g_return_val_if_fail (GPK_IS_CLIENT_DIALOG (dialog), FALSE);
+ g_return_val_if_fail (icon != NULL, FALSE);
+
+ egg_debug ("setting window icon: %s", icon);
+ window = GTK_WINDOW (gtk_builder_get_object (dialog->priv->builder, "dialog_client"));
+ gtk_window_set_icon_name (window, icon);
+ return TRUE;
+}
+
+/**
+ * gpk_modal_dialog_set_title:
+ **/
+gboolean
+gpk_modal_dialog_set_title (GpkModalDialog *dialog, const gchar *title)
+{
+ GtkLabel *label;
+ gchar *title_bold;
+
+ g_return_val_if_fail (GPK_IS_CLIENT_DIALOG (dialog), FALSE);
+ g_return_val_if_fail (title != NULL, FALSE);
+
+ /* only set the window title if we are non-modal */
+ if (!dialog->priv->has_parent)
+ gpk_modal_dialog_set_window_title (dialog, title);
+
+ /* we save this in case we are non-modal and have to use a title */
+ g_free (dialog->priv->title);
+ dialog->priv->title = g_strdup (title);
+
+ title_bold = g_strdup_printf ("<b><big>%s</big></b>", title);
+ egg_debug ("setting title: %s", title_bold);
+ label = GTK_LABEL (gtk_builder_get_object (dialog->priv->builder, "label_title"));
+ gtk_label_set_markup (label, title_bold);
+ g_free (title_bold);
+ return TRUE;
+}
+
+/**
+ * gpk_modal_dialog_set_message:
+ **/
+gboolean
+gpk_modal_dialog_set_message (GpkModalDialog *dialog, const gchar *message)
+{
+ GtkLabel *label;
+
+ g_return_val_if_fail (GPK_IS_CLIENT_DIALOG (dialog), FALSE);
+ g_return_val_if_fail (message != NULL, FALSE);
+
+ /* ignore this if it's uninteresting */
+ if (!dialog->priv->show_progress_files)
+ return FALSE;
+
+ egg_debug ("setting message: %s", message);
+ label = GTK_LABEL (gtk_builder_get_object (dialog->priv->builder, "label_message"));
+ gtk_label_set_markup (label, message);
+ return TRUE;
+}
+
+/**
+ * gpk_modal_dialog_set_action:
+ **/
+gboolean
+gpk_modal_dialog_set_action (GpkModalDialog *dialog, const gchar *action)
+{
+ GtkWidget *widget;
+
+ g_return_val_if_fail (GPK_IS_CLIENT_DIALOG (dialog), FALSE);
+
+ egg_debug ("setting action: %s", action);
+ widget = GTK_WIDGET (gtk_builder_get_object (dialog->priv->builder, "button_action"));
+ if (action != NULL)
+ gtk_button_set_label (GTK_BUTTON (widget), action);
+ else
+ gtk_widget_hide (widget);
+ return TRUE;
+}
+
+/**
+ * gpk_modal_dialog_pulse_progress:
+ **/
+static gboolean
+gpk_modal_dialog_pulse_progress (GpkModalDialog *dialog)
+{
+ GtkWidget *widget;
+ static guint rate_limit = 0;
+
+ g_return_val_if_fail (GPK_IS_CLIENT_DIALOG (dialog), FALSE);
+
+ /* debug so we can catch polling */
+ if (rate_limit++ % 20 == 0)
+ egg_debug ("polling check");
+
+ widget = GTK_WIDGET (gtk_builder_get_object (dialog->priv->builder, "progressbar_percent"));
+ gtk_progress_bar_pulse (GTK_PROGRESS_BAR (widget));
+
+ /* if there's no slider, optimise out the polling */
+ if (!GTK_WIDGET_VISIBLE (widget)) {
+ dialog->priv->pulse_timer_id = 0;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * gpk_modal_dialog_make_progressbar_pulse:
+ **/
+static void
+gpk_modal_dialog_make_progressbar_pulse (GpkModalDialog *dialog)
+{
+ GtkProgressBar *progress_bar;
+ if (dialog->priv->pulse_timer_id == 0) {
+ progress_bar = GTK_PROGRESS_BAR (gtk_builder_get_object (dialog->priv->builder, "progressbar_percent"));
+ gtk_progress_bar_set_pulse_step (progress_bar, 0.04);
+ dialog->priv->pulse_timer_id = g_timeout_add (75, (GSourceFunc) gpk_modal_dialog_pulse_progress, dialog);
+ }
+}
+
+/**
+ * gpk_modal_dialog_set_percentage:
+ **/
+gboolean
+gpk_modal_dialog_set_percentage (GpkModalDialog *dialog, guint percentage)
+{
+ GtkProgressBar *progress_bar;
+
+ g_return_val_if_fail (GPK_IS_CLIENT_DIALOG (dialog), FALSE);
+
+ egg_debug ("setting percentage: %u", percentage);
+
+ progress_bar = GTK_PROGRESS_BAR (gtk_builder_get_object (dialog->priv->builder, "progressbar_percent"));
+ if (dialog->priv->pulse_timer_id != 0) {
+ g_source_remove (dialog->priv->pulse_timer_id);
+ dialog->priv->pulse_timer_id = 0;
+ }
+
+ /* either pulse or set percentage */
+ if (percentage == PK_CLIENT_PERCENTAGE_INVALID)
+ gpk_modal_dialog_make_progressbar_pulse (dialog);
+ else
+ gtk_progress_bar_set_fraction (progress_bar, (gfloat) percentage / 100.0);
+ return TRUE;
+}
+
+/**
+ * gpk_modal_dialog_set_remaining:
+ **/
+gboolean
+gpk_modal_dialog_set_remaining (GpkModalDialog *dialog, guint remaining)
+{
+ GtkProgressBar *progress_bar;
+ gchar *timestring = NULL;
+ gchar *text = NULL;
+
+ g_return_val_if_fail (GPK_IS_CLIENT_DIALOG (dialog), FALSE);
+
+ egg_debug ("setting remaining: %u", remaining);
+ progress_bar = GTK_PROGRESS_BAR (gtk_builder_get_object (dialog->priv->builder, "progressbar_percent"));
+
+ /* unknown */
+ if (remaining == 0) {
+ gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progress_bar), "");
+ goto out;
+ }
+
+ /* get time text */
+ timestring = gpk_time_to_imprecise_string (remaining);
+ text = g_strdup_printf (_("Remaining time : %s"), timestring);
+ gtk_progress_bar_set_text (progress_bar, text);
+out:
+ g_free (timestring);
+ g_free (text);
+ return TRUE;
+}
+
+/**
+ * gpk_modal_dialog_set_image:
+ **/
+gboolean
+gpk_modal_dialog_set_image (GpkModalDialog *dialog, const gchar *image)
+{
+ g_return_val_if_fail (GPK_IS_CLIENT_DIALOG (dialog), FALSE);
+ g_return_val_if_fail (image != NULL, FALSE);
+
+ /* set state */
+ dialog->priv->set_image = TRUE;
+
+ egg_debug ("setting image: %s", image);
+ gpk_animated_icon_enable_animation (GPK_ANIMATED_ICON (dialog->priv->image_status), FALSE);
+ gtk_image_set_from_icon_name (GTK_IMAGE (dialog->priv->image_status), image, GTK_ICON_SIZE_DIALOG);
+ return TRUE;
+}
+
+/**
+ * gpk_modal_dialog_set_image_status:
+ **/
+gboolean
+gpk_modal_dialog_set_image_status (GpkModalDialog *dialog, PkStatusEnum status)
+{
+ g_return_val_if_fail (GPK_IS_CLIENT_DIALOG (dialog), FALSE);
+
+ /* set state */
+ dialog->priv->set_image = TRUE;
+ gpk_set_animated_icon_from_status (GPK_ANIMATED_ICON (dialog->priv->image_status), status, GTK_ICON_SIZE_DIALOG);
+ return TRUE;
+}
+
+/**
+ * gpk_modal_dialog_get_window:
+ **/
+GtkWindow *
+gpk_modal_dialog_get_window (GpkModalDialog *dialog)
+{
+ GtkWindow *window;
+
+ g_return_val_if_fail (GPK_IS_CLIENT_DIALOG (dialog), NULL);
+
+ window = GTK_WINDOW (gtk_builder_get_object (dialog->priv->builder, "dialog_client"));
+ return window;
+}
+
+/**
+ * gpk_modal_dialog_set_allow_cancel:
+ **/
+gboolean
+gpk_modal_dialog_set_allow_cancel (GpkModalDialog *dialog, gboolean can_cancel)
+{
+ GtkWidget *widget;
+
+ g_return_val_if_fail (GPK_IS_CLIENT_DIALOG (dialog), FALSE);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (dialog->priv->builder, "button_cancel"));
+ gtk_widget_set_sensitive (widget, can_cancel);
+
+ return TRUE;
+}
+
+/**
+ * gpk_modal_dialog_run:
+ **/
+GtkResponseType
+gpk_modal_dialog_run (GpkModalDialog *dialog)
+{
+ g_return_val_if_fail (GPK_IS_CLIENT_DIALOG (dialog), FALSE);
+
+ dialog->priv->response = GTK_RESPONSE_NONE;
+ g_main_loop_run (dialog->priv->loop);
+
+ return dialog->priv->response;
+}
+
+/**
+ * gpk_modal_dialog_close:
+ **/
+gboolean
+gpk_modal_dialog_close (GpkModalDialog *dialog)
+{
+ GtkWidget *widget;
+
+ g_return_val_if_fail (GPK_IS_CLIENT_DIALOG (dialog), FALSE);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (dialog->priv->builder, "dialog_client"));
+ gtk_widget_hide (widget);
+
+ if (dialog->priv->pulse_timer_id != 0) {
+ g_source_remove (dialog->priv->pulse_timer_id);
+ dialog->priv->pulse_timer_id = 0;
+ }
+
+ gpk_animated_icon_enable_animation (GPK_ANIMATED_ICON (dialog->priv->image_status), FALSE);
+ return TRUE;
+}
+
+/**
+ * gpk_modal_dialog_window_delete_cb:
+ **/
+static gboolean
+gpk_modal_dialog_window_delete_cb (GtkWidget *widget, GdkEvent *event, GpkModalDialog *dialog)
+{
+ dialog->priv->response = GTK_RESPONSE_DELETE_EVENT;
+ gpk_modal_dialog_close (dialog);
+ if (g_main_loop_is_running (dialog->priv->loop))
+ g_main_loop_quit (dialog->priv->loop);
+ /* do not destroy the window */
+ return TRUE;
+}
+
+/**
+ * gpk_modal_dialog_button_close_cb:
+ **/
+static void
+gpk_modal_dialog_button_close_cb (GtkWidget *widget_button, GpkModalDialog *dialog)
+{
+ dialog->priv->response = GTK_RESPONSE_CLOSE;
+ g_main_loop_quit (dialog->priv->loop);
+
+ if (dialog->priv->pulse_timer_id != 0) {
+ g_source_remove (dialog->priv->pulse_timer_id);
+ dialog->priv->pulse_timer_id = 0;
+ }
+
+ gpk_animated_icon_enable_animation (GPK_ANIMATED_ICON (dialog->priv->image_status), FALSE);
+ if (g_main_loop_is_running (dialog->priv->loop))
+ g_main_loop_quit (dialog->priv->loop);
+ else
+ g_signal_emit (dialog, signals [GPK_MODAL_DIALOG_CLOSE], 0);
+}
+
+/**
+ * gpk_modal_dialog_set_help_id:
+ **/
+gboolean
+gpk_modal_dialog_set_help_id (GpkModalDialog *dialog, const gchar *help_id)
+{
+ g_return_val_if_fail (GPK_IS_CLIENT_DIALOG (dialog), FALSE);
+ g_return_val_if_fail (dialog->priv->help_id == NULL, FALSE);
+ dialog->priv->help_id = g_strdup (help_id);
+ return TRUE;
+}
+
+/**
+ * gpk_modal_dialog_button_help_cb:
+ **/
+static void
+gpk_modal_dialog_button_help_cb (GtkWidget *widget_button, GpkModalDialog *dialog)
+{
+ gpk_gnome_help (dialog->priv->help_id);
+ g_signal_emit (dialog, signals [GPK_MODAL_DIALOG_HELP], 0);
+}
+
+/**
+ * gpk_modal_dialog_button_action_cb:
+ **/
+static void
+gpk_modal_dialog_button_action_cb (GtkWidget *widget_button, GpkModalDialog *dialog)
+{
+ dialog->priv->response = GTK_RESPONSE_OK;
+ g_main_loop_quit (dialog->priv->loop);
+ if (g_main_loop_is_running (dialog->priv->loop))
+ g_main_loop_quit (dialog->priv->loop);
+ else
+ g_signal_emit (dialog, signals [GPK_MODAL_DIALOG_ACTION], 0);
+}
+
+/**
+ * gpk_modal_dialog_button_cancel_cb:
+ **/
+static void
+gpk_modal_dialog_button_cancel_cb (GtkWidget *widget_button, GpkModalDialog *dialog)
+{
+ dialog->priv->response = GTK_RESPONSE_CANCEL;
+ if (g_main_loop_is_running (dialog->priv->loop))
+ g_main_loop_quit (dialog->priv->loop);
+ else
+ g_signal_emit (dialog, signals [GPK_MODAL_DIALOG_CANCEL], 0);
+}
+
+/**
+ * gpk_modal_dialog_set_package_list:
+ **/
+gboolean
+gpk_modal_dialog_set_package_list (GpkModalDialog *dialog, const PkPackageList *list)
+{
+ GtkTreeIter iter;
+ const PkPackageObj *obj;
+ PkDesktop *desktop;
+ gchar *icon;
+ gchar *package_id;
+ gchar *text;
+ guint length;
+ guint i;
+ GtkWidget *widget;
+
+ gtk_list_store_clear (dialog->priv->store);
+
+ length = pk_package_list_get_size (list);
+ widget = GTK_WIDGET (gtk_builder_get_object (dialog->priv->builder, "scrolledwindow_packages"));
+ if (length > 5)
+ gtk_widget_set_size_request (widget, -1, 300);
+ else if (length > 1)
+ gtk_widget_set_size_request (widget, -1, 150);
+
+ desktop = pk_desktop_new ();
+ length = pk_package_list_get_size (list);
+
+ /* add each well */
+ for (i=0; i<length; i++) {
+ obj = pk_package_list_get_obj (list, i);
+
+ /* not installed, so ignore icon */
+ if (obj->info == PK_INFO_ENUM_DOWNLOADING ||
+ obj->info == PK_INFO_ENUM_CLEANUP)
+ continue;
+
+ text = gpk_package_id_format_twoline (obj->id, obj->summary);
+ package_id = pk_package_id_to_string (obj->id);
+
+ /* get the icon */
+ icon = gpk_desktop_guess_icon_name (desktop, obj->id->name);
+ if (icon == NULL)
+ icon = g_strdup (gpk_info_enum_to_icon_name (PK_INFO_ENUM_INSTALLED));
+
+ gtk_list_store_append (dialog->priv->store, &iter);
+ gtk_list_store_set (dialog->priv->store, &iter,
+ GPK_MODAL_DIALOG_STORE_IMAGE, icon,
+ GPK_MODAL_DIALOG_STORE_ID, package_id,
+ GPK_MODAL_DIALOG_STORE_TEXT, text,
+ -1);
+ g_free (icon);
+ g_free (text);
+ g_free (package_id);
+ }
+
+ g_object_unref (desktop);
+
+ return TRUE;
+}
+
+
+/**
+ * gpk_dialog_treeview_for_package_list:
+ **/
+static gboolean
+gpk_dialog_treeview_for_package_list (GpkModalDialog *dialog)
+{
+ GtkTreeView *treeview;
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+ GtkTreeSelection *selection;
+
+ treeview = GTK_TREE_VIEW (gtk_builder_get_object (dialog->priv->builder, "treeview_packages"));
+
+ /* column for images */
+ column = gtk_tree_view_column_new ();
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (renderer, "stock-size", GTK_ICON_SIZE_DND, NULL);
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_add_attribute (column, renderer, "icon-name", GPK_MODAL_DIALOG_STORE_IMAGE);
+ gtk_tree_view_append_column (treeview, column);
+
+ /* column for name */
+ renderer = gtk_cell_renderer_text_new ();
+ /* TRANSLATORS: column for the package name */
+ column = gtk_tree_view_column_new_with_attributes (_("Name"), renderer,
+ "markup", GPK_MODAL_DIALOG_STORE_TEXT, NULL);
+ gtk_tree_view_column_set_sort_column_id (column, GPK_MODAL_DIALOG_STORE_TEXT);
+ gtk_tree_view_append_column (treeview, column);
+
+ /* set some common options */
+ gtk_tree_view_set_headers_visible (treeview, FALSE);
+ selection = gtk_tree_view_get_selection (treeview);
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE);
+ gtk_tree_selection_unselect_all (selection);
+
+ return TRUE;
+}
+
+/**
+ * gpk_modal_dialog_class_init:
+ * @klass: The GpkModalDialogClass
+ **/
+static void
+gpk_modal_dialog_class_init (GpkModalDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gpk_modal_dialog_finalize;
+ g_type_class_add_private (klass, sizeof (GpkModalDialogPrivate));
+ signals [GPK_MODAL_DIALOG_QUIT] =
+ g_signal_new ("quit",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals [GPK_MODAL_DIALOG_CLOSE] =
+ g_signal_new ("close",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals [GPK_MODAL_DIALOG_ACTION] =
+ g_signal_new ("action",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals [GPK_MODAL_DIALOG_CANCEL] =
+ g_signal_new ("cancel",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals [GPK_MODAL_DIALOG_HELP] =
+ g_signal_new ("help",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+/**
+ * gpk_modal_dialog_init:
+ * @dialog: This class instance
+ **/
+static void
+gpk_modal_dialog_init (GpkModalDialog *dialog)
+{
+ GtkWidget *widget;
+ GtkTreeView *treeview;
+ guint retval;
+ GError *error = NULL;
+ GtkBox *box;
+
+ dialog->priv = GPK_MODAL_DIALOG_GET_PRIVATE (dialog);
+
+ dialog->priv->loop = g_main_loop_new (NULL, FALSE);
+ dialog->priv->response = GTK_RESPONSE_NONE;
+ dialog->priv->pulse_timer_id = 0;
+ dialog->priv->show_progress_files = TRUE;
+ dialog->priv->has_parent = FALSE;
+ dialog->priv->set_image = FALSE;
+ dialog->priv->page = GPK_MODAL_DIALOG_PAGE_UNKNOWN;
+ dialog->priv->options = 0;
+ dialog->priv->help_id = NULL;
+ dialog->priv->title = NULL;
+
+ dialog->priv->store = gtk_list_store_new (GPK_MODAL_DIALOG_STORE_LAST,
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+ /* get UI */
+ dialog->priv->builder = gtk_builder_new ();
+ retval = gtk_builder_add_from_file (dialog->priv->builder, GPK_DATA "/gpk-client.ui", &error);
+ if (error != NULL) {
+ egg_warning ("failed to load ui: %s", error->message);
+ g_error_free (error);
+ goto out_build;
+ }
+
+ /* add animated widget */
+ dialog->priv->image_status = gpk_animated_icon_new ();
+ box = GTK_BOX (gtk_builder_get_object (dialog->priv->builder, "hbox_status"));
+ gtk_box_pack_start (box, dialog->priv->image_status, FALSE, FALSE, 0);
+ gtk_widget_show (dialog->priv->image_status);
+
+ gpk_dialog_treeview_for_package_list (dialog);
+
+ treeview = GTK_TREE_VIEW (gtk_builder_get_object (dialog->priv->builder, "treeview_packages"));
+ gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (dialog->priv->store));
+
+ /* common stuff */
+ widget = GTK_WIDGET (gtk_builder_get_object (dialog->priv->builder, "dialog_client"));
+ g_signal_connect (widget, "delete_event", G_CALLBACK (gpk_modal_dialog_window_delete_cb), dialog);
+ widget = GTK_WIDGET (gtk_builder_get_object (dialog->priv->builder, "button_close"));
+ g_signal_connect (widget, "clicked", G_CALLBACK (gpk_modal_dialog_button_close_cb), dialog);
+ widget = GTK_WIDGET (gtk_builder_get_object (dialog->priv->builder, "button_help"));
+ g_signal_connect (widget, "clicked", G_CALLBACK (gpk_modal_dialog_button_help_cb), dialog);
+ widget = GTK_WIDGET (gtk_builder_get_object (dialog->priv->builder, "button_action"));
+ g_signal_connect (widget, "clicked", G_CALLBACK (gpk_modal_dialog_button_action_cb), dialog);
+ widget = GTK_WIDGET (gtk_builder_get_object (dialog->priv->builder, "button_cancel"));
+ g_signal_connect (widget, "clicked", G_CALLBACK (gpk_modal_dialog_button_cancel_cb), dialog);
+
+ /* set the message text an absolute width so it's forced to wrap */
+ widget = GTK_WIDGET (gtk_builder_get_object (dialog->priv->builder, "hbox_message"));
+ gtk_widget_set_size_request (widget, 400, -1);
+ widget = GTK_WIDGET (gtk_builder_get_object (dialog->priv->builder, "label_message"));
+ gtk_widget_set_size_request (widget, 400, -1);
+
+out_build:
+ /* clear status and progress text */
+ gpk_modal_dialog_set_window_title (dialog, "");
+ gpk_modal_dialog_set_title (dialog, "");
+ gpk_modal_dialog_set_message (dialog, "");
+}
+
+/**
+ * gpk_modal_dialog_finalize:
+ * @object: The object to finalize
+ **/
+static void
+gpk_modal_dialog_finalize (GObject *object)
+{
+ GpkModalDialog *dialog;
+ g_return_if_fail (GPK_IS_CLIENT_DIALOG (object));
+
+ dialog = GPK_MODAL_DIALOG (object);
+ g_return_if_fail (dialog->priv != NULL);
+
+ /* no updates, we're about to rip the builder up */
+ if (dialog->priv->pulse_timer_id != 0)
+ g_source_remove (dialog->priv->pulse_timer_id);
+
+ /* if it's closed, then hide */
+ gpk_modal_dialog_close (dialog);
+
+ /* shouldn't be, but just in case */
+ if (g_main_loop_is_running (dialog->priv->loop)) {
+ egg_warning ("mainloop running on exit");
+ g_main_loop_quit (dialog->priv->loop);
+ }
+
+ g_object_unref (dialog->priv->store);
+ g_object_unref (dialog->priv->builder);
+ g_main_loop_unref (dialog->priv->loop);
+ g_free (dialog->priv->help_id);
+ g_free (dialog->priv->title);
+
+ G_OBJECT_CLASS (gpk_modal_dialog_parent_class)->finalize (object);
+}
+
+/**
+ * gpk_modal_dialog_new:
+ *
+ * Return value: a new GpkModalDialog object.
+ **/
+GpkModalDialog *
+gpk_modal_dialog_new (void)
+{
+ GpkModalDialog *dialog;
+ dialog = g_object_new (GPK_TYPE_CLIENT_DIALOG, NULL);
+ return GPK_MODAL_DIALOG (dialog);
+}
+
+/***************************************************************************
+ *** MAKE CHECK TESTS ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+gpk_modal_dialog_test (EggTest *test)
+{
+ GtkResponseType button;
+ GpkModalDialog *dialog = NULL;
+ PkPackageList *list;
+ PkPackageId *id;
+
+ if (!egg_test_start (test, "GpkModalDialog"))
+ return;
+
+ /************************************************************/
+ egg_test_title (test, "get GpkModalDialog object");
+ dialog = gpk_modal_dialog_new ();
+ if (dialog != NULL)
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, NULL);
+
+ /* set some packages */
+ list = pk_package_list_new ();
+ id = pk_package_id_new_from_list ("totem", "0.0.1", "i386", "fedora-newkey");
+ pk_package_list_add (list, PK_INFO_ENUM_INSTALLED, id, "Totem is a music player for GNOME");
+ pk_package_list_add (list, PK_INFO_ENUM_AVAILABLE, id, "Amarok is a music player for KDE");
+ gpk_modal_dialog_set_package_list (dialog, list);
+ pk_package_id_free (id);
+ g_object_unref (list);
+
+ /************************************************************/
+ egg_test_title (test, "help button");
+ gpk_modal_dialog_setup (dialog, GPK_MODAL_DIALOG_PAGE_WARNING, 0);
+ gpk_modal_dialog_set_window_title (dialog, "PackageKit self test");
+ gpk_modal_dialog_set_title (dialog, "Button press test");
+ gpk_modal_dialog_set_message (dialog, "Please press close");
+ gpk_modal_dialog_set_image (dialog, "dialog-warning");
+ gpk_modal_dialog_present (dialog);
+ button = gpk_modal_dialog_run (dialog);
+ if (button == GTK_RESPONSE_CLOSE)
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "got id %i", button);
+
+ /************************************************************/
+ egg_test_title (test, "confirm button");
+ gpk_modal_dialog_setup (dialog, GPK_MODAL_DIALOG_PAGE_CONFIRM, 0);
+ gpk_modal_dialog_set_title (dialog, "Button press test with a really really long title");
+ gpk_modal_dialog_set_message (dialog, "Please press Uninstall\n\nThis is a really really, really,\nreally long title <i>with formatting</i>");
+ gpk_modal_dialog_set_image (dialog, "dialog-information");
+ gpk_modal_dialog_set_action (dialog, "Uninstall");
+ gpk_modal_dialog_present (dialog);
+ button = gpk_modal_dialog_run (dialog);
+ if (button == GTK_RESPONSE_OK)
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "got id %i", button);
+
+ /************************************************************/
+ egg_test_title (test, "no message");
+ gpk_modal_dialog_setup (dialog, GPK_MODAL_DIALOG_PAGE_PROGRESS, 0);
+ gpk_modal_dialog_set_title (dialog, "Refresh cache");
+ gpk_modal_dialog_set_image_status (dialog, PK_STATUS_ENUM_REFRESH_CACHE);
+ gpk_modal_dialog_set_percentage (dialog, 101);
+ gpk_modal_dialog_present (dialog);
+ gpk_modal_dialog_run (dialog);
+ egg_test_success (test, NULL);
+
+ /************************************************************/
+ egg_test_title (test, "progress");
+ gpk_modal_dialog_setup (dialog, GPK_MODAL_DIALOG_PAGE_PROGRESS, GPK_MODAL_DIALOG_PACKAGE_PADDING);
+ gpk_modal_dialog_set_title (dialog, "Button press test");
+ gpk_modal_dialog_set_message (dialog, "Please press cancel");
+ gpk_modal_dialog_set_image_status (dialog, PK_STATUS_ENUM_RUNNING);
+ gpk_modal_dialog_set_percentage (dialog, 50);
+ gpk_modal_dialog_present (dialog);
+ button = gpk_modal_dialog_run (dialog);
+ if (button == GTK_RESPONSE_CANCEL)
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "got id %i", button);
+
+ /************************************************************/
+ egg_test_title (test, "progress");
+ gpk_modal_dialog_setup (dialog, GPK_MODAL_DIALOG_PAGE_PROGRESS, pk_bitfield_from_enums (GPK_MODAL_DIALOG_WIDGET_MESSAGE, -1));
+ gpk_modal_dialog_set_title (dialog, "Button press test");
+ gpk_modal_dialog_set_message (dialog, "Please press close");
+ gpk_modal_dialog_set_image_status (dialog, PK_STATUS_ENUM_INSTALL);
+ gpk_modal_dialog_set_percentage (dialog, 101);
+ gpk_modal_dialog_present (dialog);
+ button = gpk_modal_dialog_run (dialog);
+ if (button == GTK_RESPONSE_CLOSE)
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "got id %i", button);
+
+ /************************************************************/
+ egg_test_title (test, "confirm install button");
+ gpk_modal_dialog_setup (dialog, GPK_MODAL_DIALOG_PAGE_CONFIRM, GPK_MODAL_DIALOG_PACKAGE_LIST);
+ gpk_modal_dialog_set_title (dialog, "Button press test");
+ gpk_modal_dialog_set_message (dialog, "Please press Install if you can see the package list");
+ gpk_modal_dialog_set_image (dialog, "dialog-information");
+ gpk_modal_dialog_set_action (dialog, "Install");
+ gpk_modal_dialog_present (dialog);
+ button = gpk_modal_dialog_run (dialog);
+ if (button == GTK_RESPONSE_OK)
+ egg_test_success (test, NULL);
+ else
+ egg_test_failed (test, "got id %i", button);
+
+ gpk_modal_dialog_close (dialog);
+
+ g_object_unref (dialog);
+
+ egg_test_end (test);
+}
+#endif
+
Added: trunk/src/gpk-modal-dialog.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-modal-dialog.h Tue Apr 14 16:28:59 2009
@@ -0,0 +1,130 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GPK_MODAL_DIALOG_H
+#define __GPK_MODAL_DIALOG_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <packagekit-glib/packagekit.h>
+
+G_BEGIN_DECLS
+
+#define GPK_TYPE_CLIENT_DIALOG (gpk_modal_dialog_get_type ())
+#define GPK_MODAL_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GPK_TYPE_CLIENT_DIALOG, GpkModalDialog))
+#define GPK_MODAL_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GPK_TYPE_CLIENT_DIALOG, GpkModalDialogClass))
+#define GPK_IS_CLIENT_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GPK_TYPE_CLIENT_DIALOG))
+#define GPK_IS_CLIENT_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GPK_TYPE_CLIENT_DIALOG))
+#define GPK_MODAL_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GPK_TYPE_CLIENT_DIALOG, GpkModalDialogClass))
+#define GPK_MODAL_DIALOG_ERROR (gpk_modal_dialog_error_quark ())
+#define GPK_MODAL_DIALOG_TYPE_ERROR (gpk_modal_dialog_error_get_type ())
+
+/**
+ * GpkModalDialogPage:
+ */
+typedef enum
+{
+ GPK_MODAL_DIALOG_PAGE_CONFIRM,
+ GPK_MODAL_DIALOG_PAGE_PROGRESS,
+ GPK_MODAL_DIALOG_PAGE_FINISHED,
+ GPK_MODAL_DIALOG_PAGE_WARNING,
+ GPK_MODAL_DIALOG_PAGE_CUSTOM,
+ GPK_MODAL_DIALOG_PAGE_UNKNOWN
+} GpkModalDialogPage;
+
+/**
+ * GpkModalDialogWidgets:
+ */
+typedef enum
+{
+ GPK_MODAL_DIALOG_WIDGET_BUTTON_HELP,
+ GPK_MODAL_DIALOG_WIDGET_BUTTON_CANCEL,
+ GPK_MODAL_DIALOG_WIDGET_BUTTON_CLOSE,
+ GPK_MODAL_DIALOG_WIDGET_BUTTON_ACTION,
+ GPK_MODAL_DIALOG_WIDGET_PADDING,
+ GPK_MODAL_DIALOG_WIDGET_PACKAGE_LIST,
+ GPK_MODAL_DIALOG_WIDGET_PROGRESS_BAR,
+ GPK_MODAL_DIALOG_WIDGET_MESSAGE,
+ GPK_MODAL_DIALOG_WIDGET_UNKNOWN
+} GpkModalDialogWidgets;
+
+/* helpers */
+#define GPK_MODAL_DIALOG_PACKAGE_PADDING pk_bitfield_from_enums (GPK_MODAL_DIALOG_WIDGET_PADDING, GPK_MODAL_DIALOG_WIDGET_MESSAGE, -1)
+#define GPK_MODAL_DIALOG_PACKAGE_LIST pk_bitfield_value (GPK_MODAL_DIALOG_WIDGET_PACKAGE_LIST)
+#define GPK_MODAL_DIALOG_BUTTON_ACTION pk_bitfield_value (GPK_MODAL_DIALOG_WIDGET_BUTTON_ACTION)
+
+typedef struct _GpkModalDialogPrivate GpkModalDialogPrivate;
+typedef struct _GpkModalDialog GpkModalDialog;
+typedef struct _GpkModalDialogClass GpkModalDialogClass;
+
+struct _GpkModalDialog
+{
+ GObject parent;
+ GpkModalDialogPrivate *priv;
+};
+
+struct _GpkModalDialogClass
+{
+ GObjectClass parent_class;
+};
+
+GQuark gpk_modal_dialog_error_quark (void);
+GType gpk_modal_dialog_get_type (void);
+GpkModalDialog *gpk_modal_dialog_new (void);
+
+gboolean gpk_modal_dialog_present (GpkModalDialog *dialog);
+gboolean gpk_modal_dialog_present_with_time (GpkModalDialog *dialog,
+ guint32 timestamp);
+gboolean gpk_modal_dialog_set_package_list (GpkModalDialog *dialog,
+ const PkPackageList *list);
+gboolean gpk_modal_dialog_set_parent (GpkModalDialog *dialog,
+ GdkWindow *window);
+gboolean gpk_modal_dialog_set_window_icon (GpkModalDialog *dialog,
+ const gchar *icon);
+gboolean gpk_modal_dialog_set_title (GpkModalDialog *dialog,
+ const gchar *title);
+gboolean gpk_modal_dialog_set_message (GpkModalDialog *dialog,
+ const gchar *message);
+gboolean gpk_modal_dialog_set_action (GpkModalDialog *dialog,
+ const gchar *action);
+gboolean gpk_modal_dialog_set_percentage (GpkModalDialog *dialog,
+ guint percentage);
+gboolean gpk_modal_dialog_set_remaining (GpkModalDialog *dialog,
+ guint remaining);
+gboolean gpk_modal_dialog_set_image (GpkModalDialog *dialog,
+ const gchar *image);
+gboolean gpk_modal_dialog_set_image_status (GpkModalDialog *dialog,
+ PkStatusEnum status);
+gboolean gpk_modal_dialog_set_allow_cancel (GpkModalDialog *dialog,
+ gboolean can_cancel);
+gboolean gpk_modal_dialog_set_help_id (GpkModalDialog *dialog,
+ const gchar *help_id);
+GtkWindow *gpk_modal_dialog_get_window (GpkModalDialog *dialog);
+GtkResponseType gpk_modal_dialog_run (GpkModalDialog *dialog);
+gboolean gpk_modal_dialog_close (GpkModalDialog *dialog);
+gboolean gpk_modal_dialog_setup (GpkModalDialog *dialog,
+ GpkModalDialogPage page,
+ PkBitfield options);
+
+G_END_DECLS
+
+#endif /* __GPK_MODAL_DIALOG_H */
+
Modified: trunk/src/gpk-self-test.c
==============================================================================
--- trunk/src/gpk-self-test.c (original)
+++ trunk/src/gpk-self-test.c Tue Apr 14 16:28:59 2009
@@ -30,7 +30,7 @@
void egg_string_test (EggTest *test);
void gpk_dbus_test (EggTest *test);
void gpk_language_test (EggTest *test);
-void gpk_client_dialog_test (EggTest *test);
+void gpk_modal_dialog_test (EggTest *test);
void gpk_client_test (EggTest *test);
void gpk_error_test (EggTest *test);
@@ -54,8 +54,8 @@
// gpk_dbus_test (test);
gpk_language_test (test);
gpk_error_test (test);
- gpk_client_test (test);
- gpk_client_dialog_test (test);
+// gpk_client_test (test);
+ gpk_modal_dialog_test (test);
return egg_test_finish (test);
}
Modified: trunk/src/gpk-update-viewer.c
==============================================================================
--- trunk/src/gpk-update-viewer.c (original)
+++ trunk/src/gpk-update-viewer.c Tue Apr 14 16:28:59 2009
@@ -46,12 +46,11 @@
#include "gpk-cell-renderer-info.h"
#include "gpk-cell-renderer-restart.h"
#include "gpk-cell-renderer-percentage.h"
-#include "gpk-client.h"
#include "gpk-enum.h"
#include "gpk-helper-repo-signature.h"
#include "gpk-helper-eula.h"
-#define GPK_UPDATE_VIEWER_AUTO_CLOSE_TIMEOUT 10 /* seconds */
+#define GPK_UPDATE_VIEWER_AUTO_QUIT_TIMEOUT 10 /* seconds */
#define GPK_UPDATE_VIEWER_AUTO_RESTART_TIMEOUT 60 /* seconds */
#define GPK_UPDATE_VIEWER_MOBILE_SMALL_SIZE 512*1024 /* bytes */
#define GNOME_SESSION_MANAGER_SERVICE "org.gnome.SessionManager"
@@ -72,8 +71,8 @@
static EggMarkdown *markdown = NULL;
static PkPackageId *package_id_last = NULL;
static PkRestartEnum restart_update = PK_RESTART_ENUM_NONE;
-static gboolean running_hidden = FALSE;
static guint size_total = 0;
+static GConfClient *gconf_client = NULL;
enum {
GPK_UPDATES_COLUMN_TEXT,
@@ -157,15 +156,94 @@
}
/**
- * gpk_update_viewer_button_close_cb:
+ * gpk_update_viewer_quit:
**/
static void
-gpk_update_viewer_button_close_cb (GtkWidget *widget, gpointer data)
+gpk_update_viewer_quit (void)
{
+ gboolean ret;
+ gboolean allow_cancel = FALSE;
+ GError *error = NULL;
+ PkRoleEnum role;
+ PkStatusEnum status;
+ GtkWindow *window;
+ GtkWidget *dialog;
+ GtkResponseType response;
+
+ /* are we in a transaction */
+ ret = pk_client_get_role (client_primary, &role, NULL, &error);
+ if (!ret) {
+ egg_warning ("failed to get role: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+ if (role == PK_ROLE_ENUM_UNKNOWN) {
+ egg_debug ("no role, so quitting");
+ goto out;
+ }
+ ret = pk_client_get_status (client_primary, &status, &error);
+ if (!ret) {
+ egg_warning ("failed to get status: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+ if (status == PK_STATUS_ENUM_FINISHED) {
+ egg_debug ("status is finished, so quitting");
+ goto out;
+ }
+
+ /* can we easily cancel */
+ ret = pk_client_get_allow_cancel (client_primary, &allow_cancel, &error);
+ if (!ret) {
+ egg_warning ("failed to get allow cancel state: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* cancel the transaction */
+ if (allow_cancel) {
+ ret = pk_client_cancel (client_primary, &error);
+ if (!ret) {
+ egg_warning ("failed to cancel client: %s", error->message);
+ g_error_free (error);
+ }
+ goto out;
+ }
+
+ /* show modal dialog asking for confirmation */
+ window = GTK_WINDOW (gtk_builder_get_object (builder, "dialog_updates"));
+ dialog = gtk_message_dialog_new (window, GTK_DIALOG_MODAL,
+ GTK_MESSAGE_INFO, GTK_BUTTONS_CANCEL,
+ "%s", _("Cannot cancel running task"));
+
+ /* TRANSLATORS: this is the button text when we check if it's okay to download */
+ gtk_dialog_add_button (GTK_DIALOG (dialog), "gtk-quit", GTK_RESPONSE_OK);
+
+ /* TRANSLATORS, user clicked the [x] when we cannot cancel what we are doing */
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG(dialog),
+ "%s", _("There are tasks that cannot be cancelled."));
+
+ gtk_window_set_icon_name (GTK_WINDOW(dialog), GPK_ICON_SOFTWARE_INSTALLER);
+ response = gtk_dialog_run (GTK_DIALOG(dialog));
+ gtk_widget_destroy (dialog);
+
+ /* pressed cancel or [x] */
+ if (response != GTK_RESPONSE_OK)
+ return;
+out:
g_main_loop_quit (loop);
}
/**
+ * gpk_update_viewer_button_quit_cb:
+ **/
+static void
+gpk_update_viewer_button_quit_cb (GtkWidget *widget, gpointer data)
+{
+ gpk_update_viewer_quit ();
+}
+
+/**
* gpk_update_viewer_undisable_packages:
**/
static void
@@ -221,6 +299,11 @@
if (size < GPK_UPDATE_VIEWER_MOBILE_SMALL_SIZE)
goto out;
+ /* not when ignored */
+ ret = gconf_client_get_bool (gconf_client, GPK_CONF_UPDATE_VIEWER_MOBILE_BBAND, NULL);
+ if (!ret)
+ goto out;
+
/* show modal dialog */
window = GTK_WINDOW (gtk_builder_get_object (builder, "dialog_updates"));
dialog = gtk_message_dialog_new (window, GTK_DIALOG_MODAL,
@@ -354,23 +437,6 @@
}
/**
- * gpk_update_viewer_button_cancel_cb:
- **/
-static void
-gpk_update_viewer_button_cancel_cb (GtkWidget *widget, gpointer data)
-{
- gboolean ret;
- GError *error = NULL;
-
- /* cancel the transaction */
- ret = pk_client_cancel (client_primary, &error);
- if (!ret) {
- egg_warning ("failed to cancel client: %s", error->message);
- g_error_free (error);
- }
-}
-
-/**
* gpk_update_viewer_button_upgrade_cb:
**/
static void
@@ -392,43 +458,8 @@
static gboolean
gpk_update_viewer_button_delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data)
{
- gboolean ret;
- GError *error = NULL;
- PkRoleEnum role;
- PkStatusEnum status;
-
- /* if we are in a transaction, don't quit, just hide, as we want to return
- * to this state if the dialog is run again */
- ret = pk_client_get_role (client_primary, &role, NULL, &error);
- if (!ret) {
- egg_warning ("failed to get role: %s", error->message);
- g_error_free (error);
- goto out;
- }
- if (role == PK_ROLE_ENUM_UNKNOWN) {
- egg_debug ("no role, so quitting");
- goto out;
- }
- ret = pk_client_get_status (client_primary, &status, &error);
- if (!ret) {
- egg_warning ("failed to get status: %s", error->message);
- g_error_free (error);
- goto out;
- }
- if (status == PK_STATUS_ENUM_FINISHED) {
- egg_debug ("status is finished, so quitting");
- goto out;
- }
-
- /* hide window */
- egg_debug ("hiding to preserve state");
- running_hidden = TRUE;
- widget = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_updates"));
- gtk_widget_hide (widget);
+ gpk_update_viewer_quit ();
return TRUE;
-out:
- g_main_loop_quit (loop);
- return FALSE;
}
/**
@@ -632,31 +663,6 @@
}
/**
- * gpk_update_viewer_reconsider_buttons:
- **/
-static void
-gpk_update_viewer_reconsider_buttons (gpointer data)
-{
- GtkWidget *widget;
- PkStatusEnum status;
-
- /* cancel buttons? */
- pk_client_get_status (client_primary, &status, NULL);
- egg_debug ("status is %s", pk_status_enum_to_text (status));
- if (status == PK_STATUS_ENUM_FINISHED) {
- widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_install"));
- gtk_widget_show (widget);
- widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_cancel"));
- gtk_widget_hide (widget);
- } else {
- widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_install"));
- gtk_widget_hide (widget);
- widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_cancel"));
- gtk_widget_show (widget);
- }
-}
-
-/**
* gpk_update_viewer_auto_shutdown:
**/
static gboolean
@@ -726,7 +732,7 @@
len = PK_OBJ_LIST(update_list)->len;
if (len == 0) {
/* hide close button */
- widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_close"));
+ widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_quit"));
gtk_widget_hide (widget);
/* show a new title */
@@ -739,13 +745,13 @@
/* show modal dialog */
widget = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_updates"));
dialog = gtk_message_dialog_new (GTK_WINDOW (widget), GTK_DIALOG_MODAL,
- GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
+ GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
/* TRANSLATORS: title: warn the user they are quitting with unapplied changes */
- "%s", _("No updates available"));
+ "%s", _("All software is up to date"));
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG(dialog),
"%s",
/* TRANSLATORS: tell the user the problem */
- _("There are no updates available for your computer at this time."));
+ _("There are no software updates available for your computer at this time."));
gtk_window_set_icon_name (GTK_WINDOW(dialog), GPK_ICON_SOFTWARE_INSTALLER);
/* setup a callback so we autoclose */
@@ -819,6 +825,8 @@
{
GtkWidget *widget;
const gchar *text;
+ GdkDisplay *display;
+ GdkCursor *cursor;
egg_debug ("status %s", pk_status_enum_to_text (status));
@@ -831,6 +839,11 @@
/* set cursor back to normal */
if (status == PK_STATUS_ENUM_FINISHED) {
gdk_window_set_cursor (widget->window, NULL);
+ } else {
+ display = gdk_display_get_default ();
+ cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
+ gdk_window_set_cursor (widget->window, cursor);
+ gdk_cursor_unref (cursor);
}
/* clear package */
@@ -862,8 +875,7 @@
gtk_image_set_from_icon_name (GTK_IMAGE (widget), gpk_status_enum_to_icon_name (status), GTK_ICON_SIZE_BUTTON);
gtk_widget_show (widget);
out:
- /* set state */
- gpk_update_viewer_reconsider_buttons (NULL);
+ return;
}
/**
@@ -1017,7 +1029,9 @@
/* info */
renderer = gpk_cell_renderer_info_new ();
- g_object_set (renderer, "stock-size", GTK_ICON_SIZE_BUTTON, NULL);
+ g_object_set (renderer,
+ "stock-size", GTK_ICON_SIZE_BUTTON,
+ "ignore-values", "unknown,normal", NULL);
gtk_tree_view_column_pack_start (column, renderer, TRUE);
gtk_tree_view_column_add_attribute (column, renderer, "value", GPK_UPDATES_COLUMN_INFO);
@@ -1069,7 +1083,9 @@
/* status */
renderer = gpk_cell_renderer_info_new ();
- g_object_set (renderer, "stock-size", GTK_ICON_SIZE_BUTTON, NULL);
+ g_object_set (renderer,
+ "stock-size", GTK_ICON_SIZE_BUTTON,
+ "ignore-values", "unknown", NULL);
gtk_tree_view_column_pack_start (column, renderer, FALSE);
gtk_tree_view_column_add_attribute (column, renderer, "value", GPK_UPDATES_COLUMN_STATUS);
@@ -1297,16 +1313,19 @@
}
/**
- * pk_packages_treeview_clicked_cb:
+ * gpk_packages_treeview_clicked_cb:
**/
static void
-pk_packages_treeview_clicked_cb (GtkTreeSelection *selection, gpointer data)
+gpk_packages_treeview_clicked_cb (GtkTreeSelection *selection, gpointer data)
{
GtkTreeModel *model;
GtkTreeIter iter;
gchar *package_id;
PkUpdateDetailObj *obj = NULL;
+ /* set loading text */
+ gtk_text_buffer_set_text (text_buffer, _("Loading..."), -1);
+
/* This will only work in single or browse selection mode! */
if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
gtk_tree_model_get (model, &iter,
@@ -1455,10 +1474,10 @@
}
/**
- * gpk_update_viewer_requeue:
+ * gpk_update_viewer_primary_requeue:
**/
static gboolean
-gpk_update_viewer_requeue (gpointer data)
+gpk_update_viewer_primary_requeue (gpointer data)
{
gboolean ret;
GError *error = NULL;
@@ -1561,11 +1580,8 @@
widget = GTK_WIDGET (gtk_builder_get_object (builder, "progressbar_progress"));
gtk_widget_hide (widget);
- /* hidden window, so quit at this point */
- if (running_hidden) {
- egg_debug ("transaction finished whilst hidden, so exit");
- g_main_loop_quit (loop);
- }
+ widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_quit"));
+ gtk_widget_set_sensitive (widget, TRUE);
/* if secondary, ignore */
if (client == client_primary &&
@@ -1640,7 +1656,7 @@
if (role == PK_ROLE_ENUM_INSTALL_SIGNATURE ||
role == PK_ROLE_ENUM_ACCEPT_EULA) {
if (exit == PK_EXIT_ENUM_SUCCESS)
- gpk_update_viewer_requeue (NULL);
+ gpk_update_viewer_primary_requeue (NULL);
else
gpk_update_viewer_undisable_packages ();
}
@@ -1977,8 +1993,6 @@
if (command == UNIQUE_ACTIVATE) {
window = GTK_WINDOW (gtk_builder_get_object (builder, "dialog_updates"));
gtk_window_present (window);
- /* not hidden anymore */
- running_hidden = FALSE;
}
}
@@ -2027,21 +2041,9 @@
static void
gpk_update_viewer_allow_cancel_cb (PkClient *client, gboolean allow_cancel, gpointer data)
{
- GdkDisplay *display;
- GdkCursor *cursor;
GtkWidget *widget;
- widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_cancel"));
+ widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_quit"));
gtk_widget_set_sensitive (widget, allow_cancel);
-
- /* set cursor */
- if (allow_cancel) {
- gdk_window_set_cursor (widget->window, NULL);
- } else {
- display = gdk_display_get_default ();
- cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
- gdk_window_set_cursor (widget->window, cursor);
- gdk_cursor_unref (cursor);
- }
}
/**
@@ -2069,7 +2071,6 @@
if (type != GTK_RESPONSE_YES) {
/* we've ruined the old one by making the checkboxes insensitive */
gpk_update_viewer_get_new_update_list ();
- gpk_update_viewer_reconsider_buttons (NULL);
goto out;
}
@@ -2111,7 +2112,6 @@
if (type != GTK_RESPONSE_YES) {
/* we've ruined the old one by making the checkboxes insensitive */
gpk_update_viewer_get_new_update_list ();
- gpk_update_viewer_reconsider_buttons (NULL);
goto out;
}
@@ -2431,6 +2431,9 @@
goto unique_out;
}
+ /* get GConf instance */
+ gconf_client = gconf_client_get_default ();
+
g_signal_connect (unique_app, "message-received", G_CALLBACK (gpk_update_viewer_message_received_cb), NULL);
markdown = egg_markdown_new ();
@@ -2491,6 +2494,7 @@
main_window = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_updates"));
g_signal_connect (main_window, "delete_event", G_CALLBACK (gpk_update_viewer_button_delete_event_cb), NULL);
+ gtk_window_set_icon_name (GTK_WINDOW (main_window), GPK_ICON_SOFTWARE_INSTALLER);
/* helpers */
helper_repo_signature = gpk_helper_repo_signature_new ();
@@ -2543,7 +2547,7 @@
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
g_signal_connect (selection, "changed",
- G_CALLBACK (pk_packages_treeview_clicked_cb), NULL);
+ G_CALLBACK (gpk_packages_treeview_clicked_cb), NULL);
/* bottom UI */
widget = GTK_WIDGET (gtk_builder_get_object (builder, "progressbar_progress"));
@@ -2569,17 +2573,11 @@
gtk_widget_set_sensitive (widget, FALSE);
/* close button */
- widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_close"));
+ widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_quit"));
g_signal_connect (widget, "clicked",
- G_CALLBACK (gpk_update_viewer_button_close_cb), NULL);
+ G_CALLBACK (gpk_update_viewer_button_quit_cb), NULL);
gtk_window_set_focus (GTK_WINDOW(main_window), widget);
- /* hide cancel button */
- widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_cancel"));
- gtk_widget_hide (widget);
- g_signal_connect (widget, "clicked",
- G_CALLBACK (gpk_update_viewer_button_cancel_cb), NULL);
-
/* upgrade button */
widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_upgrade"));
g_signal_connect (widget, "clicked",
@@ -2636,11 +2634,11 @@
g_object_unref (helper_eula);
g_object_unref (helper_repo_signature);
- g_object_unref (builder);
g_object_unref (list_store_updates);
g_object_unref (text_buffer);
pk_package_id_free (package_id_last);
out_build:
+ g_object_unref (gconf_client);
g_object_unref (control);
g_object_unref (markdown);
g_object_unref (client_primary);
Modified: trunk/src/gpk-vendor.h
==============================================================================
--- trunk/src/gpk-vendor.h (original)
+++ trunk/src/gpk-vendor.h Tue Apr 14 16:28:59 2009
@@ -49,7 +49,7 @@
} GpkVendorClass;
/**
- * GpkClientDialogWidgets:
+ * GpkModalDialogWidgets:
*/
typedef enum
{
Modified: trunk/src/gpk-watch.c
==============================================================================
--- trunk/src/gpk-watch.c (original)
+++ trunk/src/gpk-watch.c Tue Apr 14 16:28:59 2009
@@ -46,7 +46,7 @@
#include "gpk-common.h"
#include "gpk-error.h"
#include "gpk-watch.h"
-#include "gpk-client.h"
+#include "gpk-modal-dialog.h"
#include "gpk-inhibit.h"
#include "gpk-smart-icon.h"
#include "gpk-consolekit.h"
@@ -68,13 +68,12 @@
GPtrArray *restart_package_names;
NotifyNotification *notification_cached_messages;
GpkInhibit *inhibit;
- GpkClient *gclient;
- GpkClient *monitor;
+ GpkModalDialog *dialog;
+ PkClient *client_primary;
PkConnection *pconnection;
PkTaskList *tlist;
PkRestartEnum restart;
GConfClient *gconf_client;
- gboolean show_refresh_in_menu;
PolKitGnomeAction *restart_action;
guint set_proxy_timeout;
gchar *error_details;
@@ -339,13 +338,6 @@
{
g_return_if_fail (GPK_IS_WATCH (watch));
- if (pk_task_list_contains_role (tlist, PK_ROLE_ENUM_REFRESH_CACHE) ||
- pk_task_list_contains_role (tlist, PK_ROLE_ENUM_UPDATE_PACKAGES) ||
- pk_task_list_contains_role (tlist, PK_ROLE_ENUM_UPDATE_SYSTEM))
- watch->priv->show_refresh_in_menu = FALSE;
- else
- watch->priv->show_refresh_in_menu = TRUE;
-
gpk_watch_refresh_icon (watch);
gpk_watch_refresh_tooltip (watch);
}
@@ -372,10 +364,10 @@
}
/**
- * gpk_watch_finished_cb:
+ * gpk_watch_task_list_finished_cb:
**/
static void
-gpk_watch_finished_cb (PkTaskList *tlist, PkClient *client, PkExitEnum exit_enum, guint runtime, GpkWatch *watch)
+gpk_watch_task_list_finished_cb (PkTaskList *tlist, PkClient *client, PkExitEnum exit_enum, guint runtime, GpkWatch *watch)
{
guint i;
gboolean ret;
@@ -793,27 +785,6 @@
}
/**
- * gpk_watch_menu_refresh_cache_cb:
- **/
-static void
-gpk_watch_menu_refresh_cache_cb (GtkMenuItem *item, gpointer data)
-{
- gboolean ret;
- GpkWatch *watch = GPK_WATCH (data);
- GError *error = NULL;
-
- g_return_if_fail (GPK_IS_WATCH (watch));
-
- egg_debug ("refresh cache");
- gpk_client_set_interaction (watch->priv->gclient, GPK_CLIENT_INTERACT_ALWAYS);
- ret = gpk_client_refresh_cache (watch->priv->gclient, &error);
- if (!ret) {
- egg_warning ("%s", error->message);
- g_error_free (error);
- }
-}
-
-/**
* gpk_watch_menu_show_messages_cb:
**/
static void
@@ -930,6 +901,214 @@
}
/**
+ * gpk_watch_get_role_text:
+ **/
+static gchar *
+gpk_watch_get_role_text (PkClient *client)
+{
+ const gchar *role_text;
+ gchar *text;
+ gchar *message;
+ PkRoleEnum role;
+ GError *error = NULL;
+ gboolean ret;
+
+ /* get role and text */
+ ret = pk_client_get_role (client, &role, &text, &error);
+ if (!ret) {
+ egg_warning ("failed to get role: %s", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ /* backup */
+ role_text = gpk_role_enum_to_localised_present (role);
+
+ if (!egg_strzero (text) && role != PK_ROLE_ENUM_UPDATE_PACKAGES)
+ message = g_strdup_printf ("%s: %s", role_text, text);
+ else
+ message = g_strdup_printf ("%s", role_text);
+ g_free (text);
+
+ return message;
+}
+
+/**
+ * gpk_watch_progress_changed_cb:
+ **/
+static void
+gpk_watch_progress_changed_cb (PkClient *client, guint percentage, guint subpercentage,
+ guint elapsed, guint remaining, GpkWatch *watch)
+{
+ gpk_modal_dialog_set_percentage (watch->priv->dialog, percentage);
+ gpk_modal_dialog_set_remaining (watch->priv->dialog, remaining);
+}
+
+/**
+ * gpk_watch_set_status:
+ **/
+static gboolean
+gpk_watch_set_status (GpkWatch *watch, PkStatusEnum status)
+{
+ /* do we force progress? */
+ if (status == PK_STATUS_ENUM_DOWNLOAD_REPOSITORY ||
+ status == PK_STATUS_ENUM_DOWNLOAD_PACKAGELIST ||
+ status == PK_STATUS_ENUM_DOWNLOAD_FILELIST ||
+ status == PK_STATUS_ENUM_DOWNLOAD_CHANGELOG ||
+ status == PK_STATUS_ENUM_DOWNLOAD_GROUP ||
+ status == PK_STATUS_ENUM_DOWNLOAD_UPDATEINFO ||
+ status == PK_STATUS_ENUM_REFRESH_CACHE) {
+ gpk_modal_dialog_setup (watch->priv->dialog, GPK_MODAL_DIALOG_PAGE_PROGRESS, 0);
+ }
+
+ /* set icon */
+ gpk_modal_dialog_set_image_status (watch->priv->dialog, status);
+
+ /* set label */
+ gpk_modal_dialog_set_title (watch->priv->dialog, gpk_status_enum_to_localised_text (status));
+
+ /* spin */
+ if (status == PK_STATUS_ENUM_WAIT)
+ gpk_modal_dialog_set_percentage (watch->priv->dialog, PK_CLIENT_PERCENTAGE_INVALID);
+
+ /* do visual stuff when finished */
+ if (status == PK_STATUS_ENUM_FINISHED) {
+ /* make insensitive */
+ gpk_modal_dialog_set_allow_cancel (watch->priv->dialog, FALSE);
+
+ /* stop spinning */
+ gpk_modal_dialog_set_percentage (watch->priv->dialog, 100);
+ }
+ return TRUE;
+}
+
+/**
+ * gpk_watch_status_changed_cb:
+ **/
+static void
+gpk_watch_status_changed_cb (PkClient *client, PkStatusEnum status, GpkWatch *watch)
+{
+ gpk_watch_set_status (watch, status);
+}
+
+/**
+ * gpk_watch_package_cb:
+ **/
+static void
+gpk_watch_package_cb (PkClient *client, const PkPackageObj *obj, GpkWatch *watch)
+{
+ gchar *text;
+ text = gpk_package_id_format_twoline (obj->id, obj->summary);
+ gpk_modal_dialog_set_message (watch->priv->dialog, text);
+ g_free (text);
+}
+
+/**
+ * gpk_watch_monitor_tid:
+ **/
+static gboolean
+gpk_watch_monitor_tid (GpkWatch *watch, const gchar *tid)
+{
+ PkStatusEnum status;
+ gboolean ret;
+ gboolean allow_cancel;
+ gchar *text;
+ gchar *package_id = NULL;
+ guint percentage;
+ guint subpercentage;
+ guint elapsed;
+ guint remaining;
+ GError *error = NULL;
+ PkRoleEnum role;
+
+ /* reset client */
+ ret = pk_client_reset (watch->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("failed to reset client: %s", error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ ret = pk_client_set_tid (watch->priv->client_primary, tid, &error);
+ if (!ret) {
+ egg_warning ("could not set tid: %s", error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ /* fill in role */
+ text = gpk_watch_get_role_text (watch->priv->client_primary);
+ gpk_modal_dialog_set_title (watch->priv->dialog, text);
+ g_free (text);
+
+ /* coldplug */
+ ret = pk_client_get_status (watch->priv->client_primary, &status, NULL);
+ /* no such transaction? */
+ if (!ret) {
+ egg_warning ("could not get status");
+ return FALSE;
+ }
+
+ /* are we cancellable? */
+ pk_client_get_allow_cancel (watch->priv->client_primary, &allow_cancel, NULL);
+ gpk_modal_dialog_set_allow_cancel (watch->priv->dialog, allow_cancel);
+
+ /* coldplug */
+ ret = pk_client_get_progress (watch->priv->client_primary,
+ &percentage, &subpercentage, &elapsed, &remaining, NULL);
+ if (ret) {
+ gpk_watch_progress_changed_cb (watch->priv->client_primary, percentage,
+ subpercentage, elapsed, remaining, watch);
+ } else {
+ egg_warning ("GetProgress failed");
+ gpk_watch_progress_changed_cb (watch->priv->client_primary,
+ PK_CLIENT_PERCENTAGE_INVALID,
+ PK_CLIENT_PERCENTAGE_INVALID, 0, 0, watch);
+ }
+
+ /* get the role */
+ ret = pk_client_get_role (watch->priv->client_primary, &role, NULL, &error);
+ if (!ret) {
+ egg_warning ("failed to get role: %s", error->message);
+ g_error_free (error);
+ }
+
+ /* setup the UI */
+ if (role == PK_ROLE_ENUM_SEARCH_NAME ||
+ role == PK_ROLE_ENUM_SEARCH_GROUP ||
+ role == PK_ROLE_ENUM_SEARCH_DETAILS ||
+ role == PK_ROLE_ENUM_SEARCH_FILE ||
+ role == PK_ROLE_ENUM_SEARCH_NAME ||
+ role == PK_ROLE_ENUM_GET_UPDATES)
+ gpk_modal_dialog_setup (watch->priv->dialog, GPK_MODAL_DIALOG_PAGE_PROGRESS, 0);
+ else
+ gpk_modal_dialog_setup (watch->priv->dialog, GPK_MODAL_DIALOG_PAGE_PROGRESS, GPK_MODAL_DIALOG_PACKAGE_PADDING);
+
+ /* set the status */
+ gpk_watch_set_status (watch, status);
+
+ /* do the best we can, and get the last package */
+ ret = pk_client_get_package (watch->priv->client_primary, &package_id, NULL);
+ if (ret) {
+ PkPackageId *id;
+ PkPackageObj *obj;
+
+ id = pk_package_id_new_from_string (package_id);
+ if (id != NULL) {
+ obj = pk_package_obj_new (PK_INFO_ENUM_UNKNOWN, id, NULL);
+ egg_warning ("package_id=%s", package_id);
+ gpk_watch_package_cb (watch->priv->client_primary, obj, watch);
+ pk_package_obj_free (obj);
+ }
+ pk_package_id_free (id);
+ }
+
+ gpk_modal_dialog_present (watch->priv->dialog);
+
+ return TRUE;
+}
+
+/**
* gpk_watch_menu_job_status_cb:
**/
static void
@@ -947,7 +1126,7 @@
}
/* launch the UI */
- gpk_client_monitor_tid (watch->priv->monitor, tid);
+ gpk_watch_monitor_tid (watch, tid);
}
/**
@@ -1050,24 +1229,6 @@
/* add jobs as drop down */
len = gpk_watch_populate_menu_with_jobs (watch, menu);
- /* force a refresh if we are not updating or refreshing */
- if (watch->priv->show_refresh_in_menu) {
-
- /* Separator for HIG? */
- if (len > 0) {
- widget = gtk_separator_menu_item_new ();
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), widget);
- }
-
- /* TRANSLATORS: This is a right click menu item, and will refresh all the package lists */
- widget = gtk_image_menu_item_new_with_mnemonic (_("_Refresh Software List"));
- image = gtk_image_new_from_icon_name ("view-refresh", GTK_ICON_SIZE_MENU);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (widget), image);
- g_signal_connect (G_OBJECT (widget), "activate",
- G_CALLBACK (gpk_watch_menu_refresh_cache_cb), watch);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), widget);
- }
-
/* any messages to show? */
len = watch->priv->cached_messages->len;
if (len > 0) {
@@ -1328,6 +1489,59 @@
}
/**
+ * gpk_watch_allow_cancel_cb:
+ **/
+static void
+gpk_watch_allow_cancel_cb (PkClient *client, gboolean allow_cancel, GpkWatch *watch)
+{
+ gpk_modal_dialog_set_allow_cancel (watch->priv->dialog, allow_cancel);
+}
+
+/**
+ * gpk_watch_finished_cb:
+ **/
+static void
+gpk_watch_finished_cb (PkClient *client, PkExitEnum exit_enum, guint runtime, GpkWatch *watch)
+{
+ g_return_if_fail (GPK_IS_WATCH (watch));
+
+ /* stop spinning */
+ gpk_modal_dialog_set_percentage (watch->priv->dialog, 100);
+
+ /* autoclose if success */
+ if (exit_enum == PK_EXIT_ENUM_SUCCESS) {
+ gpk_modal_dialog_close (watch->priv->dialog);
+ }
+}
+
+/**
+ * gpk_watch_button_close_cb:
+ **/
+static void
+gpk_watch_button_close_cb (GtkWidget *widget, GpkWatch *watch)
+{
+ /* close, don't abort */
+ gpk_modal_dialog_close (watch->priv->dialog);
+}
+
+/**
+ * gpk_watch_button_cancel_cb:
+ **/
+static void
+gpk_watch_button_cancel_cb (GtkWidget *widget, GpkWatch *watch)
+{
+ gboolean ret;
+ GError *error = NULL;
+
+ /* we might have a transaction running */
+ ret = pk_client_cancel (watch->priv->client_primary, &error);
+ if (!ret) {
+ egg_warning ("failed to cancel client: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+/**
* gpk_watch_init:
* @watch: This class instance
**/
@@ -1343,17 +1557,31 @@
watch->priv->notification_cached_messages = NULL;
watch->priv->restart = PK_RESTART_ENUM_NONE;
- watch->priv->show_refresh_in_menu = TRUE;
watch->priv->gconf_client = gconf_client_get_default ();
watch->priv->sicon = gpk_smart_icon_new ();
watch->priv->set_proxy_timeout = 0;
- watch->priv->gclient = gpk_client_new ();
watch->priv->cached_messages = g_ptr_array_new ();
watch->priv->restart_package_names = g_ptr_array_new ();
- watch->priv->monitor = gpk_client_new ();
- gpk_client_set_interaction (watch->priv->monitor, GPK_CLIENT_INTERACT_WARNING_PROGRESS);
+ watch->priv->client_primary = pk_client_new ();
+ g_signal_connect (watch->priv->client_primary, "finished",
+ G_CALLBACK (gpk_watch_finished_cb), watch);
+ g_signal_connect (watch->priv->client_primary, "progress-changed",
+ G_CALLBACK (gpk_watch_progress_changed_cb), watch);
+ g_signal_connect (watch->priv->client_primary, "status-changed",
+ G_CALLBACK (gpk_watch_status_changed_cb), watch);
+ g_signal_connect (watch->priv->client_primary, "package",
+ G_CALLBACK (gpk_watch_package_cb), watch);
+ g_signal_connect (watch->priv->client_primary, "allow-cancel",
+ G_CALLBACK (gpk_watch_allow_cancel_cb), watch);
+
+ watch->priv->dialog = gpk_modal_dialog_new ();
+ gpk_modal_dialog_set_window_icon (watch->priv->dialog, "pk-package-installed");
+ g_signal_connect (watch->priv->dialog, "cancel",
+ G_CALLBACK (gpk_watch_button_cancel_cb), watch);
+ g_signal_connect (watch->priv->dialog, "close",
+ G_CALLBACK (gpk_watch_button_close_cb), watch);
/* we need to get ::locked */
watch->priv->control = pk_control_new ();
@@ -1376,7 +1604,7 @@
g_signal_connect (watch->priv->tlist, "status-changed",
G_CALLBACK (gpk_watch_task_list_changed_cb), watch);
g_signal_connect (watch->priv->tlist, "finished",
- G_CALLBACK (gpk_watch_finished_cb), watch);
+ G_CALLBACK (gpk_watch_task_list_finished_cb), watch);
g_signal_connect (watch->priv->tlist, "error-code",
G_CALLBACK (gpk_watch_error_code_cb), watch);
g_signal_connect (watch->priv->tlist, "message",
@@ -1451,11 +1679,11 @@
g_object_unref (watch->priv->inhibit);
g_object_unref (watch->priv->tlist);
g_object_unref (watch->priv->control);
- g_object_unref (watch->priv->gclient);
g_object_unref (watch->priv->pconnection);
g_object_unref (watch->priv->gconf_client);
g_object_unref (watch->priv->restart_action);
- g_object_unref (watch->priv->monitor);
+ g_object_unref (watch->priv->client_primary);
+ g_object_unref (watch->priv->dialog);
G_OBJECT_CLASS (gpk_watch_parent_class)->finalize (object);
}
Modified: trunk/src/org.freedesktop.PackageKit.xml
==============================================================================
--- trunk/src/org.freedesktop.PackageKit.xml (original)
+++ trunk/src/org.freedesktop.PackageKit.xml Tue Apr 14 16:28:59 2009
@@ -5,7 +5,6 @@
]>
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
- <!-- ######################################################################################### -->
<interface name="org.freedesktop.PackageKit.Query">
<doc:doc>
<doc:description>
@@ -17,6 +16,7 @@
<!--*****************************************************************************************-->
<method name="IsInstalled">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<doc:doc>
<doc:description>
<doc:para>
@@ -56,6 +56,7 @@
<!--*****************************************************************************************-->
<method name="SearchFile">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<doc:doc>
<doc:description>
<doc:para>
@@ -362,64 +363,5 @@
</arg>
</method>
</interface>
-
- <!-- ######################################################################################### -->
- <!-- LEGACY INTERFACE -->
- <interface name="org.freedesktop.PackageKit">
-<!--
- <method name="IsPackageInstalled">
- <arg type="s" name="package_name" direction="in"/>
- <arg type="b" name="installed" direction="out"/>
- </method>
--->
- <method name="InstallLocalFile">
- <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
- <arg type="u" name="xid" direction="in"/>
- <arg type="u" name="timestamp" direction="in"/>
- <arg type="s" name="full_path" direction="in"/>
- </method>
- <method name="InstallProvideFile">
- <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
- <arg type="u" name="xid" direction="in"/>
- <arg type="u" name="timestamp" direction="in"/>
- <arg type="s" name="full_path" direction="in"/>
- </method>
- <method name="InstallPackageName">
- <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
- <arg type="u" name="xid" direction="in"/>
- <arg type="u" name="timestamp" direction="in"/>
- <arg type="s" name="package_name" direction="in"/>
- </method>
- <method name="InstallMimeType">
- <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
- <arg type="u" name="xid" direction="in"/>
- <arg type="u" name="timestamp" direction="in"/>
- <arg type="s" name="mime_type" direction="in"/>
- </method>
- <method name="InstallGStreamerCodecs">
- <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
- <arg type="u" name="xid" direction="in"/>
- <arg type="u" name="timestamp" direction="in"/>
- <arg type="a(ss)" name="codecs" direction="in"/>
- </method>
- <method name="InstallFont">
- <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
- <arg type="u" name="xid" direction="in"/>
- <arg type="u" name="timestamp" direction="in"/>
- <arg type="s" name="font_desc" direction="in"/>
- </method>
- <method name="InstallFonts">
- <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
- <arg type="u" name="xid" direction="in"/>
- <arg type="u" name="timestamp" direction="in"/>
- <arg type="as" name="font_descs" direction="in"/>
- </method>
- <method name="InstallCatalog">
- <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
- <arg type="u" name="xid" direction="in"/>
- <arg type="u" name="timestamp" direction="in"/>
- <arg type="s" name="catalog_file" direction="in"/>
- </method>
- </interface>
</node>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]