From: J. Ali Harlow Date: Sat, 20 Feb 2010 12:11:02 +0000 (+0000) Subject: First cut at an applications manager X-Git-Tag: 0.3~1 X-Git-Url: http://project.juiblex.co.uk/git/?a=commitdiff_plain;h=70ea5d97c71f800fbaccc1967c05304bed5143da;p=plover.git First cut at an applications manager --- diff --git a/Makefile.am b/Makefile.am index 23ca042..c3475ed 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1 +1 @@ -SUBDIRS=plover setup update +SUBDIRS=plover setup update plover-gtk app-manager diff --git a/app-manager/Makefile.am b/app-manager/Makefile.am new file mode 100644 index 0000000..d577425 --- /dev/null +++ b/app-manager/Makefile.am @@ -0,0 +1,31 @@ +AM_CFLAGS=$(GUI_CFLAGS) -g -DPLOVER_DATADIR=\""$(pkgdatadir)"\" -I$(top_srcdir) +LDADD=../plover/libplover.la ../plover-gtk/libplover-gtk.la $(GUI_LIBS) + +bin_PROGRAMS=app-manager +app_manager_SOURCES=app-manager.c app-manager.h packagelist.c applications.c \ + localmedia.c localmedia.h +if HAVE_WINDRES +app_manager_SOURCES+=resources.rc +endif +uidir=$(pkgdatadir) +ui_DATA=app-manager.ui +desktopdir=$(datadir)/applications +desktop_DATA=app-manager.desktop +scaleabledir=$(datadir)/icons/hicolor/scalable/apps +scaleable_DATA=plover-applications.svg + +.rc.$(OBJEXT): + $(WINDRES) $< $@ + +resources.$(OBJEXT): plover-applications.ico + +plover-applications%.pnm: plover-applications.svg + rsvg -w $* -h $* -f png $< temp.png + pngtopnm temp.png | pnmquant 256 > $@ + $(RM) temp.png + +app-manager.ico: plover-applications16.pnm \ + plover-applications22.pnm plover-applications32.pnm + ppmtowinicon -output=$@ $^ + +EXTRA_DIST=app-manager.desktop app-manager.ui plover-applications.svg diff --git a/app-manager/app-manager.c b/app-manager/app-manager.c new file mode 100644 index 0000000..e897c89 --- /dev/null +++ b/app-manager/app-manager.c @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2010 J. Ali Harlow + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include "app-manager.h" +#include "localmedia.h" + +#define LOGO_NAME "plover-applications" + +GtkBuilder *ui; +GtkTreeModel *installed,*applications,*location,*local_media; + +int main(int argc,char **argv) +{ + GError *err=0; + GtkWidget *w; + gchar *s,*contents; + gsize len; + PloverPackageSet *set; + GOptionEntry options[]={ + {NULL} + }; + if (!gtk_init_with_args(&argc,&argv,NULL,options,NULL,&err)) + { + g_printerr("%s",err->message); + exit(0); + } + gtk_window_set_default_icon_name(LOGO_NAME); + ui=gtk_builder_new(); + if (!g_file_get_contents("app-manager.ui",&contents,&len,&err) && + g_error_matches(err,G_FILE_ERROR,G_FILE_ERROR_NOENT)) + { + g_clear_error(&err); + s=g_build_filename(PLOVER_DATADIR,"app-manager.ui",NULL); + (void)g_file_get_contents(s,&contents,&len,&err); + g_free(s); + } + if (!err) + { + (void)gtk_builder_add_from_string(ui,contents,len,&err); + g_free(contents); + } + if (err) + { + g_error("%s",err->message); + exit(0); + } + gtk_builder_connect_signals(ui,NULL); + installed=GTK_TREE_MODEL(plover_package_store_new()); + set=plover_package_set_new_from_installed("",NULL); + if (set) + plover_package_store_add_set(PLOVER_PACKAGE_STORE(installed),set); + applications=plover_applications_model_new(installed); + set_package_model(applications); + gtk_main(); + g_object_unref(ui); + exit(0); +} + +G_MODULE_EXPORT void + on_applications_toggled(GtkToggleToolButton *button,gpointer data) +{ + if (gtk_toggle_tool_button_get_active(button)) + { + if (!applications) + applications=plover_applications_model_new(installed); + set_package_model(applications); + } +} + +G_MODULE_EXPORT void + on_all_packages_toggled(GtkToggleToolButton *button,gpointer data) +{ + if (gtk_toggle_tool_button_get_active(button)) + set_package_model(installed); +} + +G_MODULE_EXPORT void + on_local_media_toggled(GtkToggleToolButton *button,gpointer data) +{ + if (gtk_toggle_tool_button_get_active(button)) + { + if (!local_media) + local_media=plover_local_media_store_new(); + set_package_model(local_media); + } +} + +G_MODULE_EXPORT void + on_location_toggled(GtkToggleToolButton *button,gpointer data) +{ + if (gtk_toggle_tool_button_get_active(button)) + set_package_model(location); +} + +G_MODULE_EXPORT void on_open_location(GtkWidget *widget) +{ + GtkWidget *w=GTK_WIDGET(gtk_builder_get_object(ui,"MainWindow")); + GtkWidget *dialog; + gchar *path,*name; + PloverPackageSet *set; + GSList *sets; + GError *err=NULL; + dialog=gtk_file_chooser_dialog_new("Open Location",GTK_WINDOW(w), + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL,GTK_STOCK_OPEN,GTK_RESPONSE_ACCEPT,NULL); +#if GTK_CHECK_VERSION(2,18,0) + gtk_file_chooser_set_create_folders(GTK_FILE_CHOOSER(dialog),FALSE); +#endif + if (gtk_dialog_run(GTK_DIALOG(dialog))==GTK_RESPONSE_ACCEPT) + { + path=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + set=plover_package_set_new_from_repository(path,&err); + if (set) + { + if (!location) + location=GTK_TREE_MODEL(plover_package_store_new()); + while((sets= + plover_package_store_get_sets(PLOVER_PACKAGE_STORE(location)))) + plover_package_store_remove_set(PLOVER_PACKAGE_STORE(location), + PLOVER_PACKAGE_SET(sets->data)); + plover_package_store_add_set(PLOVER_PACKAGE_STORE(location),set); + g_object_unref(set); + w=GTK_WIDGET(gtk_builder_get_object(ui,"LocationButton")); + name=g_filename_display_basename(path); + gtk_tool_button_set_label(GTK_TOOL_BUTTON(w),name); + g_free(name); + gtk_widget_show(w); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(w),TRUE); + } + else + { + gtk_widget_destroy(dialog); + dialog=gtk_message_dialog_new(GTK_WINDOW(w), + GTK_DIALOG_DESTROY_WITH_PARENT,GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE,"Error loading repository '%s'",path); + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), + "%s",err->message); + gtk_dialog_run(GTK_DIALOG(dialog)); + g_error_free(err); + } + g_free(path); + } + gtk_widget_destroy(dialog); +} + +G_MODULE_EXPORT void on_scan_local_media(GtkWidget *widget) +{ + if (!local_media) + local_media=plover_local_media_store_new(); + plover_local_media_store_scan(PLOVER_LOCAL_MEDIA_STORE(local_media)); +} + +G_MODULE_EXPORT void on_help_about(GtkWidget *widget) +{ + GtkWidget *w=GTK_WIDGET(gtk_builder_get_object(ui,"MainWindow")); + gtk_show_about_dialog(GTK_WINDOW(w),"name",PACKAGE_NAME, + "version",PACKAGE_VERSION,"comments","Application Manager", + "copyright","Copyright © 2010 J. Ali Harlow","logo-icon-name",LOGO_NAME, + NULL); +} + +G_MODULE_EXPORT void on_find_clicked(GtkButton *button) +{ + gchar *text; + GtkWidget *w=GTK_WIDGET(gtk_builder_get_object(ui,"SearchEntry")); + text=g_strdup(gtk_entry_get_text(GTK_ENTRY(w))); + gtk_entry_set_text(GTK_ENTRY(w),""); + gtk_entry_set_text(GTK_ENTRY(w),text); + g_free(text); +} diff --git a/app-manager/app-manager.desktop b/app-manager/app-manager.desktop new file mode 100644 index 0000000..1635ab9 --- /dev/null +++ b/app-manager/app-manager.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Application Manager +Comment=Manage applications +Exec=app-manager +Icon=plover-applications +Terminal=false +Type=Application +Categories=GTK diff --git a/app-manager/app-manager.h b/app-manager/app-manager.h new file mode 100644 index 0000000..dca76f9 --- /dev/null +++ b/app-manager/app-manager.h @@ -0,0 +1,7 @@ +#include +#include + +extern GtkBuilder *ui; +GtkTreeModel *plover_applications_model_new(GtkTreeModel *installed); +void set_package_model(GtkTreeModel *model); +PloverPackage *get_active_package(void); diff --git a/app-manager/app-manager.ui b/app-manager/app-manager.ui new file mode 100644 index 0000000..c6b7f6b --- /dev/null +++ b/app-manager/app-manager.ui @@ -0,0 +1,609 @@ + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Application Manager + 600 + 400 + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + vertical + 6 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Package + True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + Open _Location... + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Open a package repository at a known location + True + image1 + False + + + + + + + _Scan local media + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Scan local media for package repositories + True + image2 + False + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + gtk-quit + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Quit the application manager + True + True + + + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _View + True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Show a list of files owned by the selected package + _File list + True + True + + + + + + True + Show the description etc., of the selected package + Package _details + True + True + True + menuitem2 + + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Help + True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + gtk-about + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Display details about the application manager + True + True + + + + + + + + + + False + 0 + + + + + True + True + vertical + 200 + True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 6 + 6 + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + vertical + 6 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 6 + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + True + 10 + False + + + 0 + + + + + gtk-find + True + True + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + + False + False + 1 + + + + + False + False + 0 + + + + + True + + + True + vertical + + + False + 0 + + + + + True + vertical + 2 + True + + + True + Show installed applications + _Applications + True + plover-applications + True + + + + False + True + + + + + True + Show all installed packages + A_ll Packages + True + gtk-index + toolbutton1 + + + + False + True + + + + + True + + + False + True + + + + + True + Show packages in repositories on local media + Local _Media + True + gtk-cdrom + toolbutton1 + + + + False + True + + + + + Location + True + gtk-directory + toolbutton1 + + + + False + True + + + + + Show updates available for installed packages + _Updates + True + gtk-execute + toolbutton1 + + + False + True + + + + + 1 + + + + + True + vertical + + + False + 2 + + + + + 1 + + + + + False + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + automatic + automatic + in + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + True + True + + + + + + + True + True + + + + + True + 6 + 6 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 6 + + + True + True + automatic + automatic + in + + + True + True + + + + + 0 + + + + + True + True + automatic + automatic + in + + + True + True + 6 + 6 + False + word + 6 + 6 + description + False + + + + + 1 + + + + + True + vertical + + + True + 0 + 0 + + + True + + + True + gtk-home + + + False + 0 + + + + + www.gnome.org + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + none + http://www.city-occupational.co.uk/ + + + False + 1 + + + + + + + False + 0 + + + + + True + True + never + automatic + + + True + queue + + + True + 0 + 0 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 6 + 2 + 2 + 6 + 6 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Architecture: + True + + + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + i386 + True + True + + + 1 + 2 + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + License: + True + + + 1 + 2 + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + LGPL + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + + + + + + + + 1 + + + + + False + end + 2 + + + + + + + False + True + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + False + 2 + + + + + + + + True + gtk-open + + + True + gtk-cdrom + + diff --git a/app-manager/applications.c b/app-manager/applications.c new file mode 100644 index 0000000..6b72505 --- /dev/null +++ b/app-manager/applications.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010 J. Ali Harlow + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include "app-manager.h" + +static gboolean plover_applications_visible_func(GtkTreeModel *model, + GtkTreeIter *iter,gpointer data) +{ + /* Visible if row is non-empty and package contains a .desktop file + * in /usr/share/applications + */ + PloverPackage *package; + GtkTreeModel *file_store; + GtkTreeIter fi; + gchar *name,*dir; + gboolean visible=FALSE; + gtk_tree_model_get(model,iter,PLOVER_PACKAGE_STORE_OBJ_COLUMN,&package,-1); + if (package) + { + file_store=GTK_TREE_MODEL(plover_package_get_file_store(package)); + if (gtk_tree_model_get_iter_first(file_store,&fi)) + { + do + { + gtk_tree_model_get(file_store,&fi, + PLOVER_PACKAGE_FILE_STORE_NAME_COLUMN,&name,-1); + dir=g_path_get_dirname(name); + if (!strcmp(dir,"/usr/share/applications") && + g_str_has_suffix(name,".desktop")) + visible=TRUE; + g_free(dir); + g_free(name); + } while(!visible && gtk_tree_model_iter_next(file_store,&fi)); + } + } + g_object_unref(package); + return visible; +} + +GtkTreeModel *plover_applications_model_new(GtkTreeModel *installed) +{ + GtkTreeModel *model; + model=gtk_tree_model_filter_new(installed,NULL); + gtk_tree_model_filter_set_visible_func(model, + plover_applications_visible_func,NULL,NULL); + return model; +} diff --git a/app-manager/localmedia.c b/app-manager/localmedia.c new file mode 100644 index 0000000..9f6a2d8 --- /dev/null +++ b/app-manager/localmedia.c @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2010 J. Ali Harlow + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include "localmedia.h" + +G_DEFINE_TYPE(PloverLocalMediaStore,plover_local_media_store, + PLOVER_TYPE_PACKAGE_STORE); + +static void plover_local_media_store_dispose(GObject *obj) +{ + PloverLocalMediaStore *store=PLOVER_LOCAL_MEDIA_STORE(obj); + if (store->monitor) + { + g_object_unref(store->monitor); + store->monitor=NULL; + } + if (G_OBJECT_CLASS(plover_local_media_store_parent_class)->dispose) + G_OBJECT_CLASS(plover_local_media_store_parent_class)->dispose(obj); +} + +static void + plover_local_media_store_class_init(PloverLocalMediaStoreClass *klass) +{ + GObjectClass *oclass=G_OBJECT_CLASS(klass); + oclass->dispose=plover_local_media_store_dispose; +} + +GtkTreeModel *plover_local_media_store_new(void) +{ + return g_object_new(PLOVER_TYPE_LOCAL_MEDIA_STORE,NULL); +} + +static void local_media_scan_mount(PloverLocalMediaStore *store,GMount *mount) +{ + GFile *root; + gchar *path; + PloverPackageSet *set; + root=g_mount_get_root(mount); + path=g_file_get_path(root); + if (path) + { + set=plover_package_set_new_from_repository(path,NULL); + if (set) + { + g_object_set_data(G_OBJECT(mount),"plover-local-media-set",set); + plover_package_store_add_set(PLOVER_PACKAGE_STORE(store),set); + g_object_ref(mount); + } + g_free(path); + } + g_object_unref(root); +} + +static void local_media_mounted(GObject *source,GAsyncResult *res,gpointer data) +{ + GVolume *volume=G_VOLUME(source); + GMount *mount; + PloverLocalMediaStore *store=PLOVER_LOCAL_MEDIA_STORE(data); + if (g_volume_mount_finish(volume,res,NULL)) + { + mount=g_volume_get_mount(volume); + if (mount) + { + local_media_scan_mount(store,mount); + g_object_unref(mount); + } + } + g_object_unref(volume); +} + +static void local_media_scan_drive(PloverLocalMediaStore *store,GDrive *drive) +{ + GVolume *volume; + GMount *mount; + GList *volumes,*link; + if (g_drive_has_media(drive)) + { + volumes=g_drive_get_volumes(drive); + for(link=volumes;link;link=link->next) + { + volume=G_VOLUME(link->data); + mount=g_volume_get_mount(volume); + if (mount) + { + local_media_scan_mount(store,mount); + g_object_unref(mount); + } + else if (!store->implicit_scan && g_volume_can_mount(volume)) + g_volume_mount(volume,G_MOUNT_MOUNT_NONE,NULL,NULL, + local_media_mounted,store); + g_object_unref(volume); + } + g_list_free(volumes); + } +} + +static void local_media_polled(GObject *source,GAsyncResult *res,gpointer data) +{ + GDrive *drive=G_DRIVE(source); + PloverLocalMediaStore *store=PLOVER_LOCAL_MEDIA_STORE(data); + if (g_drive_poll_for_media_finish(drive,res,NULL)) + local_media_scan_drive(store,drive); + g_object_unref(drive); +} + +void plover_local_media_store_scan(PloverLocalMediaStore *store) +{ + GList *drives,*link; + GDrive *drive; + g_return_if_fail(PLOVER_IS_LOCAL_MEDIA_STORE(store)); + drives=g_volume_monitor_get_connected_drives(store->monitor); + for(link=drives;link;link=link->next) + { + drive=G_DRIVE(link->data); + if (g_drive_is_media_removable(drive)) + { + if (!g_drive_is_media_check_automatic(drive) && + g_drive_can_poll_for_media(drive) || + !g_drive_has_media(drive) && !store->implicit_scan) + { + g_object_ref(drive); + g_drive_poll_for_media(drive,NULL,local_media_polled,store); + } + else + local_media_scan_drive(store,drive); + } + g_object_unref(drive); + } + g_list_free(drives); +} + +static void local_media_mount_added(GVolumeMonitor *volume_monitor, + GMount *mount,PloverLocalMediaStore *store) +{ + local_media_scan_mount(store,mount); +} + +static void local_media_mount_removed(GVolumeMonitor *volume_monitor, + GMount *mount,PloverLocalMediaStore *store) +{ + PloverPackageSet *set= + g_object_get_data(G_OBJECT(mount),"plover-local-media-set"); + if (set) + { + plover_package_store_remove_set(PLOVER_PACKAGE_STORE(store),set); + g_object_set_data(G_OBJECT(mount),"plover-local-media-set",NULL); + g_object_unref(set); + g_object_unref(mount); + } +} + +static void local_media_mount_changed(GVolumeMonitor *volume_monitor, + GMount *mount,PloverLocalMediaStore *store) +{ + local_media_mount_removed(volume_monitor,mount,store); + local_media_mount_added(volume_monitor,mount,store); +} + +static void plover_local_media_store_init(PloverLocalMediaStore *store) +{ + store->monitor=g_volume_monitor_get(); + store->implicit_scan=TRUE; + plover_local_media_store_scan(store); + store->implicit_scan=FALSE; + g_signal_connect(store->monitor,"mount-added", + G_CALLBACK(local_media_mount_added),store); + g_signal_connect(store->monitor,"mount-changed", + G_CALLBACK(local_media_mount_changed),store); + g_signal_connect(store->monitor,"mount-removed", + G_CALLBACK(local_media_mount_removed),store); +} diff --git a/app-manager/localmedia.h b/app-manager/localmedia.h new file mode 100644 index 0000000..7fc4484 --- /dev/null +++ b/app-manager/localmedia.h @@ -0,0 +1,41 @@ +#include +#include + +G_BEGIN_DECLS + +#define PLOVER_TYPE_LOCAL_MEDIA_STORE\ + plover_local_media_store_get_type() +#define PLOVER_LOCAL_MEDIA_STORE(obj)\ + G_TYPE_CHECK_INSTANCE_CAST(obj,\ + PLOVER_TYPE_LOCAL_MEDIA_STORE,\ + PloverLocalMediaStore) +#define PLOVER_LOCAL_MEDIA_STORE_CLASS(klass)\ + G_TYPE_CHECK_CLASS_CAST(klass,\ + PLOVER_TYPE_LOCAL_MEDIA_STORE,\ + PloverLocalMediaStoreClass) +#define PLOVER_IS_LOCAL_MEDIA_STORE(obj)\ + G_TYPE_CHECK_INSTANCE_TYPE(obj,\ + PLOVER_TYPE_LOCAL_MEDIA_STORE) +#define PLOVER_IS_LOCAL_MEDIA_STORE_CLASS(klass)\ + G_TYPE_CHECK_CLASS_TYPE(obj,\ + PLOVER_TYPE_LOCAL_MEDIA_STORE) +#define PLOVER_LOCAL_MEDIA_STORE_GET_CLASS(obj)\ + G_TYPE_INSTANCE_GET_CLASS(obj,\ + PLOVER_TYPE_LOCAL_MEDIA_STORE,\ + PloverLocalMediaStoreClass) + +typedef struct _PloverLocalMediaStore { + PloverPackageStore parent_instance; + GVolumeMonitor *monitor; + gboolean implicit_scan; +} PloverLocalMediaStore; + +typedef struct _PloverLocalMediaStoreClass { + PloverPackageStoreClass parent_class; +} PloverLocalMediaStoreClass; + +GType plover_local_media_store_get_type(void) G_GNUC_CONST; +GtkTreeModel *plover_local_media_store_new(void); +void plover_local_media_scan(PloverLocalMediaStore *store); + +G_END_DECLS diff --git a/app-manager/packagelist.c b/app-manager/packagelist.c new file mode 100644 index 0000000..6425f95 --- /dev/null +++ b/app-manager/packagelist.c @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2010 J. Ali Harlow + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include "app-manager.h" + +GtkTreeView *view=NULL; +PloverPackage *active=NULL; +gboolean view_files=FALSE; + +void package_present(PloverPackage *package) +{ + gchar *s; + const char *text,*t; + GtkWidget *w; + GtkTextBuffer *buf; + buf=GTK_TEXT_BUFFER(gtk_builder_get_object(ui,"description")); + if (package) + { + s=g_strdup(plover_package_get_description(package)); + g_strdelimit(s,"\t\n",' '); + } + else + s=g_strdup(""); + gtk_text_buffer_set_text(buf,s,-1); + g_free(s); + w=GTK_WIDGET(gtk_builder_get_object(ui,"PackageDetails")); + if (!package) + { + gtk_widget_hide(w); + w=GTK_WIDGET(gtk_builder_get_object(ui,"FilesScrolledWindow")); + gtk_widget_hide(w); + w=GTK_WIDGET(gtk_builder_get_object(ui,"DescriptionScrolledWindow")); + gtk_widget_show(w); + } + else + { + if (view_files) + gtk_widget_hide(w); + else + { + gtk_widget_show(w); + w=GTK_WIDGET(gtk_builder_get_object(ui,"HomepageBox")); + text=plover_package_get_URL(package); + if (!*text) + gtk_widget_hide(w); + else + { + gtk_widget_show(w); + w=GTK_WIDGET(gtk_builder_get_object(ui,"Homepage")); + gtk_link_button_set_uri(GTK_LINK_BUTTON(w),text); + t=strstr(text,"://"); + if (t) + t+=3; + if (t) + s=strndup(t,strcspn(t,"/")); + else + s=strdup(text); + gtk_button_set_label(GTK_BUTTON(w),s); + g_free(s); + } + w=GTK_WIDGET(gtk_builder_get_object(ui,"Architecture")); + gtk_label_set_text(GTK_LABEL(w),plover_package_get_arch(package)); + w=GTK_WIDGET(gtk_builder_get_object(ui,"License")); + gtk_label_set_text(GTK_LABEL(w), + plover_package_get_license(package)); + } + w=GTK_WIDGET(gtk_builder_get_object(ui,"FilesScrolledWindow")); + if (view_files) + gtk_widget_show(w); + else + gtk_widget_hide(w); + w=GTK_WIDGET(gtk_builder_get_object(ui,"DescriptionScrolledWindow")); + if (view_files) + { + gtk_widget_hide(w); + w=GTK_WIDGET(gtk_builder_get_object(ui,"Files")); + gtk_tree_view_set_model(GTK_TREE_VIEW(w), + GTK_TREE_MODEL(plover_package_get_file_store(package))); + } + else + { + gtk_widget_show(w); + /* Without this, Gtk+ 2.18.6 just truncates long license tags */ + w=GTK_WIDGET(gtk_builder_get_object(ui,"DetailsScrolledWindow")); + gtk_widget_queue_resize(w); + } + } +} + +void package_filelist_present(PloverPackage *package) +{ +} + +static void package_selection_changed(GtkTreeSelection *selection) +{ + GtkTreeIter iter; + GtkTreeView *view; + GtkTreeModel *model; + if (active) + g_object_unref(active); + if (gtk_tree_selection_get_selected(selection,NULL,&iter)) + { + view=gtk_tree_selection_get_tree_view(selection); + model=gtk_tree_view_get_model(view); + gtk_tree_model_get(model,&iter,PLOVER_PACKAGE_STORE_OBJ_COLUMN,&active, + -1); + } + else + active=NULL; + package_present(active); +} + +static void package_activated(GtkTreeView *view,GtkTreePath *path, + GtkTreeViewColumn *column,gpointer data) +{ + GtkTreeIter iter; + GtkTreeModel *model=gtk_tree_view_get_model(view); + PloverPackage *package; + if (gtk_tree_model_get_iter(model,&iter,path)) + { + gtk_tree_model_get(model,&iter,PLOVER_PACKAGE_STORE_OBJ_COLUMN,&package, + -1); + package_filelist_present(package); + } +} + +static void package_cell_data_func(GtkTreeViewColumn *column, + GtkCellRenderer *cell,GtkTreeModel *model,GtkTreeIter *iter,gpointer data) +{ + gchar *markup; + gchar *summary,*name,*version; + gtk_tree_model_get(model,iter,PLOVER_PACKAGE_STORE_SUMMARY_COLUMN,&summary, + PLOVER_PACKAGE_STORE_NAME_COLUMN,&name, + PLOVER_PACKAGE_STORE_VERSION_COLUMN,&version,-1); + markup=g_strdup_printf("%s\n%s %s",summary,name,version,NULL); + g_free(summary); + g_free(name); + g_free(version); + g_object_set(cell,"markup",markup,NULL); + g_free(markup); +} + +void set_package_model(GtkTreeModel *model) +{ + GtkWidget *w; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + GtkTreeSelection *selection; + if (!view) + { + w=GTK_WIDGET(gtk_builder_get_object(ui,"Packages")); + if (w) + { + view=GTK_TREE_VIEW(w); +#if 0 + column=gtk_tree_view_column_new_with_attributes("Icon", + gtk_cell_renderer_pixbuf_new(),"pixbuf", + PLOVER_PACKAGE_FILE_STORE_ICON_COLUMN,NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(w),column); +#endif + column=gtk_tree_view_column_new(); + gtk_tree_view_column_set_title(column,"Summary"); + renderer=gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(column,renderer,FALSE); + gtk_tree_view_column_set_cell_data_func(column,renderer, + package_cell_data_func,NULL,NULL); + gtk_tree_view_append_column(view,column); + gtk_widget_show_all(w); + gtk_tree_view_set_headers_visible(view,FALSE); + w=GTK_WIDGET(gtk_builder_get_object(ui,"SearchEntry")); + gtk_tree_view_set_search_entry(view,GTK_ENTRY(w)); + selection=gtk_tree_view_get_selection(view); + g_signal_connect(selection,"changed", + G_CALLBACK(package_selection_changed),NULL); + g_signal_connect(view,"row-activated",G_CALLBACK(package_activated), + NULL); + } + else + g_warning("Packages: no such widget in UI"); + w=GTK_WIDGET(gtk_builder_get_object(ui,"Files")); + if (w) + { + column=gtk_tree_view_column_new_with_attributes("Name", + gtk_cell_renderer_text_new(),"text", + PLOVER_PACKAGE_FILE_STORE_NAME_COLUMN,NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(w),column); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(w),FALSE); + gtk_widget_show_all(w); + } + else + g_warning("Files: no such widget in UI"); + } + if (view) + { + gtk_tree_view_set_model(view,model); + gtk_tree_view_set_search_column(view, + PLOVER_PACKAGE_STORE_NAME_COLUMN); + } + package_present(NULL); +} + +PloverPackage *get_active_package(void) +{ + return active; +} + +G_MODULE_EXPORT void + on_view_files_toggled(GtkCheckMenuItem *menuitem,gpointer data) +{ + view_files=gtk_check_menu_item_get_active(menuitem); + package_present(active); +} + +G_MODULE_EXPORT void + on_view_details_toggled(GtkCheckMenuItem *menuitem,gpointer data) +{ +} diff --git a/app-manager/plover-applications.svg b/app-manager/plover-applications.svg new file mode 100644 index 0000000..07cfc18 --- /dev/null +++ b/app-manager/plover-applications.svg @@ -0,0 +1,1108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Misc Stuff + + + Lapo Calamandrei + + + + + + stuff + box + misc + various + mess + + + + + + Jakub Steiner + + + 2007-01-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app-manager/resources.rc.in b/app-manager/resources.rc.in new file mode 100644 index 0000000..470304c --- /dev/null +++ b/app-manager/resources.rc.in @@ -0,0 +1,32 @@ +#include + +MAINICON ICON "app-manager.ico" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@, + @PLOVER_MICRO_VERSION@,0 + PRODUCTVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@, + @PLOVER_MICRO_VERSION@,0 + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + { + BLOCK "StringFileInfo" + { + BLOCK "080904B0" + { + VALUE "CompanyName","The plover development team" + VALUE "FileDescription","Application Manager" + VALUE "FileVersion","@PACKAGE_VERSION@" + VALUE "InternalName","app-manager" + VALUE "LegalCopyright", + "Copyright © 2010 J. Ali Harlow et al" + VALUE "OriginalFilename","app-manager.exe" + VALUE "ProductName","plover" + VALUE "ProductVersion","@PACKAGE_VERSION@" + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation",0x809,0x4B0 + } + } diff --git a/configure.ac b/configure.ac index a336c3e..854481e 100644 --- a/configure.ac +++ b/configure.ac @@ -9,10 +9,14 @@ AC_CONFIG_HEADER([config.h]) AC_CONFIG_FILES([Makefile plover/Makefile plover/plover.pc +plover-gtk/Makefile +plover-gtk/plover-gtk.pc setup/Makefile setup/resources.rc update/Makefile update/resources.rc +app-manager/Makefile +app-manager/resources.rc ]) AM_INIT_AUTOMAKE(no-define) case $VERSION in @@ -43,12 +47,19 @@ esac # increment CURRENT and set AGE and REVISION to 0. # - If the interface is the same as the previous version, increment REVISION. # -LT_CURRENT=0 -LT_REVISION=1 -LT_AGE=0 -AC_SUBST(LT_CURRENT) -AC_SUBST(LT_REVISION) -AC_SUBST(LT_AGE) +lt_current=0 +lt_revision=1 +lt_age=0 +LIBPLOVER_LT_VERSION_INFO="$lt_current:$lt_revision:$lt_age" +AC_SUBST(LIBPLOVER_LT_VERSION_INFO) + +# and likewise for plover-gtk. +# +lt_current=0 +lt_revision=0 +lt_age=0 +PLOVER_GTK_LT_VERSION_INFO="$lt_current:$lt_revision:$lt_age" +AC_SUBST(PLOVER_GTK_LT_VERSION_INFO) ################################################## # Checks for programs. @@ -75,10 +86,21 @@ AC_HEADER_STDC PKG_CHECK_MODULES(RAZOR,[razor >= 0.2],[:],[RAZOR_LIBS=-lrazor]) PKG_CHECK_MODULES(EXPAT,[expat],[:],[EXPAT_LIBS=-lexpat]) PKG_CHECK_MODULES(ZLIB,[zlib],[:],[ZLIB_LIBS=-lz]) +PKG_CHECK_MODULES(GIO,[gio-2.0]) +PKG_CHECK_MODULES(GTK,[gtk+-2.0]) +PKG_CHECK_MODULES(GMODULE_EXPORT,[gmodule-export-2.0]) LIBPLOVER_CFLAGS="$RAZOR_CFLAGS $EXPAT_CFLAGS $ZLIB_CFLAGS" LIBPLOVER_LIBS="$RAZOR_LIBS $EXPAT_LIBS $ZLIB_LIBS" AC_SUBST(LIBPLOVER_CFLAGS) AC_SUBST(LIBPLOVER_LIBS) +PLOVER_GTK_CFLAGS="$GTK_CFLAGS $RAZOR_CFLAGS" +PLOVER_GTK_LIBS="$GTK_LIBS $RAZOR_LIBS" +AC_SUBST(PLOVER_GTK_CFLAGS) +AC_SUBST(PLOVER_GTK_LIBS) +GUI_CFLAGS="$GMODULE_EXPORT_CFLAGS $GIO_CFLAGS $PLOVER_GTK_CFLAGS $LIBPLOVER_CFLAGS" +GUI_LIBS="$GMODULE_EXPORT_LIBS $GIO_LIBS $PLOVER_GTK_LIBS $LIBPLOVER_LIBS" +AC_SUBST(GUI_CFLAGS) +AC_SUBST(GUI_LIBS) save_PKG_CONFIG="$PKG_CONFIG" PKG_CONFIG="$PKG_CONFIG --static" PKG_CHECK_MODULES(SETUP,[whelk]) diff --git a/plover-gtk/Makefile.am b/plover-gtk/Makefile.am new file mode 100644 index 0000000..4d41f41 --- /dev/null +++ b/plover-gtk/Makefile.am @@ -0,0 +1,15 @@ +AM_CFLAGS=-g $(PLOVER_GTK_CFLAGS) +LIBS=$(PLOVER_GTK_LIBS) +INCLUDES=-I$(top_srcdir) +LDFLAGS=-no-undefined -version-info $(PLOVER_GTK_LT_VERSION_INFO) + +pkginclude_HEADERS=error.h package.h packageset.h packagestore.h \ + packagefilestore.h + +lib_LTLIBRARIES=libplover-gtk.la +libplover_gtk_la_SOURCES=$(pkginclude_HEADERS) \ + error.c package.c packageset.c packagestore.c \ + packagefilestore.c + +pkgconfigdir=$(libdir)/pkgconfig +pkgconfig_DATA=plover-gtk.pc diff --git a/plover-gtk/error.c b/plover-gtk/error.c new file mode 100644 index 0000000..237d39a --- /dev/null +++ b/plover-gtk/error.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2010 J. Ali Harlow + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include +#include + +GQuark plover_razor_error_quark(void) +{ + static GQuark quark=0; + if (!quark) + quark=g_quark_from_static_string("plover-razor-error-quark"); + return quark; +} + diff --git a/plover-gtk/error.h b/plover-gtk/error.h new file mode 100644 index 0000000..9e7800f --- /dev/null +++ b/plover-gtk/error.h @@ -0,0 +1,11 @@ +#ifndef __PLOVER_ERROR_H__ +#define __PLOVER_ERROR_H__ + +#define PLOVER_RAZOR_ERROR plover_razor_error_quark() + +typedef enum { + PLOVER_RAZOR_ERROR_FAILED +} PloverRazorError; + +#endif /* __PLOVER_ERROR_H__ */ + diff --git a/plover-gtk/package.c b/plover-gtk/package.c new file mode 100644 index 0000000..e3ea09e --- /dev/null +++ b/plover-gtk/package.c @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2010 J. Ali Harlow + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include +#include +#include +#include +#include "plover-gtk/package.h" + +G_DEFINE_TYPE(PloverPackage,plover_package,G_TYPE_OBJECT); + +typedef struct _PloverPackagePrivate { + struct razor_set *set; + struct razor_package *pkg; + PloverPackageFileStore *file_store; +} PloverPackagePrivate; + +#define PLOVER_PACKAGE_GET_PRIVATE(obj)\ + G_TYPE_INSTANCE_GET_PRIVATE(obj,\ + PLOVER_TYPE_PACKAGE,PloverPackagePrivate) + +enum { + CHANGED=0, + N_SIGNALS +}; + +static guint signals[N_SIGNALS]; + +static void plover_package_dispose(GObject *obj) +{ + PloverPackagePrivate *priv=PLOVER_PACKAGE_GET_PRIVATE(obj); + if (priv->file_store) + { + g_object_unref(priv->file_store); + priv->file_store=NULL; + } + if (G_OBJECT_CLASS(plover_package_parent_class)->dispose) + G_OBJECT_CLASS(plover_package_parent_class)->dispose(obj); +} + +static void plover_package_class_init(PloverPackageClass *klass) +{ + GObjectClass *oclass=G_OBJECT_CLASS(klass); + oclass->dispose=plover_package_dispose; + g_type_class_add_private(klass,sizeof(PloverPackagePrivate)); + signals[CHANGED]=g_signal_newv("changed", + G_TYPE_FROM_CLASS(klass),G_SIGNAL_RUN_LAST,NULL,NULL,NULL, + g_cclosure_marshal_VOID__VOID,G_TYPE_NONE,0,NULL); +} + +static void plover_package_init(PloverPackage *package) +{ +} + +PloverPackage *plover_package_new(struct razor_set *set, + struct razor_package *pkg) +{ + PloverPackage *package; + PloverPackagePrivate *priv; + package=g_object_new(PLOVER_TYPE_PACKAGE,NULL); + priv=PLOVER_PACKAGE_GET_PRIVATE(package); + priv->set=set; + priv->pkg=pkg; + return package; +} + +const char *plover_package_get_name(PloverPackage *package) +{ + PloverPackagePrivate *priv; + const char *name; + g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL); + priv=PLOVER_PACKAGE_GET_PRIVATE(package); + razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_NAME,&name, + RAZOR_DETAIL_LAST); + return name; +} + +const char *plover_package_get_summary(PloverPackage *package) +{ + PloverPackagePrivate *priv; + const char *summary; + g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL); + priv=PLOVER_PACKAGE_GET_PRIVATE(package); + razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_SUMMARY,&summary, + RAZOR_DETAIL_LAST); + return summary; +} + +const char *plover_package_get_version(PloverPackage *package) +{ + PloverPackagePrivate *priv; + const char *version; + g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL); + priv=PLOVER_PACKAGE_GET_PRIVATE(package); + razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_VERSION,&version, + RAZOR_DETAIL_LAST); + return version; +} + +const char *plover_package_get_license(PloverPackage *package) +{ + PloverPackagePrivate *priv; + const char *license; + g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL); + priv=PLOVER_PACKAGE_GET_PRIVATE(package); + razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_LICENSE,&license, + RAZOR_DETAIL_LAST); + return license; +} + +const char *plover_package_get_arch(PloverPackage *package) +{ + PloverPackagePrivate *priv; + const char *arch; + g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL); + priv=PLOVER_PACKAGE_GET_PRIVATE(package); + razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_ARCH,&arch, + RAZOR_DETAIL_LAST); + return arch; +} + +const char *plover_package_get_description(PloverPackage *package) +{ + PloverPackagePrivate *priv; + const char *description; + g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL); + priv=PLOVER_PACKAGE_GET_PRIVATE(package); + razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_DESCRIPTION, + &description,RAZOR_DETAIL_LAST); + return description; +} + +const char *plover_package_get_URL(PloverPackage *package) +{ + PloverPackagePrivate *priv; + const char *URL; + g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL); + priv=PLOVER_PACKAGE_GET_PRIVATE(package); + razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_URL,&URL, + RAZOR_DETAIL_LAST); + return URL; +} + +GdkPixbuf *plover_package_get_icon(PloverPackage *package) +{ + g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL); + return NULL; +} + +PloverPackageFileStore *plover_package_get_file_store(PloverPackage *package) +{ + PloverPackagePrivate *priv; + struct razor_file_iterator *iter; + g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL); + priv=PLOVER_PACKAGE_GET_PRIVATE(package); + if (!priv->file_store) + { + iter=razor_file_iterator_create(priv->set,priv->pkg,0); + priv->file_store=plover_package_file_store_new(iter); + razor_file_iterator_destroy(iter); + } + return priv->file_store; +} diff --git a/plover-gtk/package.h b/plover-gtk/package.h new file mode 100644 index 0000000..23bbff5 --- /dev/null +++ b/plover-gtk/package.h @@ -0,0 +1,50 @@ +#ifndef __PLOVER_PACKAGE_H__ +#define __PLOVER_PACKAGE_H__ + +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define PLOVER_TYPE_PACKAGE plover_package_get_type() +#define PLOVER_PACKAGE(obj) G_TYPE_CHECK_INSTANCE_CAST(obj,\ + PLOVER_TYPE_PACKAGE,PloverPackage) +#define PLOVER_PACKAGE_CLASS(klass)\ + G_TYPE_CHECK_CLASS_CAST(klass,\ + PLOVER_TYPE_PACKAGE,PloverPackageClass) +#define PLOVER_IS_PACKAGE(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj,\ + PLOVER_TYPE_PACKAGE) +#define PLOVER_IS_PACKAGE_CLASS(klass)\ + G_TYPE_CHECK_CLASS_TYPE(obj,\ + PLOVER_TYPE_PACKAGE) +#define PLOVER_PACKAGE_GET_CLASS(obj)\ + G_TYPE_INSTANCE_GET_CLASS(obj,\ + PLOVER_TYPE_PACKAGE,PloverPackageClass) + +typedef struct _PloverPackage { + GObject parent_instance; +} PloverPackage; + +typedef struct _PloverPackageClass { + GObjectClass parent_class; +} PloverPackageClass; + +GType plover_package_get_type(void) G_GNUC_CONST; +PloverPackage *plover_package_new(struct razor_set *set, + struct razor_package *pkg); +const char *plover_package_get_name(PloverPackage *package); +const char *plover_package_get_summary(PloverPackage *package); +const char *plover_package_get_version(PloverPackage *package); +const char *plover_package_get_license(PloverPackage *package); +const char *plover_package_get_arch(PloverPackage *package); +const char *plover_package_get_description(PloverPackage *package); +const char *plover_package_get_URL(PloverPackage *package); +GdkPixbuf *plover_package_get_icon(PloverPackage *package); +PloverPackageFileStore *plover_package_get_file_store(PloverPackage *package); + +G_END_DECLS + +#endif /* __PLOVER_PACKAGE_H__ */ diff --git a/plover-gtk/packagefilestore.c b/plover-gtk/packagefilestore.c new file mode 100644 index 0000000..d119555 --- /dev/null +++ b/plover-gtk/packagefilestore.c @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford + * Copyright (C) 2010 J. Ali Harlow + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include +#include +#include +#include +#include "plover-gtk/packagefilestore.h" + +#define VALID_ITER(iter,store) ((iter) && (iter)->user_data && \ + PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(store)->stamp==(iter)->stamp && \ + !g_sequence_iter_is_end((iter)->user_data) && \ + g_sequence_iter_get_sequence((iter)->user_data)== \ + PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(store)->seq) + +static GType column_types[PLOVER_PACKAGE_FILE_STORE_NO_COLUMNS]; + +static void plover_package_file_store_tree_model_init(GtkTreeModelIface *iface); + +G_DEFINE_TYPE_WITH_CODE(PloverPackageFileStore,plover_package_file_store, + G_TYPE_OBJECT,G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_MODEL, + plover_package_file_store_tree_model_init)); + +typedef struct _PloverPackageFileStorePrivate { + GSequence *seq; + int stamp; +} PloverPackageFileStorePrivate; + +#define PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(obj)\ + G_TYPE_INSTANCE_GET_PRIVATE(obj,\ + PLOVER_TYPE_PACKAGE_FILE_STORE,\ + PloverPackageFileStorePrivate) + +static void plover_package_file_store_finalize(GObject *obj) +{ + PloverPackageFileStorePrivate *priv= + PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(obj); + g_sequence_free(priv->seq); + if (G_OBJECT_CLASS(plover_package_file_store_parent_class)->finalize) + G_OBJECT_CLASS(plover_package_file_store_parent_class)->finalize(obj); +} + +static void + plover_package_file_store_class_init(PloverPackageFileStoreClass *klass) +{ + GObjectClass *oclass=G_OBJECT_CLASS(klass); + oclass->finalize=plover_package_file_store_finalize; + g_type_class_add_private(klass,sizeof(PloverPackageFileStorePrivate)); + column_types[PLOVER_PACKAGE_FILE_STORE_NAME_COLUMN]=G_TYPE_STRING; +} + +static GtkTreeModelFlags +plover_package_file_store_get_flags(GtkTreeModel *tree_model) +{ + return GTK_TREE_MODEL_ITERS_PERSIST|GTK_TREE_MODEL_LIST_ONLY; +} + +static gint plover_package_file_store_get_n_columns(GtkTreeModel *tree_model) +{ + return PLOVER_PACKAGE_FILE_STORE_NO_COLUMNS; +} + +static GType + plover_package_file_store_get_column_type(GtkTreeModel *tree_model,gint indx) +{ + PloverPackageFileStore *store=(PloverPackageFileStore *)tree_model; + g_return_val_if_fail(indx>=0 && indx=g_sequence_get_length(priv->seq)) + return FALSE; + iter->stamp=priv->stamp; + iter->user_data=g_sequence_get_iter_at_pos(priv->seq,i); + return TRUE; +} + +static GtkTreePath * + plover_package_file_store_get_path(GtkTreeModel *tree_model,GtkTreeIter *iter) +{ + GtkTreePath *path; + g_return_val_if_fail(VALID_ITER(iter,tree_model),NULL); + if (g_sequence_iter_is_end(iter->user_data)) + return NULL; + path=gtk_tree_path_new(); + gtk_tree_path_append_index(path, + g_sequence_iter_get_position(iter->user_data)); + return path; +} + +static void plover_package_file_store_get_value(GtkTreeModel *tree_model, + GtkTreeIter *iter,gint column,GValue *value) +{ + PloverPackageFileStore *store=(PloverPackageFileStore *)tree_model; + char *name; + g_return_if_fail(column>=0 && columnuser_data); + g_value_init(value,column_types[column]); + switch((PloverPackageFileStoreColumn)column) + { + case PLOVER_PACKAGE_FILE_STORE_NAME_COLUMN: + g_value_set_string(value,name); + break; + } +} + +static gboolean plover_package_file_store_iter_next(GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + g_return_val_if_fail(VALID_ITER(iter,tree_model),FALSE); + iter->user_data=g_sequence_iter_next(iter->user_data); + return !g_sequence_iter_is_end(iter->user_data); +} + +static gboolean + plover_package_file_store_iter_children(GtkTreeModel *tree_model, + GtkTreeIter *iter,GtkTreeIter *parent) +{ + PloverPackageFileStorePrivate *priv; + PloverPackageFileStore *store=(PloverPackageFileStore *)tree_model; + priv=PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(tree_model); + /* this is a list, nodes have no children */ + if (parent) + return FALSE; + if (g_sequence_get_length(priv->seq)>0) + { + iter->stamp=priv->stamp; + iter->user_data=g_sequence_get_begin_iter(priv->seq); + return TRUE; + } + else + return FALSE; +} + +static gboolean + plover_package_file_store_iter_has_child(GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + return FALSE; +} + +static gint plover_package_file_store_iter_n_children(GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + PloverPackageFileStorePrivate *priv; + PloverPackageFileStore *store=(PloverPackageFileStore *)tree_model; + priv=PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(tree_model); + if (!iter) + return g_sequence_get_length(priv->seq); + g_return_val_if_fail(VALID_ITER(iter,tree_model),-1); + return 0; +} + +static gboolean + plover_package_file_store_iter_nth_child(GtkTreeModel *tree_model, + GtkTreeIter *iter,GtkTreeIter *parent,gint n) +{ + PloverPackageFileStorePrivate *priv; + PloverPackageFileStore *store=(PloverPackageFileStore *)tree_model; + priv=PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(tree_model); + GSequenceIter *child; + if (parent) + return FALSE; + child=g_sequence_get_iter_at_pos(priv->seq,n); + if (g_sequence_iter_is_end(child)) + return FALSE; + iter->stamp=priv->stamp; + iter->user_data=child; + return TRUE; +} + +static gboolean plover_package_file_store_iter_parent(GtkTreeModel *tree_model, + GtkTreeIter *iter,GtkTreeIter *child) +{ + return FALSE; +} + +static void plover_package_file_store_tree_model_init(GtkTreeModelIface *iface) +{ + iface->get_flags=plover_package_file_store_get_flags; + iface->get_n_columns=plover_package_file_store_get_n_columns; + iface->get_column_type=plover_package_file_store_get_column_type; + iface->get_iter=plover_package_file_store_get_iter; + iface->get_path=plover_package_file_store_get_path; + iface->get_value=plover_package_file_store_get_value; + iface->iter_next=plover_package_file_store_iter_next; + iface->iter_children=plover_package_file_store_iter_children; + iface->iter_has_child=plover_package_file_store_iter_has_child; + iface->iter_n_children=plover_package_file_store_iter_n_children; + iface->iter_nth_child=plover_package_file_store_iter_nth_child; + iface->iter_parent=plover_package_file_store_iter_parent; +} + +static void plover_package_file_store_init(PloverPackageFileStore *store) +{ + PloverPackageFileStorePrivate *priv; + priv=PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(store); + priv->seq=g_sequence_new(g_free); + priv->stamp=g_random_int(); +} + +PloverPackageFileStore * + plover_package_file_store_new(struct razor_file_iterator *files) +{ + const char *name; + GSequenceIter *si; + GtkTreeIter ti; + GtkTreePath *path; + gint *indices; + PloverPackageFileStore *store; + PloverPackageFileStorePrivate *priv; + store=g_object_new(PLOVER_TYPE_PACKAGE_FILE_STORE,NULL); + priv=PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(store); + path=gtk_tree_path_new(); + gtk_tree_path_append_index(path,0); + indices=gtk_tree_path_get_indices(path); + while(razor_file_iterator_next(files,&name)) + { + si=g_sequence_insert_sorted(priv->seq,g_strdup(name),g_strcmp0,NULL); + *indices=g_sequence_iter_get_position(si); + ti.stamp=priv->stamp; + ti.user_data=si; + gtk_tree_model_row_inserted(GTK_TREE_MODEL(store),path,&ti); + } + gtk_tree_path_free(path); + return store; +} diff --git a/plover-gtk/packagefilestore.h b/plover-gtk/packagefilestore.h new file mode 100644 index 0000000..65c27c6 --- /dev/null +++ b/plover-gtk/packagefilestore.h @@ -0,0 +1,50 @@ +#ifndef __PLOVER_PACKAGE_FILE_STORE_H__ +#define __PLOVER_PACKAGE_FILE_STORE_H__ + +#include +#include + +G_BEGIN_DECLS + +#define PLOVER_TYPE_PACKAGE_FILE_STORE\ + plover_package_file_store_get_type() +#define PLOVER_PACKAGE_FILE_STORE(obj)\ + G_TYPE_CHECK_INSTANCE_CAST(obj,\ + PLOVER_TYPE_PACKAGE_FILE_STORE,\ + PloverPackageFileStore) +#define PLOVER_PACKAGE_FILE_STORE_CLASS(klass)\ + G_TYPE_CHECK_CLASS_CAST(klass,\ + PLOVER_TYPE_PACKAGE_FILE_STORE,\ + PloverPackageFileStoreClass) +#define PLOVER_IS_PACKAGE_FILE_STORE(obj)\ + G_TYPE_CHECK_INSTANCE_TYPE(obj,\ + PLOVER_TYPE_PACKAGE_FILE_STORE) +#define PLOVER_IS_PACKAGE_FILE_STORE_CLASS(klass)\ + G_TYPE_CHECK_CLASS_TYPE(obj,\ + PLOVER_TYPE_PACKAGE_FILE_STORE) +#define PLOVER_PACKAGE_FILE_STORE_GET_CLASS(obj)\ + G_TYPE_INSTANCE_GET_CLASS(obj,\ + PLOVER_TYPE_PACKAGE_FILE_STORE,\ + PloverPackageFileStoreClass) + +typedef enum +{ + PLOVER_PACKAGE_FILE_STORE_NAME_COLUMN, + PLOVER_PACKAGE_FILE_STORE_NO_COLUMNS +} PloverPackageFileStoreColumn; + +typedef struct _PloverPackageFileStore { + GObject parent_instance; +} PloverPackageFileStore; + +typedef struct _PloverPackageFileStoreClass { + GObjectClass parent_class; +} PloverPackageFileStoreClass; + +GType plover_package_file_store_get_type(void) G_GNUC_CONST; +PloverPackageFileStore * + plover_package_file_store_new(struct razor_file_iterator *files); + +G_END_DECLS + +#endif /* __PLOVER_PACKAGE_FILE_STORE_H__ */ diff --git a/plover-gtk/packageset.c b/plover-gtk/packageset.c new file mode 100644 index 0000000..29b65aa --- /dev/null +++ b/plover-gtk/packageset.c @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2010 J. Ali Harlow + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include "plover/plover.h" +#include "plover-gtk/error.h" +#include "plover-gtk/packageset.h" +#include "plover-gtk/package.h" + +G_DEFINE_TYPE(PloverPackageSet,plover_package_set,G_TYPE_OBJECT); + +typedef struct _PloverPackageSetPrivate { + struct razor_root *root; + struct razor_set *set; + GSList *packages; +} PloverPackageSetPrivate; + +#define PLOVER_PACKAGE_SET_GET_PRIVATE(obj)\ + G_TYPE_INSTANCE_GET_PRIVATE(obj,\ + PLOVER_TYPE_PACKAGE_SET,\ + PloverPackageSetPrivate) + +enum { + CHANGED=0, + N_SIGNALS +}; + +static guint signals[N_SIGNALS]; + +static void plover_package_set_finalize(GObject *obj) +{ + PloverPackageSetPrivate *priv=PLOVER_PACKAGE_SET_GET_PRIVATE(obj); + if (priv->root) + { + /* priv->set, if set, is owned by priv->root and should not + * be destroyed. + */ + razor_root_close(priv->root); + } + else if (priv->set) + razor_set_destroy(priv->set); + if (G_OBJECT_CLASS(plover_package_set_parent_class)->finalize) + G_OBJECT_CLASS(plover_package_set_parent_class)->finalize(obj); +} + +static void plover_package_set_dispose(GObject *obj) +{ + PloverPackageSetPrivate *priv=PLOVER_PACKAGE_SET_GET_PRIVATE(obj); + if (G_OBJECT_CLASS(plover_package_set_parent_class)->dispose) + G_OBJECT_CLASS(plover_package_set_parent_class)->dispose(obj); +} + +static void plover_package_set_class_init(PloverPackageSetClass *klass) +{ + GObjectClass *oclass=G_OBJECT_CLASS(klass); + oclass->finalize=plover_package_set_finalize; + oclass->dispose=plover_package_set_dispose; + g_type_class_add_private(klass,sizeof(PloverPackageSetPrivate)); + signals[CHANGED]=g_signal_newv("changed", + G_TYPE_FROM_CLASS(klass),G_SIGNAL_RUN_LAST,NULL,NULL,NULL, + g_cclosure_marshal_VOID__VOID,G_TYPE_NONE,0,NULL); +} + +static void plover_package_set_init(PloverPackageSet *set) +{ +} + +PloverPackageSet *plover_package_set_new(void) +{ + return g_object_new(PLOVER_TYPE_PACKAGE_SET,NULL); +} + +PloverPackageSet *plover_package_set_new_from_installed(const char *root, + GError **err) +{ + PloverPackageSet *set; + PloverPackageSetPrivate *priv; + set=plover_package_set_new(); + priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set); + priv->root=razor_root_open(root); + if (!priv->root) + { + g_set_error(err,PLOVER_RAZOR_ERROR,PLOVER_RAZOR_ERROR_FAILED, + "Failed to open %s as razor root",root); + g_object_unref(set); + return NULL; + } + priv->set=razor_root_get_system_set(priv->root); + if (!priv->set) + { + g_set_error(err,PLOVER_RAZOR_ERROR,PLOVER_RAZOR_ERROR_FAILED, + "Failed to get system set from %s",root); + g_object_unref(set); + return NULL; + } + return set; +} + +PloverPackageSet *plover_package_set_new_from_repository(const char *base, + GError **err) +{ + int fd; + gchar *s; + PloverPackageSet *set; + PloverPackageSetPrivate *priv; + set=plover_package_set_new(); + priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set); + fd=open(".",O_RDONLY); + s=g_build_filename(base,"repodata",NULL); + if (chdir(s)<0) + { + g_set_error(err,G_FILE_ERROR,g_file_error_from_errno(errno), + "%s: %s",s,g_strerror(errno)); + g_object_unref(set); + return NULL; + } + g_free(s); + priv->set=plover_razor_set_create_from_yum(".."); + fchdir(fd); + close(fd); + if (!priv->set) + { + g_set_error(err,PLOVER_RAZOR_ERROR,PLOVER_RAZOR_ERROR_FAILED, + "Failed to create package set from repository %s",base); + g_object_unref(set); + return NULL; + } + return set; +} + +GSList *plover_package_set_get_packages(PloverPackageSet *set) +{ + struct razor_package_iterator *iter; + struct razor_package *pkg; + PloverPackageSetPrivate *priv; + PloverPackage *package; + g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL); + priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set); + if (priv->set && !priv->packages) + { + iter=razor_package_iterator_create(priv->set); + while(razor_package_iterator_next(iter,&pkg,RAZOR_DETAIL_LAST)) + { + package=plover_package_new(priv->set,pkg); + priv->packages=g_slist_prepend(priv->packages,package); + } + razor_package_iterator_destroy(iter); + } + return priv->packages; +} diff --git a/plover-gtk/packageset.h b/plover-gtk/packageset.h new file mode 100644 index 0000000..e3e8ecf --- /dev/null +++ b/plover-gtk/packageset.h @@ -0,0 +1,44 @@ +#ifndef __PLOVER_PACKAGE_SET_H__ +#define __PLOVER_PACKAGE_SET_H__ + +#include + +G_BEGIN_DECLS + +#define PLOVER_TYPE_PACKAGE_SET plover_package_set_get_type() +#define PLOVER_PACKAGE_SET(obj) G_TYPE_CHECK_INSTANCE_CAST(obj,\ + PLOVER_TYPE_PACKAGE_SET,PloverPackageSet) +#define PLOVER_PACKAGE_SET_CLASS(klass)\ + G_TYPE_CHECK_CLASS_CAST(klass,\ + PLOVER_TYPE_PACKAGE_SET,\ + PloverPackageSetClass) +#define PLOVER_IS_PACKAGE_SET(obj)\ + G_TYPE_CHECK_INSTANCE_TYPE(obj,\ + PLOVER_TYPE_PACKAGE_SET) +#define PLOVER_IS_PACKAGE_SET_CLASS(klass)\ + G_TYPE_CHECK_CLASS_TYPE(obj,\ + PLOVER_TYPE_PACKAGE_SET) +#define PLOVER_PACKAGE_SET_GET_CLASS(obj)\ + G_TYPE_INSTANCE_GET_CLASS(obj,\ + PLOVER_TYPE_PACKAGE_SET,\ + PloverPackageSetClass) + +typedef struct _PloverPackageSet { + GObject parent_instance; +} PloverPackageSet; + +typedef struct _PloverPackageSetClass { + GObjectClass parent_class; +} PloverPackageSetClass; + +GType plover_package_set_get_type(void) G_GNUC_CONST; +PloverPackageSet *plover_package_set_new(void); +PloverPackageSet *plover_package_set_new_from_installed(const char *root, + GError **err); +PloverPackageSet *plover_package_set_new_from_repository(const char *base, + GError **err); +GSList *plover_package_set_get_packages(PloverPackageSet *set); + +G_END_DECLS + +#endif /* __PLOVER_PACKAGE_SET_H__ */ diff --git a/plover-gtk/packagestore.c b/plover-gtk/packagestore.c new file mode 100644 index 0000000..408964c --- /dev/null +++ b/plover-gtk/packagestore.c @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford + * Copyright (C) 2010 J. Ali Harlow + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include "plover/plover.h" +#include "plover-gtk/package.h" +#include "plover-gtk/packagestore.h" + +#define VALID_ITER(iter,store) ((iter) && (iter)->user_data && \ + PLOVER_PACKAGE_STORE_GET_PRIVATE(store)->stamp==(iter)->stamp && \ + !g_sequence_iter_is_end((iter)->user_data) && \ + g_sequence_iter_get_sequence((iter)->user_data)== \ + PLOVER_PACKAGE_STORE_GET_PRIVATE(store)->seq) + +static GType column_types[PLOVER_PACKAGE_STORE_NO_COLUMNS]; + +static void plover_package_store_tree_model_init(GtkTreeModelIface *iface); + +G_DEFINE_TYPE_WITH_CODE(PloverPackageStore,plover_package_store,G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_MODEL, + plover_package_store_tree_model_init)); + +typedef struct _PloverPackageStorePrivate { + GSList *sets; + GSequence *seq; + int stamp; +} PloverPackageStorePrivate; + +#define PLOVER_PACKAGE_STORE_GET_PRIVATE(obj)\ + G_TYPE_INSTANCE_GET_PRIVATE(obj,\ + PLOVER_TYPE_PACKAGE_STORE,\ + PloverPackageStorePrivate) + +static void plover_package_store_finalize(GObject *obj) +{ + PloverPackageStorePrivate *priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(obj); + g_sequence_free(priv->seq); + if (G_OBJECT_CLASS(plover_package_store_parent_class)->finalize) + G_OBJECT_CLASS(plover_package_store_parent_class)->finalize(obj); +} + +static void plover_package_store_dispose(GObject *obj) +{ + PloverPackageStorePrivate *priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(obj); + g_slist_foreach(priv->sets,(GFunc)g_object_unref,NULL); + g_slist_free(priv->sets); + priv->sets=NULL; + g_sequence_free(priv->seq); + priv->seq=g_sequence_new(NULL); + if (G_OBJECT_CLASS(plover_package_store_parent_class)->dispose) + G_OBJECT_CLASS(plover_package_store_parent_class)->dispose(obj); +} + +static void plover_package_store_class_init(PloverPackageStoreClass *klass) +{ + GObjectClass *oclass=G_OBJECT_CLASS(klass); + oclass->finalize=plover_package_store_finalize; + oclass->dispose=plover_package_store_dispose; + g_type_class_add_private(klass,sizeof(PloverPackageStorePrivate)); + column_types[PLOVER_PACKAGE_STORE_OBJ_COLUMN]=PLOVER_TYPE_PACKAGE; + column_types[PLOVER_PACKAGE_STORE_INSTALLED_COLUMN]=G_TYPE_BOOLEAN; + column_types[PLOVER_PACKAGE_STORE_ICON_COLUMN]=GDK_TYPE_PIXBUF; + column_types[PLOVER_PACKAGE_STORE_NAME_COLUMN]=G_TYPE_STRING; + column_types[PLOVER_PACKAGE_STORE_VERSION_COLUMN]=G_TYPE_STRING; + column_types[PLOVER_PACKAGE_STORE_SUMMARY_COLUMN]=G_TYPE_STRING; +} + +static GtkTreeModelFlags +plover_package_store_get_flags(GtkTreeModel *tree_model) +{ + return GTK_TREE_MODEL_ITERS_PERSIST|GTK_TREE_MODEL_LIST_ONLY; +} + +static gint plover_package_store_get_n_columns(GtkTreeModel *tree_model) +{ + return PLOVER_PACKAGE_STORE_NO_COLUMNS; +} + +static GType + plover_package_store_get_column_type(GtkTreeModel *tree_model,gint indx) +{ + PloverPackageStore *store=(PloverPackageStore *)tree_model; + g_return_val_if_fail(indx>=0 && indx=g_sequence_get_length(priv->seq)) + return FALSE; + iter->stamp=priv->stamp; + iter->user_data=g_sequence_get_iter_at_pos(priv->seq,i); + return TRUE; +} + +static GtkTreePath * + plover_package_store_get_path(GtkTreeModel *tree_model,GtkTreeIter *iter) +{ + GtkTreePath *path; + g_return_val_if_fail(VALID_ITER(iter,tree_model),NULL); + if (g_sequence_iter_is_end(iter->user_data)) + return NULL; + path=gtk_tree_path_new(); + gtk_tree_path_append_index(path, + g_sequence_iter_get_position(iter->user_data)); + return path; +} + +static void plover_package_store_get_value(GtkTreeModel *tree_model, + GtkTreeIter *iter,gint column,GValue *value) +{ + PloverPackageStore *store=(PloverPackageStore *)tree_model; + PloverPackage *package; + g_return_if_fail(column>=0 && columnuser_data); + g_value_init(value,column_types[column]); + switch((PloverPackageStoreColumn)column) + { + case PLOVER_PACKAGE_STORE_OBJ_COLUMN: + g_value_set_object(value,package); + break; + case PLOVER_PACKAGE_STORE_INSTALLED_COLUMN: + break; + case PLOVER_PACKAGE_STORE_ICON_COLUMN: + g_value_set_object(value,plover_package_get_icon(package)); + break; + case PLOVER_PACKAGE_STORE_NAME_COLUMN: + g_value_set_string(value,plover_package_get_name(package)); + break; + case PLOVER_PACKAGE_STORE_VERSION_COLUMN: + g_value_set_string(value,plover_package_get_version(package)); + break; + case PLOVER_PACKAGE_STORE_SUMMARY_COLUMN: + g_value_set_string(value,plover_package_get_summary(package)); + break; + } +} + +static gboolean + plover_package_store_iter_next(GtkTreeModel *tree_model,GtkTreeIter *iter) +{ + g_return_val_if_fail(VALID_ITER(iter,tree_model),FALSE); + iter->user_data=g_sequence_iter_next(iter->user_data); + return !g_sequence_iter_is_end(iter->user_data); +} + +static gboolean plover_package_store_iter_children(GtkTreeModel *tree_model, + GtkTreeIter *iter,GtkTreeIter *parent) +{ + PloverPackageStorePrivate *priv; + PloverPackageStore *store=(PloverPackageStore *)tree_model; + priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(tree_model); + /* this is a list, nodes have no children */ + if (parent) + return FALSE; + if (g_sequence_get_length(priv->seq)>0) + { + iter->stamp=priv->stamp; + iter->user_data=g_sequence_get_begin_iter(priv->seq); + return TRUE; + } + else + return FALSE; +} + +static gboolean plover_package_store_iter_has_child(GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + return FALSE; +} + +static gint plover_package_store_iter_n_children(GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + PloverPackageStorePrivate *priv; + PloverPackageStore *store=(PloverPackageStore *)tree_model; + priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(tree_model); + if (!iter) + return g_sequence_get_length(priv->seq); + g_return_val_if_fail(VALID_ITER(iter,tree_model),-1); + return 0; +} + +static gboolean plover_package_store_iter_nth_child(GtkTreeModel *tree_model, + GtkTreeIter *iter,GtkTreeIter *parent,gint n) +{ + PloverPackageStorePrivate *priv; + PloverPackageStore *store=(PloverPackageStore *)tree_model; + priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(tree_model); + GSequenceIter *child; + if (parent) + return FALSE; + child=g_sequence_get_iter_at_pos(priv->seq,n); + if (g_sequence_iter_is_end(child)) + return FALSE; + iter->stamp=priv->stamp; + iter->user_data=child; + return TRUE; +} + +static gboolean plover_package_store_iter_parent(GtkTreeModel *tree_model, + GtkTreeIter *iter,GtkTreeIter *child) +{ + return FALSE; +} + +static void plover_package_store_tree_model_init(GtkTreeModelIface *iface) +{ + iface->get_flags=plover_package_store_get_flags; + iface->get_n_columns=plover_package_store_get_n_columns; + iface->get_column_type=plover_package_store_get_column_type; + iface->get_iter=plover_package_store_get_iter; + iface->get_path=plover_package_store_get_path; + iface->get_value=plover_package_store_get_value; + iface->iter_next=plover_package_store_iter_next; + iface->iter_children=plover_package_store_iter_children; + iface->iter_has_child=plover_package_store_iter_has_child; + iface->iter_n_children=plover_package_store_iter_n_children; + iface->iter_nth_child=plover_package_store_iter_nth_child; + iface->iter_parent=plover_package_store_iter_parent; +} + +static void plover_package_store_init(PloverPackageStore *store) +{ + PloverPackageStorePrivate *priv; + priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store); + priv->seq=g_sequence_new(NULL); + priv->stamp=g_random_int(); +} + +PloverPackageStore *plover_package_store_new(void) +{ + return g_object_new(PLOVER_TYPE_PACKAGE_STORE,NULL); +} + +GSList *plover_package_store_get_sets(PloverPackageStore *store) +{ + PloverPackageStorePrivate *priv; + g_return_val_if_fail(PLOVER_IS_PACKAGE_STORE(store),NULL); + priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store); + return priv->sets; +} + +static gint + plover__package_compar(gconstpointer a,gconstpointer b,gpointer user_data) +{ + PloverPackage *pa=PLOVER_PACKAGE(a); + PloverPackage *pb=PLOVER_PACKAGE(b); + return strcmp(plover_package_get_name(pa),plover_package_get_name(pb)); +} + +void plover_package_store_add_set(PloverPackageStore *store, + PloverPackageSet *set) +{ + GSList *packages,*link; + GSequenceIter *si; + GtkTreeIter ti; + GtkTreePath *path; + gint *indices; + PloverPackageStorePrivate *priv; + g_return_if_fail(PLOVER_IS_PACKAGE_STORE(store)); + g_return_if_fail(PLOVER_IS_PACKAGE_SET(set)); + priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store); + g_return_if_fail(g_slist_find(priv->sets,set) == NULL); + g_object_ref(set); + path=gtk_tree_path_new(); + gtk_tree_path_append_index(path,0); + indices=gtk_tree_path_get_indices(path); + packages=plover_package_set_get_packages(set); + for(link=packages;link;link=link->next) + { + si=g_sequence_insert_sorted(priv->seq,link->data, + plover__package_compar,NULL); + *indices=g_sequence_iter_get_position(si); + ti.stamp=priv->stamp; + ti.user_data=si; + gtk_tree_model_row_inserted(GTK_TREE_MODEL(store),path,&ti); + } + gtk_tree_path_free(path); + priv->sets=g_slist_prepend(priv->sets,set); +} + +void plover_package_store_remove_set(PloverPackageStore *store, + PloverPackageSet *set) +{ + GSList *packages,*link; + GSequence *seq; + GSequenceIter *iter,*prev,*remove; + GtkTreePath *path; + gint *indices; + PloverPackageStorePrivate *priv; + g_return_if_fail(PLOVER_IS_PACKAGE_STORE(store)); + g_return_if_fail(PLOVER_IS_PACKAGE_SET(set)); + priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store); + g_return_if_fail(g_slist_find(priv->sets,set) != NULL); + seq=g_sequence_new(NULL); + path=gtk_tree_path_new(); + gtk_tree_path_append_index(path,0); + indices=gtk_tree_path_get_indices(path); + packages=plover_package_set_get_packages(set); + for(link=packages;link;link=link->next) + g_sequence_insert_sorted(seq,link->data,plover__package_compar,NULL); + prev=NULL; + iter=g_sequence_get_begin_iter(priv->seq); + remove=g_sequence_get_begin_iter(seq); + while(!g_sequence_iter_is_end(iter) && !g_sequence_iter_is_end(remove)) + { + if (g_sequence_get(iter)==g_sequence_get(remove)) + { + *indices=g_sequence_iter_get_position(iter); + g_sequence_remove(iter); + remove=g_sequence_iter_next(remove); + gtk_tree_model_row_deleted(GTK_TREE_MODEL(store),path); + } + else + prev=iter; + if (prev) + iter=g_sequence_iter_next(prev); + else + iter=g_sequence_get_begin_iter(priv->seq); + } + gtk_tree_path_free(path); + g_sequence_free(seq); + priv->sets=g_slist_remove(priv->sets,set); + g_object_unref(set); + priv->stamp++; +} diff --git a/plover-gtk/packagestore.h b/plover-gtk/packagestore.h new file mode 100644 index 0000000..78691a9 --- /dev/null +++ b/plover-gtk/packagestore.h @@ -0,0 +1,58 @@ +#ifndef __PLOVER_PACKAGE_STORE_H__ +#define __PLOVER_PACKAGE_STORE_H__ + +#include +#include + +G_BEGIN_DECLS + +#define PLOVER_TYPE_PACKAGE_STORE\ + plover_package_store_get_type() +#define PLOVER_PACKAGE_STORE(obj)\ + G_TYPE_CHECK_INSTANCE_CAST(obj,\ + PLOVER_TYPE_PACKAGE_STORE,PloverPackageStore) +#define PLOVER_PACKAGE_STORE_CLASS(klass)\ + G_TYPE_CHECK_CLASS_CAST(klass,\ + PLOVER_TYPE_PACKAGE_STORE,\ + PloverPackageStoreClass) +#define PLOVER_IS_PACKAGE_STORE(obj)\ + G_TYPE_CHECK_INSTANCE_TYPE(obj,\ + PLOVER_TYPE_PACKAGE_STORE) +#define PLOVER_IS_PACKAGE_STORE_CLASS(klass)\ + G_TYPE_CHECK_CLASS_TYPE(obj,\ + PLOVER_TYPE_PACKAGE_STORE) +#define PLOVER_PACKAGE_STORE_GET_CLASS(obj)\ + G_TYPE_INSTANCE_GET_CLASS(obj,\ + PLOVER_TYPE_PACKAGE_STORE,\ + PloverPackageStoreClass) + +typedef enum +{ + PLOVER_PACKAGE_STORE_OBJ_COLUMN, + PLOVER_PACKAGE_STORE_INSTALLED_COLUMN, + PLOVER_PACKAGE_STORE_ICON_COLUMN, + PLOVER_PACKAGE_STORE_NAME_COLUMN, + PLOVER_PACKAGE_STORE_VERSION_COLUMN, + PLOVER_PACKAGE_STORE_SUMMARY_COLUMN, + PLOVER_PACKAGE_STORE_NO_COLUMNS +} PloverPackageStoreColumn; + +typedef struct _PloverPackageStore { + GObject parent_instance; +} PloverPackageStore; + +typedef struct _PloverPackageStoreClass { + GObjectClass parent_class; +} PloverPackageStoreClass; + +GType plover_package_store_get_type(void) G_GNUC_CONST; +PloverPackageStore *plover_package_store_new(void); +GSList *plover_package_store_get_sets(PloverPackageStore *store); +void plover_package_store_add_set(PloverPackageStore *store, + PloverPackageSet *set); +void plover_package_store_remove_set(PloverPackageStore *store, + PloverPackageSet *set); + +G_END_DECLS + +#endif /* __PLOVER_PACKAGE_STORE_H__ */ diff --git a/plover-gtk/plover-gtk.pc.in b/plover-gtk/plover-gtk.pc.in new file mode 100644 index 0000000..f1bd8a4 --- /dev/null +++ b/plover-gtk/plover-gtk.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: plover-gtk +Description: Plover Gtk+ objects +Version: @VERSION@ +Requires: plover gtk+-2.0 +Libs: -L${libdir} -lplover-gtk +Cflags: -I${includedir} diff --git a/plover/Makefile.am b/plover/Makefile.am index 38c3cd3..1a05feb 100644 --- a/plover/Makefile.am +++ b/plover/Makefile.am @@ -1,13 +1,12 @@ AM_CFLAGS=-g $(LIBPLOVER_CFLAGS) LIBS=$(LIBPLOVER_LIBS) INCLUDES=-I$(top_srcdir) -LDFLAGS=-no-undefined \ - -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) - -lib_LTLIBRARIES=libplover.la -libplover_la_SOURCES=plover.h util.c import-yum.c razor.c comps.c +LDFLAGS=-no-undefined -version-info $(LIBPLOVER_LT_VERSION_INFO) pkginclude_HEADERS=plover.h +lib_LTLIBRARIES=libplover.la +libplover_la_SOURCES=$(pkginclude_HEADERS) util.c import-yum.c razor.c comps.c + pkgconfigdir=$(libdir)/pkgconfig pkgconfig_DATA=plover.pc diff --git a/plover/import-yum.c b/plover/import-yum.c index d6c0c5e..e572273 100644 --- a/plover/import-yum.c +++ b/plover/import-yum.c @@ -98,6 +98,9 @@ yum_primary_start_element(void *data, const char *name, const char **atts) if (strcmp(atts[i], "packages") == 0) ctx->total = atoi(atts[i + 1]); } + } else if (strcmp(name, "package") == 0) { + *ctx->name=*ctx->arch=*ctx->summary=*ctx->description='\0'; + *ctx->url=*ctx->license='\0'; } else if (strcmp(name, "name") == 0) { ctx->state = YUM_STATE_PACKAGE_NAME; ctx->p = ctx->name; @@ -216,9 +219,6 @@ yum_primary_end_element (void *data, const char *name) XML_StopParser(ctx->current_parser, XML_TRUE); ctx->current_parser = ctx->filelists_parser; - - printf("\rimporting %d/%d", ++ctx->current, ctx->total); - fflush(stdout); } } @@ -360,6 +360,5 @@ plover_razor_set_create_from_yum(const char *base) gzclose(primary); gzclose(filelists); - printf ("\nsaving\n"); return razor_importer_finish(ctx.importer); }