diff -Nru gourmet-0.15.1/ChangeLog gourmet-0.15.2/ChangeLog --- gourmet-0.15.1/ChangeLog 2009-11-07 03:33:35.000000000 +0000 +++ gourmet-0.15.2/ChangeLog 2009-12-15 02:26:15.000000000 +0000 @@ -1,3 +1,165 @@ +2009-12-14 Thomas M. Hinkle + + * src/lib/backends/db.py (RecData.update_version_info): Fix update + from versions < 0.11.x + +2009-12-11 Thomas M. Hinkle + + * src/lib/plugins/nutritional_information/nutrition.py (foo.SimpleInterface.print_info): + Be less verbose. + * src/lib/importers/importer.py (Importer.commit_rec): Make sure + we provide unicode strings to db. + * src/lib/reccard.py (IngredientEditorModule.quick_add): Make sure + we provide unicode strings to DB. + (DescriptionEditorModule.save): Make sure we provide unicode strings. + +2009-12-02 Thomas M. Hinkle + + * src/lib/check_encodings.py (GetFile.__init__): Divide lines + using built-in splitlines() function -- this fixes problems with + line breaks on e.g. mac text files. + + * src/lib/importers/importManager.py (ImportManager.finish_web_import): + Print information about importer being used. + + +2009-12-01 Thomas M. Hinkle + + * src/lib/GourmetRecipeManager.py (RecGui.setup_main_window): Add + right-click menu back to main interface (we use the contents of + the action menu for the right-click). + + * src/lib/reccard.py (RecCardDisplay.update_yields_multiplier): + Fix updating of yield_unit on yield_change. + +2009-11-29 Thomas M Hinkle + + * src/lib/prefsGui.py (PreferencesGui): Make PreferencesGui + pluggable. + + * src/lib/plugins/nutritional_information/__init__.py: ++ + preferences plugin + + * src/lib/plugins/nutritional_information/export_plugin.py (NutritionBaseExporterPlugin): + Add preference that allows user to turn off nutritional export + altogether or to turn it off when information is only partial. + + * src/lib/plugin.py (BaseExporterPlugin.add_field): Add parameter + write_empty_field (which defaults to False) to determine whether + we add custom fields with no content. + (DatabasePlugin.remove): Change "deactivate" call to "remove", + which was what was intended (deactivate is called when the + pluggable is destroyed; remove is called when the plugin is + deactivated). + (PrefsPlugin): Add base class for adding tabs to preferences + dialog. + + * src/lib/plugin_loader.py (MasterLoader.register_pluggable): Fix + typo. + + * glade/preferenceDialog.glade: Remove hardcoded email + preferences (if we want them back, they belong in the email + plugin). + +2009-11-22 Thomas M. Hinkle + + * src/lib/plugins/import_export/pdf_plugin/pdf_exporter.py (CustomUnitOption): + Add custom widget for setting margins that allows adjusting of + units (cm/inch/points). + (PdfPrefGetter.get_args_from_opts): Save page layout preferences + correctly. + + * src/lib/gtk_extras/optionTable.py (OptionTable.createOptionWidgets): + Add CustomOption option for callers who want to provide their own + widget for setting an option. + + * src/lib/plugins/nutritional_information/export_plugin.py (NutritionBaseExporterPlugin.get_nutritional_info_as_text_blob): + Escape items in case they have &s or other characters that screw + up XML. + +2009-11-21 Thomas M. Hinkle + + * src/lib/plugins/import_export/pdf_plugin/print_plugin.py (PDFRecipePrinter.begin_print): + Try to raise an error if there's a problem with the PDF. + + * src/lib/plugins/import_export/pdf_plugin/pdf_exporter.py (PdfPrefTable): + Use prefs to save pdf settings automatically. + + * src/lib/gtk_extras/optionTable.py (OptionTable.createOptionWidgets): + Fix bug where having a default value of 0 made any other value + unsettable. + + * src/lib/reccard.py (RecCardDisplay.print_cb): Move repetitive + code to printmanager. + + * src/lib/exporters/printer.py (PrintManager.print_recipes): Move + basic printing code to PrintManager. + + * src/lib/GourmetRecipeManager.py (ImporterExporter.print_recs): + Move repetitive print code to print manager so we can do things + like handle exceptions elegantly there. + +2009-11-20 Thomas M. Hinkle + + * src/lib/plugins/nutritional_information/export_plugin.py (NutritionBaseExporterPlugin.get_nutritional_info_as_text_blob): + Fix typo that broke printing. + + * src/lib/GourmetRecipeManager.py (GourmetApplication.setup_recipes): + Clarify code around autosave. + + + * src/lib/plugins/nutritional_information/reccard_plugin.py (NutritionDisplayModule.enter_page): + Fix keyError bug on initialization. + + * src/lib/plugins/nutritional_information/nutritionLabel.py (NutritionLabel.setup_yield_label): + Use singular form for "amount per ___" yield unit. + + * src/lib/plugins/nutritional_information/export_plugin.py (NutritionBaseExporterPlugin.get_nutritional_info_as_text_blob): + Use singular form for "amount per ____" yield unit. + + * src/lib/shopgui.py (ShopGui.setup_main): Don't show window + initially. + + * src/lib/reccard.py (RecCardDisplay.update_yields_multiplier): + Use singular forms when settings yields to 1. + +2009-11-19 Thomas M. Hinkle + + * src/lib/plugins/import_export/pdf_plugin/pdf_exporter.py (write_ingref): + Only write links that will work -- we do this by tracking which + recipes are going into our document and checking links against + that list of recipes. + + * src/lib/plugins/import_export/pdf.gourmet-plugin.in: Change name + and description to reflect this plugin's new status as the primary + printing provider. + + * src/lib/exporters/printer.py: Add simple message telling user + which plugin to install to get printing if there is no printing. + + * src/lib/exporters/exporter.py (ExporterMultirec.append_referenced_recipes): + Add method to automatically append referenced recipes to the list + of recipes to be exported. + + * src/lib/plugin_loader.py (MasterLoader.deactivate_plugin_set): + Fix typo that broke deactivation of plugins. + +2009-11-17 Thomas M. Hinkle + + * src/lib/GourmetRecipeManager.py (ImporterExporter.print_recs): + Use new printing API to print. + * src/lib/plugin.py (PrinterPlugin): Add new plugin for printing. + * src/lib/reccard.py (RecCardDisplay.print_cb): Use new printing + API to print. + * src/lib/shopgui.py (ShopGui.doSave): No longer use "lprprinter" + to do text save. + (ShopGui.printList): Use new printing API to print. + * src/lib/exporters/printer.py: Rewrite printer.py to use a plugin + architecture. If no plugins are available, no printing. The + expected plugin will be the PDF plugin using Reportlab. + * plugins/import_export/pdf_plugin/print_plugin.py: Create plugin + for new printing plugin architecture. + 2009-11-06 Thomas M Hinkle * src/lib/plugins/import_export/website_import_plugins/__init__.py (plugins): diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/debian/changelog /tmp/KYLRrknCT9/gourmet-0.15.2/debian/changelog --- gourmet-0.15.1/debian/changelog 2009-12-15 20:12:12.000000000 +0000 +++ gourmet-0.15.2/debian/changelog 2009-12-15 20:12:13.000000000 +0000 @@ -1,4 +1,4 @@ -gourmet (0.15.1-0ubuntu1~jdstrand0.9.10.0) karmic-proposed; urgency=low +gourmet (0.15.2-0ubuntu1~jdstrand0.9.10.0) karmic-proposed; urgency=low * New upstream release (LP: #431806, Closes: #530841). Also fixes the following bugs: @@ -13,7 +13,7 @@ - debian/control: bump Standards-Version to 3.8.3 - debian/compat: bump to 5 - -- Jamie Strandboge Sun, 13 Dec 2009 09:35:18 -0600 + -- Jamie Strandboge Tue, 15 Dec 2009 13:31:42 -0600 gourmet (0.14.5-2ubuntu2) karmic; urgency=low diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/glade/preferenceDialog.glade /tmp/KYLRrknCT9/gourmet-0.15.2/glade/preferenceDialog.glade --- gourmet-0.15.1/glade/preferenceDialog.glade 2009-05-20 01:48:57.000000000 +0100 +++ gourmet-0.15.2/glade/preferenceDialog.glade 2009-11-30 11:55:25.000000000 +0000 @@ -1,1058 +1,530 @@ - - - + - - - Gourmet Recipe Manager Preferences - GTK_WINDOW_TOPLEVEL - GTK_WIN_POS_NONE - False - 400 - 500 - True - False - True - False - False - GDK_WINDOW_TYPE_HINT_DIALOG - GDK_GRAVITY_NORTH_WEST - True - False - True - - - - True - False - 0 - - - - True - GTK_BUTTONBOX_END - - - - True - True - True - gtk-close - True - GTK_RELIEF_NORMAL - True - -7 - - - - - 0 - False - True - GTK_PACK_END - - - - - - True - True - True - True - GTK_POS_TOP - False - False - - - - True - True - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - GTK_SHADOW_NONE - GTK_CORNER_TOP_LEFT - - - - True - GTK_SHADOW_IN - - - - True - 0.5 - 0.5 - 1 - 1 - 6 - 6 - 6 - 6 - - - - True - False - 0 - - - - True - <b>Index View Preferences</b> - False - True - GTK_JUSTIFY_LEFT - False - False - 0 - 0 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - 0.5 - 0.5 - 1 - 1 - 6 - 0 - 12 - 0 - - - - True - False - 0 - - - - True - False - 6 - - - - True - _Recipes per page: - True - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - recipesPerPageSpinButton - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - 0 - 0 - 1 - 1 - 0 - 0 - 6 - 0 - - - - True - True - 1 - 0 - True - GTK_UPDATE_ALWAYS - False - False - 15 1 100 1 10 0 - - - - - 0 - False - True - - - - - 11 - True - True - - - - - - True - <i>Configure which columns are included in the recipe index view.</i> - False - True - GTK_JUSTIFY_LEFT - True - False - 0 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - - 0 - False - False - - - - - - - - - - - False - True - - - - - - True - Index View - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - tab - - - - - - True - True - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - GTK_SHADOW_NONE - GTK_CORNER_TOP_LEFT - - - - True - GTK_SHADOW_IN - - - - True - 0.5 - 0.5 - 1 - 1 - 6 - 6 - 6 - 6 - - - - True - False - 0 - - - - True - <b>Card View Preferences</b> - False - True - GTK_JUSTIFY_LEFT - False - False - 0 - 0 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - 0.5 - 0.5 - 1 - 1 - 6 - 0 - 12 - 0 - - - - True - False - 0 - - - - True - False - 0 - - - - True - True - _Allow units to change when multiplying - True - GTK_RELIEF_NORMAL - True - False - False - True - - - 0 - False - False - - - - - - True - Use fractions when possible for display - True - _Use fractions - True - GTK_RELIEF_NORMAL - True - False - False - True - - - 0 - False - False - - - - - - False - <i>Remove items you don't use from the Recipe Card interface.</i> - False - True - GTK_JUSTIFY_LEFT - True - False - 0 - 0.5 - 0 - 6 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - 0 - True - True - - - - - - - 0 - True - True - - - - - - - - - - - False - True - - - - - - True - Card View - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - tab - - - - - - True - True - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - GTK_SHADOW_NONE - GTK_CORNER_TOP_LEFT - - - - True - GTK_SHADOW_IN - - - - True - 0.5 - 0.5 - 1 - 1 - 6 - 6 - 6 - 6 - - - - True - False - 0 - - - - True - <b>Shopping List Preferences</b> - False - True - GTK_JUSTIFY_LEFT - False - False - 0 - 0 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - 0.5 - 0.5 - 1 - 1 - 6 - 0 - 12 - 0 - - - - True - False - 0 - - - - True - <i>What should Gourmet do with Optional Ingredients when adding recipes to the shopping list?</i> - False - True - GTK_JUSTIFY_LEFT - True - False - 0 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - 0.5 - 0.5 - 1 - 1 - 0 - 0 - 12 - 0 - - - - True - False - 0 - - - - True - True - As_k whether to include optional ingredients - True - GTK_RELIEF_NORMAL - True - False - False - True - - - 0 - False - False - - - - - - True - 0 - 0 - 1 - 1 - 0 - 0 - 12 - 0 - - - - True - False - 0 - - - - True - True - _Remember user selections by default - True - GTK_RELIEF_NORMAL - True - False - False - True - - - 0 - False - False - - - - - - True - True - GTK_RELIEF_NORMAL - True - - - - True - 0.5 - 0.5 - 0 - 0 - 0 - 0 - 0 - 0 - - - - True - False - 2 - - - - True - gtk-clear - 4 - 0.5 - 0.5 - 0 - 0 - - - 0 - False - False - - - - - - True - _Clear remembered optional ingredients - True - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - - - - 0 - False - False - - - - - - - 0 - False - False - - - - - - True - True - _Always add optional ingredients - True - GTK_RELIEF_NORMAL - True - False - False - True - optional_ask - - - 0 - False - False - - - - - - True - True - _Never add optional ingredients - True - GTK_RELIEF_NORMAL - True - False - False - True - optional_ask - - - 0 - False - False - - - - - - - 0 - False - False - - - - - - - 0 - True - True - - - - - - - - - - - False - True - - - - - - True - Shopping List - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - tab - - - - - - True - GTK_SHADOW_IN - - - - True - 0.5 - 0.5 - 1 - 1 - 6 - 6 - 6 - 6 - - - - True - False - 0 - - - - True - <b>Email Preferences</b> - False - True - GTK_JUSTIFY_LEFT - False - False - 0 - 0 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - 0.5 - 0.5 - 1 - 1 - 6 - 0 - 12 - 0 - - - - True - False - 0 - - - - True - False - 0 - - - - True - <i>Preferences for use when sending a recipe in an email.</i> - False - True - GTK_JUSTIFY_LEFT - True - False - 0 - 0.5 - 0 - 6 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - 0 - False - True - - - - - - True - False - 0 - - - - True - True - Include Recipe in _Body of E-mail (A good idea no matter what) - True - GTK_RELIEF_NORMAL - True - False - False - True - - - 0 - False - False - - - - - - True - True - Include Recipe as an _HTML Attachment to the E-mail - True - GTK_RELIEF_NORMAL - True - False - False - True - - - 0 - False - False - - - - - - True - True - _Always use these settings - True - GTK_RELIEF_NORMAL - True - False - False - True - - - 0 - False - False - - - - - 0 - False - True - - - - - - - 0 - True - True - - - - - - - - - False - True - - - - - - True - Email Preferences - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - tab - - - - - 0 - True - True - - - - - - + + + + Gourmet Recipe Manager Preferences + 400 + 500 + dialog + + + True + + + True + True + + + True + True + automatic + automatic + + + True + + + True + 6 + 6 + 6 + 6 + + + True + + + True + 0 + 0 + <b>Index View Preferences</b> + True + + + False + False + 0 + + + + + True + 6 + 12 + + + True + + + True + 6 + + + True + 0 + _Recipes per page: + True + recipesPerPageSpinButton + + + False + False + 0 + + + + + True + 0 + 0 + 6 + + + True + True + 15 1 100 1 10 0 + 1 + True + + + + + False + 1 + + + + + 11 + 0 + + + + + True + 0 + <i>Configure which columns are included in the recipe index view.</i> + True + True + + + False + False + 1 + + + + + + + False + False + 1 + + + + + + + + + + + + + True + Index View + + + False + tab + + + + + True + True + automatic + automatic + + + True + + + True + 6 + 6 + 6 + 6 + + + True + + + True + 0 + 0 + <b>Card View Preferences</b> + True + + + False + False + 0 + + + + + True + 6 + 12 + + + True + + + True + + + _Allow units to change when multiplying + True + True + False + True + True + + + False + False + 0 + + + + + _Use fractions + True + True + False + Use fractions when possible for display + True + True + + + False + False + 1 + + + + + 0 + 6 + <i>Remove items you don't use from the Recipe Card interface.</i> + True + True + + + False + False + 2 + + + + + 0 + + + + + + + 1 + + + + + + + + + + + 1 + + + + + True + Card View + + + 1 + False + tab + + + + + True + True + automatic + automatic + + + True + + + True + 6 + 6 + 6 + 6 + + + True + + + True + 0 + 0 + <b>Shopping List Preferences</b> + True + + + False + False + 0 + + + + + True + 6 + 12 + + + True + + + True + 0 + <i>What should Gourmet do with Optional Ingredients when adding recipes to the shopping list?</i> + True + True + + + False + False + 0 + + + + + True + 12 + + + True + + + As_k whether to include optional ingredients + True + True + False + True + True + + + False + False + 0 + + + + + True + 0 + 0 + 12 + + + True + + + _Remember user selections by default + True + True + False + True + True + + + False + False + 0 + + + + + True + True + False + + + True + 0 + 0 + + + True + 2 + + + True + gtk-clear + + + False + False + 0 + + + + + True + _Clear remembered optional ingredients + True + + + False + False + 1 + + + + + + + + + False + False + 1 + + + + + + + False + False + 1 + + + + + _Always add optional ingredients + True + True + False + True + True + optional_ask + + + False + False + 2 + + + + + _Never add optional ingredients + True + True + False + True + True + optional_ask + + + False + False + 3 + + + + + + + False + False + 1 + + + + + + + 1 + + + + + + + + + + + 2 + + + + + True + Shopping List + + + 2 + False + tab + + + + + 2 + + + + + True + end + + + gtk-close + -7 + True + True + True + False + True + + + False + False + 0 + + + + + False + end + 0 + + + + + diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/gourmet-0.15.0/gourmet.desktop.in /tmp/KYLRrknCT9/gourmet-0.15.2/gourmet-0.15.0/gourmet.desktop.in --- gourmet-0.15.1/gourmet-0.15.0/gourmet.desktop.in 2009-05-30 00:05:29.000000000 +0100 +++ gourmet-0.15.2/gourmet-0.15.0/gourmet.desktop.in 1970-01-01 01:00:00.000000000 +0100 @@ -1,9 +0,0 @@ -[Desktop Entry] -_Name=Gourmet Recipe Manager -_Comment=Organize recipes, create shopping lists, calculate nutritional information, and more. -Exec=gourmet -Terminal=false -Type=Application -Categories=GNOME;Application;Utility; -StartupNotify=true -Icon=recbox.png Binary files /tmp/Ab6j0d1sfy/gourmet-0.15.1/i18n/messages.mo and /tmp/KYLRrknCT9/gourmet-0.15.2/i18n/messages.mo differ diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/MANIFEST /tmp/KYLRrknCT9/gourmet-0.15.2/MANIFEST --- gourmet-0.15.1/MANIFEST 2009-11-07 04:29:40.000000000 +0000 +++ gourmet-0.15.2/MANIFEST 2009-12-15 02:29:50.000000000 +0000 @@ -31,7 +31,6 @@ glade/shopCatEditor.glade glade/timerDialog.glade glade/valueEditor.glade -gourmet-0.15.0/gourmet.desktop.in gourmet.1 gourmet.desktop.in i18n/POTFILES.in @@ -70,7 +69,6 @@ i18n/ja.po i18n/lt.po i18n/lv.po -i18n/messages.mo i18n/nb.po i18n/nl.po i18n/nl_BE.po @@ -150,15 +148,11 @@ src/lib/exporters/eatdrinkfeelgood_exporter.py src/lib/exporters/exportManager.py src/lib/exporters/exporter.py -src/lib/exporters/gnomeprinter.py -src/lib/exporters/gnomeprinter_obsolete.py src/lib/exporters/gxml_exporter.py -src/lib/exporters/lprprinter.py src/lib/exporters/page_drawer.py src/lib/exporters/printer.py src/lib/exporters/recipe_emailer.py src/lib/exporters/rtf_exporter.py -src/lib/exporters/winprinter.py src/lib/exporters/xml_exporter.py src/lib/gdebug.py src/lib/gettext_setup.py @@ -226,6 +220,7 @@ src/lib/plugins/browse_recipes/images/preptime_empty_clock.png src/lib/plugins/browse_recipes/images/rating.png src/lib/plugins/browse_recipes/images/source.png +src/lib/plugins/check_for_unicode_16/__init__.py src/lib/plugins/duplicate_finder.gourmet-plugin src/lib/plugins/duplicate_finder.gourmet-plugin.in src/lib/plugins/duplicate_finder/__init__.py @@ -324,6 +319,7 @@ src/lib/plugins/nutritional_information/export_plugin.py src/lib/plugins/nutritional_information/images/Nutrition.png src/lib/plugins/nutritional_information/main_plugin.py +src/lib/plugins/nutritional_information/nutPrefsPlugin.py src/lib/plugins/nutritional_information/nut_recipe_card_display.glade src/lib/plugins/nutritional_information/nutrition.py src/lib/plugins/nutritional_information/nutritionDisplay.py @@ -358,6 +354,8 @@ src/lib/plugins/unit_display_prefs.gourmet-plugin.in src/lib/plugins/unit_display_prefs/__init__.py src/lib/plugins/unit_display_prefs/unit_prefs_dialog.py +src/lib/plugins/utf16.gourmet-plugin +src/lib/plugins/utf16.gourmet-plugin.in src/lib/prefs.py src/lib/prefsGui.py src/lib/profileImport.py diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/PKG-INFO /tmp/KYLRrknCT9/gourmet-0.15.2/PKG-INFO --- gourmet-0.15.1/PKG-INFO 2009-11-07 04:29:42.000000000 +0000 +++ gourmet-0.15.2/PKG-INFO 2009-12-15 02:29:57.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: gourmet -Version: 0.15.1 +Version: 0.15.2 Summary: Recipe Organizer and Shopping List Generator for Gnome Home-page: http://grecipe-manager.sourceforge.net Author: Thomas Mills Hinkle diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/backends/db.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/backends/db.py --- gourmet-0.15.1/src/lib/backends/db.py 2009-11-07 03:16:35.000000000 +0000 +++ gourmet-0.15.2/src/lib/backends/db.py 2009-12-15 02:13:06.000000000 +0000 @@ -460,28 +460,15 @@ stored_info = self.fetch_one(self.info_table) ### Code for updates between versions... - if not self.new_db: - print 'version older than 0.11.4 -- doing update' - # Version < 0.11.4 -> version >= 0.11.4... fix up screwed up keylookup_table tables... - # We don't actually do this yet... (FIXME) + if not self.new_db: + sv_text = "%s.%s.%s"%(stored_info.version_super,stored_info.version_major,stored_info.version_minor) #print 'STORED_INFO:',stored_info.version_super,stored_info.version_major,stored_info.version_minor - if stored_info.version_super == 0 and stored_info.version_major <= 11 and stored_info.version_minor <= 3: - self.backup_db() - print 'Fixing broken ingredient-key view from earlier versions.' - # Drop keylookup_table table, which wasn't being properly kept up - # to date... - self.delete_by_criteria(self.keylookup_table,{}) - # And update it in accord with current ingredients (less - # than an ideal decision, alas) - for ingredient in self.fetch_all(self.ingredients_table,deleted=False): - self.add_ing_to_keydic(ingredient.item,ingredient.ingkey) - # Change from servings to yields! ( we use the plural to avoid a headache with keywords) if (stored_info.version_super == 0 and ((stored_info.version_major <= 14 and stored_info.version_minor <= 7) or (stored_info.version_major < 14) )): - print 'Database older than 0.14.7 -- updating' + print 'Database older than 0.14.7 -- updating',sv_text # Don't change the table defs here without changing them # above as well (for new users) - sorry for the stupid # repetition of code. @@ -495,13 +482,13 @@ } ).execute() if stored_info.version_super == 0 and stored_info.version_major < 14: - print 'Database older than 0.14.0 -- updating' + print 'Database older than 0.14.0 -- updating',sv_text self.backup_db() # Name changes to make working with IDs make more sense # (i.e. the column named 'id' should always be a unique # identifier for a given table -- it should not be used to # refer to the IDs from *other* tables - print 'Upgrade from < 0.14' + print 'Upgrade from < 0.14',sv_text self.alter_table('categories',self.setup_category_table, {'id':'recipe_id'},['category']) print 'RECREATE INGREDIENTS TABLE (This could take a while...)' @@ -517,7 +504,7 @@ # (These all get added in 0.13.0) if stored_info.version_super == 0 and stored_info.version_major <= 12: self.backup_db() - print 'UPDATE FROM < 0.13.0...' + print 'UPDATE FROM < 0.13.0...',sv_text # Don't change the table defs here without changing them # above as well (for new users) - sorry for the stupid # repetition of code. @@ -526,7 +513,7 @@ self.add_column_to_table(self.recipe_table,('ingredient_hash',String(length=32),{})) # Add a link field... self.add_column_to_table(self.recipe_table,('link',Text(),{})) - print 'Searching for links in old recipe fields...' + print 'Searching for links in old recipe fields...',sv_text URL_SOURCES = ['instructions','source','modifications'] recs = self.search_recipes( [ @@ -571,6 +558,19 @@ ) # Add hash values to identify all recipes... for r in self.fetch_all(self.recipe_table): self.update_hashes(r) + + if stored_info.version_super == 0 and stored_info.version_major <= 11 and stored_info.version_minor <= 3: + print 'version older than 0.11.4 -- doing update',sv_text + self.backup_db() + print 'Fixing broken ingredient-key view from earlier versions.' + # Drop keylookup_table table, which wasn't being properly kept up + # to date... + self.delete_by_criteria(self.keylookup_table,{}) + # And update it in accord with current ingredients (less + # than an ideal decision, alas) + for ingredient in self.fetch_all(self.ingredients_table,deleted=False): + self.add_ing_to_keydic(ingredient.item,ingredient.ingkey) + for plugin in self.plugins: self.update_plugin_version(plugin, (current_super,current_major,current_minor) diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/check_encodings.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/check_encodings.py --- gourmet-0.15.1/src/lib/check_encodings.py 2009-06-18 11:05:23.000000000 +0100 +++ gourmet-0.15.2/src/lib/check_encodings.py 2009-12-15 01:46:35.000000000 +0000 @@ -2,12 +2,13 @@ from gdebug import debug from gtk_extras import dialog_extras as de from gettext import gettext as _ +from prefs import get_prefs class CheckEncoding: """A class to read a file and guess the correct text encoding.""" - encodings = ['iso8859','ascii','latin_1','cp850','cp1252','utf-8','utf-16','utf-16-be'] + encodings = ['iso8859','ascii','latin_1','cp850','cp1252','utf-8'] all_encodings= ['ascii','cp037','cp424', 'cp437','cp500','cp737','cp775','cp850','cp852', 'cp855','cp856','cp857','cp860','cp861','cp862', @@ -23,6 +24,8 @@ 'utf_16_le','utf_7','utf_8'] def __init__ (self, file, encodings=None): + if get_prefs().get('utf-16',False): + self.encodings.extend(['utf_16','utf_16_le','utf_16_be']) if encodings: self.encodings = encodings if type(file)==str: file = open(file,'r') @@ -51,10 +54,12 @@ if not encodings: encodings=self.all_encodings self.possible_encodings = {} for e in encodings: + print 'Test ',e try: d=self.txt.decode(e) - if not d in self.possible_encodings.values(): - # if we don't already have this possibility, add + if d and (not d in self.possible_encodings.values()): + # if we don't already have this possibility, add + print "Maybe it's",e,d self.possible_encodings[e]=d.encode('utf8') except UnicodeDecodeError: pass @@ -71,7 +76,7 @@ else: encoding = encs.keys()[0] self.enc = encoding - self.lines = encs[self.enc].split('\n') + self.lines = encs[self.enc].splitlines() debug('reading file %s as encoding %s'%(file, self.enc)) self.lines = [l.encode() for l in self.lines] else: @@ -181,7 +186,8 @@ def set_buffer_text (self, buffer, text): """Set buffer text to show encoding differences.""" - lines = text.split('\n') + print 'Setting buffer to',text + lines = text.splitlines() totl = len(lines) shown = [] for line,diffs in self.diff_lines.items(): @@ -201,7 +207,11 @@ l = lines[n] if n==line: start = 0 + print 'Inserting',l for sdiff,ediff in diffs: + print 'Cut into...' + print l[start:sdiff] + print l[sdiff:ediff] buffer.insert_with_tags(buffer.get_end_iter(), l[start:sdiff], *self.line_highlight_tags) @@ -209,6 +219,7 @@ l[sdiff:ediff], *self.highlight_tags) start = ediff + print l[start:] buffer.insert_with_tags(buffer.get_end_iter(), l[start:], *self.line_highlight_tags) @@ -220,11 +231,11 @@ encoded_buffers = self.encodings.values() def mycmp (a,b): '''Sort by number of newlines (most first)''' - return cmp(b.count('\n'),a.count('\n')) + return cmp(len(b.splitlines()),len(a.splitlines())) encoded_buffers.sort(mycmp) enc1 = encoded_buffers[0] - enc_rest = [e.split('\n') for e in encoded_buffers[1:]] - for linenum, l in enumerate(enc1.split('\n')): + enc_rest = [e.splitlines() for e in encoded_buffers[1:]] + for linenum, l in enumerate(enc1.splitlines()): other_lines = [len(e)>linenum and e[linenum] for e in enc_rest] # Remove any Falses returned by above other_lines = filter(lambda x: type(x) != bool, other_lines) @@ -237,6 +248,7 @@ else: ranges.append([chnum,chnum+1]) self.diff_lines[linenum]=ranges + print 'DIFF_LINES=',self.diff_lines def getEncoding (*args,**kwargs): @@ -251,8 +263,10 @@ if __name__ == '__main__': print 'grabbing dialog extras' - import gtk_extras.dialog_extras as de - print 'selecting file' - fn=de.select_file('Select file to decode',filters=[['Plain Text',['text/plain'],'*txt']],) - print 'fn = ',fn - print "Got file ", get_file(fn)[0:5] + #import gtk_extras.dialog_extras as de + #print 'selecting file' + #fn=de.select_file('Select file to decode',filters=[['Plain Text',['text/plain'],'*txt']],) + #print 'fn = ',fn + print "Got file ", get_file('/tmp/foo.txt')[0:5] + + diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/defaults/defaults_en.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/defaults/defaults_en.py --- gourmet-0.15.1/src/lib/defaults/defaults_en.py 2009-11-05 20:54:32.000000000 +0000 +++ gourmet-0.15.2/src/lib/defaults/defaults_en.py 2009-11-20 11:44:56.000000000 +0000 @@ -830,7 +830,8 @@ PLURALS += [(s,s+'s') for s in ['cup','crust','clove','serving','pound','gram', 'ounce','tablespoon','teaspoon','gallon','can', - 'slice','pie','package','quart','pint',] + 'slice','pie','package','quart','pint','muffin', + 'cookie',] ] diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/defaults/defaults.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/defaults/defaults.py --- gourmet-0.15.1/src/lib/defaults/defaults.py 2009-05-20 01:48:57.000000000 +0100 +++ gourmet-0.15.2/src/lib/defaults/defaults.py 2009-11-20 11:49:42.000000000 +0000 @@ -104,4 +104,4 @@ return ngettext(*forms) else: return word - + diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/exporters/exporter.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/exporters/exporter.py --- gourmet-0.15.1/src/lib/exporters/exporter.py 2009-05-20 02:34:57.000000000 +0100 +++ gourmet-0.15.2/src/lib/exporters/exporter.py 2009-11-24 11:55:13.000000000 +0000 @@ -467,7 +467,7 @@ name = 'Exporter' - def __init__ (self, rd, recipe_table, out, one_file=True, + def __init__ (self, rd, recipes, out, one_file=True, ext='txt', conv=None, imgcount=1, @@ -475,13 +475,13 @@ exporter=exporter, exporter_kwargs={}, padding=None): - """Output all recipes in recipe_table into a document or multiple + """Output all recipes in recipes into a document or multiple documents. if one_file, then everything is in one file. Otherwise, we treat 'out' as a directory and put individual recipe files within it.""" self.timer=TimeAction('exporterMultirec.__init__()') self.rd = rd - self.recipe_table = recipe_table + self.recipes = recipes self.out = out self.padding=padding self.one_file = one_file @@ -522,12 +522,22 @@ print "oops:",ret,"doesn't look like unicode." raise return ret + + def append_referenced_recipes (self): + for r in self.recipes[:]: + reffed = self.rd.db.execute( + 'select * from ingredients where recipe_id=? and refid is not null',r.id + ) + for ref in reffed: + rec = self.rd.get_rec(ref.refid) + if not rec in self.recipes: + print 'Appending recipe ',rec.title,'referenced in ',r.title + self.recipes.append(rec) @pluggable_method def do_run (self): - print 'Exportermultirec.do_run' self.rcount = 0 - self.rlen = len(self.recipe_table) + self.rlen = len(self.recipes) if not self.one_file: self.outdir=self.out if os.path.exists(self.outdir): @@ -542,7 +552,8 @@ self.suspended = False self.terminated = False first = True - for r in self.recipe_table: + self.append_referenced_recipes() + for r in self.recipes: self.check_for_sleep() msg = _("Exported %(number)s of %(total)s recipes")%{'number':self.rcount,'total':self.rlen} self.emit('progress',float(self.rcount)/float(self.rlen), msg) diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/exporters/exportManager.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/exporters/exportManager.py --- gourmet-0.15.1/src/lib/exporters/exportManager.py 2009-05-24 18:55:55.000000000 +0100 +++ gourmet-0.15.2/src/lib/exporters/exportManager.py 2009-11-18 02:44:16.000000000 +0000 @@ -168,7 +168,7 @@ for plugin in self.plugins: filters.append(plugin.saveas_filters) return filters - + def register_plugin (self, plugin): name = plugin.saveas_filters[0] if self.plugins_by_name.has_key(name): diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/exporters/gnomeprinter_obsolete.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/exporters/gnomeprinter_obsolete.py --- gourmet-0.15.1/src/lib/exporters/gnomeprinter_obsolete.py 2009-05-20 01:48:57.000000000 +0100 +++ gourmet-0.15.2/src/lib/exporters/gnomeprinter_obsolete.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,331 +0,0 @@ -# we keep this around because not all gnomeprints support the PANGO LAYOUT stuff we've moved to. -import gtk, gnomeprint, gnomeprint.ui, re -import exporter -from gourmet import ImageExtras,gglobals,convert -from gourmet.gdebug import * -from gettext import gettext as _ - -def do_print(dialog, job): - pc = gnomeprint.Context(dialog.get_config()) - job.render(pc) - pc.close() - -class renderer: - def __init__(self, job=None): - if not job: - job = gnomeprint.Job(gnomeprint.config_default()) - self.job = job - self.gpc = self.job.get_context() - self.width, self.height = gnomeprint.job_get_page_size_from_config(job.get_config()) - self.margin = 48 - self.wmargin = 100 - self.left = self.wmargin - self.right = self.width - self.wmargin - self.top = self.height - self.margin - self.bottom = self.margin - self.default_left = self.left - self.default_right = self.right - # units are 1/72 in. - self.head_indent = -30 - self.move_down_hooks = [] - # <<>> - self.n = 0 - self.new_page() - self.adjust = 0 # allows adjustments for more than one page... - self.default_font='Serif' - self.default_head='Sans' - self.default_head_size=16 - self.default_head_style='Bold' - self.set_font() - - def set_font (self, fontname=None, size=12, style='Regular'): - if not fontname: fontname = self.default_font - self.font = gnomeprint.font_find_closest("%s %s"%(fontname,style),size) - self.lheight = size * 1.25 - self.gpc.setfont(self.font) - - def end (self): - self.gpc.showpage() - self.job.close() - - def setup_columns (columns=2, depth=None, ): - pass - - def write_pixbuf (self, pixbuf, inline=True, align='left', border=10): - """Align can take "left", "right", or "center". - "center" implies not inline.""" - raw_image = pixbuf.get_pixels() - has_alpha = pixbuf.get_has_alpha() - rowstride = pixbuf.get_rowstride() - height = pixbuf.get_height() - width = pixbuf.get_width() - # if we're not at the top, give us our border - if not self.yposition >= self.top: - self.move_down(border) - if (self.yposition - height) <= self.bottom: - self.new_page() - self.gpc.gsave() - if align=='left': - left = self.left - if align=='right': - left = self.right - width - if align=='center': - left = (self.width - width)/2 - self.gpc.translate(left,self.yposition-height) - #self.gpc.moveto(self.left, self.yposition) - self.gpc.scale(width,height) - if has_alpha: self.gpc.rgbaimage(raw_image, width, height, rowstride) - else: self.gpc.rgbimage(raw_image, width, height, rowstride) - self.gpc.grestore() - # don't allow "inline" if our width is less than a few words - remaining_width = self.right - self.left - width -border - if remaining_width < self.font.get_width_utf8("A reasonable length"): - inline = False - if inline and align != 'center': - # we shift the left and right side to allow for our image - if align=='left': - self.left = left + width + border - else: - self.right = left - border - # we set up a hook to reset margins once we're beyond the image. - image_end_pos = self.yposition - def reset_margins (yposition): - if yposition <= image_end_pos - (height + border): - self.left = self.default_left - self.right = self.default_right - self.move_down_hooks.remove(self.reset_margin_hook) - self.reset_margin_hook=reset_margins - self.move_down_hooks.append(self.reset_margin_hook) - else: - self.move_down(height + border) - - def write_line (self, text, indent=0): - self.move_down(self.lheight) - self.gpc.moveto(self.left + indent, self.yposition) - self.gpc.show(text) - - def write_heading (self, line, size=None, fontname=None, style=None, - indent=None, space_before=1, space_after=1): - if not size: size=self.default_head_size - if not fontname: fontname=self.default_head - if not style: style=self.default_head_style - if indent == None: indent=self.head_indent - self.set_font(fontname,size=16,style=style) - if self.yposition <= self.lheight * 3: - # start a new page if we're within three lines - # of the bottom - self.new_page() - if self.yposition < self.top and space_before: - # give us space before if we're not at the top - # of the page. - self.move_down(self.lheight * space_before) - self.write_paragraph(line, indent=indent) - if space_after: - self.move_down(self.lheight * space_after) - self.set_font() - - def write_paragraph (self, text, indent=0, space=False, - first_indent=0): - """first_indent is *relative* to indent.""" - words = text.split() - line = [] - n = 0 - linestr = "" - if space: - self.move_down(self.lheight) - first_line_flag = True - while n < len(words): - prev_line = linestr - linestr += " %s"%words[n] - lwidth = self.font.get_width_utf8(linestr) - # this is mildly hackish: custom wmargin only modifies - # our left margin, since this is what I'd usually want. - if first_line_flag: - length = self.right - self.left - indent - first_indent - else: - length = self.right - self.left - indent - if lwidth >= length: - # if we're over, we back up one... - if first_line_flag: - self.write_line(prev_line, indent=indent + first_indent) - first_line_flag = False - else: - self.write_line(prev_line, indent=indent) - linestr=words[n] - n += 1 - if first_line_flag: - indent = indent + first_indent - self.write_line(linestr, indent=indent) - - def new_page (self): - if self.n > 0: - self.gpc.showpage() - self.n += 1 - self.gpc.beginpage("%s"%self.n) - self.yposition = self.top - - def move_down (self, amt): - """ Move position down """ - self.yposition = self.yposition - amt - # we allow functions to act on the position each time we - # move down. This allows us to handle things like embedded - # images and columns. - if self.move_down_hooks: - for f in self.move_down_hooks: - f(self.yposition) - if self.yposition <= self.margin: - self.new_page() - -def show_preview(dialog,job): - #job = gnomeprint.Job(dialog.get_config()) - #render_to_job(job) - w = gnomeprint.ui.JobPreview(job, "Print Preview") - w.set_property('allow-grow', 1) - w.set_property('allow-shrink', 1) - w.set_transient_for(dialog) - w.show_all() - w.present() - -def print_dialog_response(dialog, resp, job): - if resp == gnomeprint.ui.DIALOG_RESPONSE_PREVIEW: - show_preview(dialog,job) - elif resp == gnomeprint.ui.DIALOG_RESPONSE_CANCEL: - dialog.destroy() - elif resp == gnomeprint.ui.DIALOG_RESPONSE_PRINT: - do_print(dialog, job) - dialog.destroy() - -def render_to_job (job): - r = renderer(job) - for f in ['Sans','Serif','Monospace','Arial']: - for s in [12,14,16,18,24]: - for sty in ['Regular','Bold','Italic']: - r.set_font(f,s,sty) - r.write_paragraph( "This is a paragraph in %s %s %s. "%(f,sty,s) * 5) - for i in xrange(10): - r.write_paragraph( "This is paragraph %s, indeed! "%i * 30 ) - for i in xrange(10): - r.write_paragraph( - "This is a paragraph that's not indented, and I have eaten a total of %s chocolate bars. "%i * 25, - indent=0, space=True - ) - r.end() - -class print_writer (renderer): - def __init__ (self, show_dialog=True, dialog_title=_("Print"), dialog_kwargs={}, - dialog_parent=None): - renderer.__init__(self) - self.show_dialog = show_dialog - self.dialog_parent = dialog_parent - self.dialog_title = dialog_title - self.dialog_kwargs = dialog_kwargs - - def write (self, text): - lines = text.split("\n") - if lines[-1]=='': - lines = lines[0:-1] - for l in lines: self.write_line(l) - - def close (self): - self.end() - if self.show_dialog: - dialog = gnomeprint.ui.Dialog(self.job, self.dialog_title, - gnomeprint.ui.DIALOG_RANGE | gnomeprint.ui.DIALOG_COPIES, - **self.dialog_kwargs) - flags = (gnomeprint.ui.RANGE_CURRENT - |gnomeprint.ui.RANGE_ALL - |gnomeprint.ui.RANGE_RANGE - |gnomeprint.ui.RANGE_SELECTION) - dialog.construct_range_page(flags, 1, 1, _("_Current"), _("_Range")) - dialog.connect('response', print_dialog_response, self.job) - if self.dialog_parent: dialog.set_transient_for(self.dialog_parent) - dialog.show() - -class RecRenderer (print_writer): - def __init__ (self, rd, recs, mult=1, dialog_title=_("Print Recipes"), - dialog_parent=None, change_units=True): - print_writer.__init__(self, show_dialog=True, dialog_title=dialog_title, - dialog_parent=dialog_parent) - do_new_page = False - for r in recs: - if do_new_page: - self.new_page() - r=RecWriter(rd, r, self, mult, change_units) - do_new_page = True # put pagebreaks between recipes... - self.close() - - -class RecWriter (exporter.exporter_mult): - def __init__ (self, rd, r, printwriter, change_units=True, mult=1): - self.print_writer = printwriter - self.r = r - exporter.exporter_mult.__init__(self, rd, r, None, - change_units=change_units, - mult=mult) - - def write_head (self): - pass - - def write_image (self, image): - pb = ImageExtras.get_pixbuf_from_jpg(image) - self.print_writer.write_pixbuf(pb, align='right') - - def write_attr (self, label, text): - attr=gglobals.NAME_TO_ATTR[label] - if attr=='title': - self.print_writer.write_heading(text) - return - self.print_writer.write_paragraph("%s: %s"%(label, text)) - - def write_text (self, label, text): - self.print_writer.write_heading(label, space_after=0, space_before=0.5) - pars = re.split("\n+", text) - for p in pars: self.print_writer.write_paragraph(p, space=True) - - def write_inghead (self): - self.print_writer.write_heading(_('Ingredients'), space_before=0.5, space_after=0) - - def write_grouphead (self, name): - self.print_writer.write_heading(name, - size=self.print_writer.default_head_size-2, - style='Regular', - indent=0, - space_before=0.5, - space_after=0) - - def write_ing (self, amount="1", unit=None, item=None, key=None, optional=False): - if amount: line = amt + " " - else: line = "" - if unit: line += "%s "%unit - if item: line += "%s"%item - if optional: line += " (%s)"%_("optional") - self.print_writer.write_paragraph(line) - -class SimpleWriter (print_writer): - def __init__ (self, file=None, dialog_parent=None, show_dialog=True): - print_writer.__init__(self,dialog_parent=dialog_parent,show_dialog=show_dialog) - - def write_header (self, text): - self.write_heading(text, size=14, space_before=0.5, space_after=0) - - def write_subheader (self, text): - self.write_heading(text, size=12, style="Regular", space_after=0, space_before=0.5) - -if __name__ == '__main__': - #dialog = show_print_dialog() - #dialog.connect("destroy", lambda *args: gtk.main_quit()) - #gtk.mainloop() - for do_this in range(2): - o = print_writer(show_dialog=True) - for h in range(10): - o.write_heading('Heading %s'%h, size=16+h, indent=None) - if (h/2) == float(h)/2: - if h > 5: align='right' - else: align='left' - else: align='center' - img = gtk.gdk.pixbuf_new_from_file("/tmp/gourmet_temporary_img.jpg") - o.write_pixbuf(img, align=align) - for n in range(15): - o.write_paragraph('This is job number %s. The is paragraph number %s. '%(do_this,n) * 10, first_indent=25) - o.close() - gtk.main() diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/exporters/gnomeprinter.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/exporters/gnomeprinter.py --- gourmet-0.15.1/src/lib/exporters/gnomeprinter.py 2009-05-20 01:48:57.000000000 +0100 +++ gourmet-0.15.2/src/lib/exporters/gnomeprinter.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,409 +0,0 @@ -import gtk, gnomeprint, gnomeprint.ui, re, pango -import exporter -from MarkupString import MarkupString -from gourmet import ImageExtras,gglobals,convert -from gourmet.gdebug import * -from gettext import gettext as _ -import xml.sax.saxutils - -def do_print(dialog, job): - debug('do_print',0) - pc = gnomeprint.Context(dialog.get_config()) - job.render(pc) - pc.close() - -class renderer: - def __init__ (self): - "Print Preview the document" - self.pn = 0 - self.config = gnomeprint.config_default() - self.job = gnomeprint.Job(self.config) - self.gpc = self.job.get_context() - self.setup_defaults() - self.setup_page() - self.move_down_hooks = [] - self.simple_escaper = re.compile("&(?=[^ ;]*($| ))") - - def escape (self, text): - pos = 0 - out = "" - for m in self.simple_escaper.finditer(text): - s=m.start() - e=m.end() - out += text[pos:s] - out += "&" - pos = e - out += text[pos:] - return out - - def end (self): - self.gpc.showpage() - self.job.close() - - def setup_defaults (self): - self.default_font='Serif' - self.default_head_family='Sans' - self.default_head_size=16 - self.default_head_style='normal' - self.default_head_weight='bold' - - def setup_page (self): - self.width,self.height = gnomeprint.job_get_page_size_from_config(self.job.get_config()) - self.margin = 50 - self.top = self.height - self.margin - self.bottom = self.margin - self.left = self.margin - self.right = self.width - self.margin - self.default_left = self.left - self.default_right = self.right - self.new_page() - - def new_page (self): - if self.pn > 0: - self.gpc.showpage() - self.pn += 1 - self.gpc.beginpage("%s"%self.pn) - self.pos = [self.left,self.top] - self.gpc.moveto(*self.pos) - #self.gpc.moveto(10,10) - #self.gpc.show("Page %s"%self.pn) - #self.gpc.moveto(*self.pos) - - def printBlock (self, markup): - paras = markup.split("\n") - for p in paras: self.printPara(p) - - def write_heading (self, line, - size=None, - font_family=None, - style=None, - weight=None, - indent=None, space_before=1, space_after=1): - if not size: size=self.default_head_size - if type(size)==int: - if size < 5000: size = size * 1000 # convenience, in case we typed a normal fontsize :) - if not font_family: font_family=self.default_head_family - if not style: style=self.default_head_style - if not weight: weight=self.default_head_weight - stag = ''%{ - 'size':size, - 'weight':weight, - 'family':font_family, - 'style':style - } - l = stag + line + '' - if space_before: - space_before = int(space_before+0.9) - l = "\n"*space_before + l - if space_after: - space_after = int(space_after+0.9) - l = l + "\n"*space_after - #self.write_paragraph('%s'%line,indent=indent) - self.write_paragraph(l,indent=indent) - - def write_paragraph (self, markup, indent=0, space=False, first_indent=0, force=False): - "Print some markup to the supplied context" - # first, we do a simple escape routine, just in case we're - # not actually being handed valid markup. Not fail-safe by - # any means, but should save us from the common "&"s that slip - # through - markup=self.escape(markup) - #need to use pango.Layout to format paragraphs - #for each block of text - paraContext = gnomeprint.pango_create_context(gnomeprint.pango_get_default_font_map()) - para = pango.Layout(paraContext) - para.set_wrap(pango.WRAP_WORD) - if first_indent: para.set_indent(int(first_indent)*pango.SCALE) - para.set_justify(True) - para.set_width(int(self.right-self.left)*pango.SCALE) - para.set_markup(markup) - x,y=para.get_size() - x = x/pango.SCALE - y = y/pango.SCALE - if space: y += 1 - #print 'paragraph of size ',x,y - botpos = self.pos[1] - y - #print 'moves bottom to ',botpos, ' bottom at %s'%self.bottom - if botpos < self.bottom and not force: - # running off the bottom of the page. In 2.6 we'll be able to handle this gracefully. - # in 2.4, we create a terrible, no-good, very bad hack. - # (right is tied to left-to-right languages...) and we're definitely tied to horizontal - # languages (left-to-right/right-to-left) in this whole routine. - room = self.pos[1]-self.bottom - shrink_by_percentage = float(room) / y - mymarkup = MarkupString(markup) - char = int(len(mymarkup.raw)*shrink_by_percentage) - # we automatically backup until we find a space. If there are no spaces, we fail. - try: - while mymarkup[char]!=" ": - char -= 1 - except IndexError: - char += 1 - startmark = mymarkup[:char] - endmark = mymarkup[char+1:] - #print 'breaking block into %s and endblock (length of %s)'%(startmark,len(endmark)) - self.write_paragraph(startmark,force=True) - self.new_page() - self.write_paragraph(endmark,indent=False) - else: - self.gpc.pango_layout(para) - #self.pos[1] = self.pos[1]-y - self.move_down(y) - #self.gpc.moveto(*self.pos) - - def move_down (self, amt): - self.pos[1]=self.pos[1] - amt - self.pos[0]=self.left - if self.move_down_hooks: - for f in self.move_down_hooks: - f(self.pos[1]) - if self.pos[1] <= self.bottom: - self.new_page() - self.gpc.moveto(*self.pos) - - def write_pixbuf (self, pixbuf, inline=True, align='left', border=10): - debug('write_pixbuf ',3) - """Align can take "left", "right", or "center". - "center" implies not inline.""" - raw_image = pixbuf.get_pixels() - has_alpha = pixbuf.get_has_alpha() - rowstride = pixbuf.get_rowstride() - height = pixbuf.get_height() - width = pixbuf.get_width() - # if we're not at the top, give us our border - if not self.pos[1] >= self.top: - self.move_down(border) - if (self.pos[1] - height) <= self.bottom: - self.new_page() - self.gpc.gsave() - if align=='left': - left = self.left - if align=='right': - left = self.right - width - if align=='center': - left = (self.width - width)/2 - self.gpc.translate(left,self.pos[1]-height) - self.gpc.moveto(left, self.pos[1]) - self.gpc.show('just moved into place!') - self.gpc.scale(width,height) - if has_alpha: self.gpc.rgbaimage(raw_image, width, height, rowstride) - else: self.gpc.rgbimage(raw_image, width, height, rowstride) - self.gpc.grestore() - #self.gpc.show('just restored') - # don't allow "inline" if our remaining width is less half - remaining_width = self.right - self.left - width -border - if remaining_width < 0.4 * width: - inline = False - if inline and align != 'center': - # we shift the left and right side to allow for our image - if align=='left': - self.left = self.left + width + border - else: # align=='right' - self.right = self.right - width - border - # we set up a hook to reset margins once we're beyond the image. - image_end_pos = self.pos[1] - def reset_margins (yposition): - debug('reset_margins ',3) - if yposition <= image_end_pos - (height + border): - self.left = self.default_left - self.right = self.default_right - self.move_down_hooks.remove(self.reset_margin_hook) - self.reset_margin_hook=reset_margins - self.pos[0]=self.left # shift ourselves into position - #self.gpc.moveto(*self.pos) - self.move_down_hooks.append(self.reset_margin_hook) - else: - self.move_down(height + border) - -def show_preview(dialog,job): - debug('show_preview',0) - #job = gnomeprint.Job(dialog.get_config()) - #render_to_job(job) - w = gnomeprint.ui.JobPreview(job, "Print Preview") - w.set_property('allow-grow', 1) - w.set_property('allow-shrink', 1) - w.set_transient_for(dialog) - w.show_all() - w.present() - -def print_dialog_response(dialog, resp, job): - debug('print_dialog_response',3) - if resp == gnomeprint.ui.DIALOG_RESPONSE_PREVIEW: - show_preview(dialog,job) - elif resp == gnomeprint.ui.DIALOG_RESPONSE_CANCEL: - dialog.destroy() - elif resp == gnomeprint.ui.DIALOG_RESPONSE_PRINT: - do_print(dialog, job) - dialog.destroy() - -def render_to_job (job): - debug('render_to_job ',3) - r = renderer(job) - for f in ['Sans','Serif','Monospace','Arial']: - for s in [12,14,16,18,24]: - for sty in ['normal','oblique','italic']: - r.set_font(f,s,sty) - r.write_paragraph( "This is a paragraph in %s %s %s. "%(f,sty,s) * 5) - for i in xrange(10): - r.write_paragraph( "This is paragraph %s, indeed! "%i * 30 ) - for i in xrange(10): - r.write_paragraph( - "This is a paragraph that's not indented, and I have eaten a total of %s chocolate bars. "%i * 25, - indent=0, space=True - ) - r.end() - -class print_writer (renderer): - def __init__ (self, show_dialog=True, dialog_title=_("Print"), dialog_kwargs={}, - dialog_parent=None): - debug('print_writer.__init__ ',3) - renderer.__init__(self) - self.show_dialog = show_dialog - self.dialog_parent = dialog_parent - self.dialog_title = dialog_title - self.dialog_kwargs = dialog_kwargs - - def close (self): - debug('close ',1) - self.end() - if self.show_dialog: - debug('preparing dialog',1) - dialog = gnomeprint.ui.Dialog(self.job, self.dialog_title, - gnomeprint.ui.DIALOG_RANGE | gnomeprint.ui.DIALOG_COPIES, - **self.dialog_kwargs) - debug('preparing dialog 2',1) - flags = (gnomeprint.ui.RANGE_CURRENT - |gnomeprint.ui.RANGE_ALL - |gnomeprint.ui.RANGE_RANGE - |gnomeprint.ui.RANGE_SELECTION) - debug('preparing dialog 3',1) - dialog.construct_range_page(flags, 1, 1, _("_Current"), _("_Range")) - dialog.connect('response', print_dialog_response, self.job) - if self.dialog_parent: dialog.set_transient_for(self.dialog_parent) - debug('showing dialog',1) - dialog.show() - debug('showed dialog',1) - -class RecRenderer (print_writer): - def __init__ (self, rd, recs, mult=1, dialog_title=_("Print Recipes"), - dialog_parent=None, change_units=True): - debug('RecRenderer.__init__ ',3) - print_writer.__init__(self, show_dialog=True, dialog_title=dialog_title, - dialog_parent=dialog_parent) - do_new_page = False - for r in recs: - if do_new_page: - self.new_page() - r=RecWriter(rd, r, self, change_units=change_units, mult=mult) - r.do_run() - do_new_page = True # put pagebreaks between recipes... - self.close() - - -class RecWriter (exporter.exporter_mult): - def __init__ (self, rd, r, printwriter, change_units=True, mult=1): - debug('__init__ rd=%s r=%s printwriter=%s change_units=%s mult=%s'%(rd,r,printwriter,change_units,mult),3) - self.print_writer = printwriter - self.r = r - exporter.exporter_mult.__init__(self, rd, r, out=None, change_units=change_units, mult=mult, - do_markup=False, - use_ml=True) - - def write_head (self): - debug('write_head ',3) - pass - - def write_image (self, image): - debug('write_image ',3) - pb = ImageExtras.get_pixbuf_from_jpg(image) - self.print_writer.write_pixbuf(pb, align='right') - - def write_attr (self, label, text): - debug('write_attr ',3) - attr=gglobals.NAME_TO_ATTR[label] - if attr=='title': - self.print_writer.write_heading(xml.sax.saxutils.escape(text)) - return - self.print_writer.write_paragraph(xml.sax.saxutils.escape("%s: %s"%(label, text))) - - def write_text (self, label, text): - debug('write_text ',3) - self.print_writer.write_heading(label, space_after=0, space_before=0.5) - pars = re.split("\n+", text) - for n,p in enumerate(pars): - if n==0: - self.print_writer.write_paragraph(p) - else: - self.print_writer.write_paragraph(p,first_indent=25) - - def write_inghead (self): - debug('write_inghead ',3) - self.print_writer.write_heading(xml.sax.saxutils.escape(_('Ingredients')), space_before=0.5, space_after=0) - - def write_grouphead (self, name): - debug('write_grouphead ',3) - self.print_writer.write_heading(xml.sax.saxutils.escape(name), - size=self.print_writer.default_head_size-2, - style='normal', - indent=0, - space_before=0.5, - space_after=0) - - def write_ing (self, amount="1", unit=None, item=None, key=None, optional=False): - debug('write_ing ',3) - if amount: line = amount + " " - else: line = "" - if unit: line += "%s "%unit - if item: line += "%s"%item - if optional: line += " (%s)"%_("optional") - self.print_writer.write_paragraph(xml.sax.saxutils.escape(line)) - -class SimpleWriter (print_writer): - def __init__ (self, file=None, dialog_parent=None, show_dialog=True): - debug('__init__ ',3) - print_writer.__init__(self,dialog_parent=dialog_parent,show_dialog=show_dialog) - - def write_header (self, text): - debug('write_header ',3) - self.dont_escape=True - self.write_heading(xml.sax.saxutils.escape(text), size=14, space_before=0.5, space_after=0) - self.dont_escape=False - - def write_subheader (self, text): - debug('write_subheader ',3) - self.dont_escape=True - try: - #print text - self.write_heading(xml.sax.saxutils.escape(text), - size=12, - style="normal", - space_after=0, - space_before=0.5) - except: - print 'Trouble printing "%s"'%text - raise - self.dont_escape=False - - def write_paragraph (self, text, *args, **kwargs): - if not self.dont_escape: text=xml.sax.saxutils.escape(text) - print_writer.write_paragraph(self,text,*args,**kwargs) - -if __name__ == '__main__': - #dialog = show_print_dialog() - #dialog.connect("destroy", lambda *args: gtk.main_quit()) - #gtk.mainloop() - for do_this in range(2): - o = print_writer(show_dialog=True) - for h in range(10): - o.write_heading('Heading %s'%h, size=16+h, indent=None) - if (h/2) == float(h)/2: - if h > 5: align='right' - else: align='left' - else: align='center' - #img = gtk.gdk.pixbuf_new_from_file("/tmp/gourmet_temporary_img.jpg") - #o.write_pixbuf(img, align=align) - for n in range(15): - o.write_paragraph('This is job number %s. The is paragraph number %s. '%(do_this,n) * 10, first_indent=25) - o.close() - gtk.threads_init() - gtk.main() diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/exporters/lprprinter.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/exporters/lprprinter.py --- gourmet-0.15.1/src/lib/exporters/lprprinter.py 2009-05-20 01:48:57.000000000 +0100 +++ gourmet-0.15.2/src/lib/exporters/lprprinter.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,60 +0,0 @@ -from gourmet.gtk_extras import dialog_extras as de -import exporter -import os -from gettext import gettext as _ - -class RecRenderer: - def __init__ (self, rd, recs, mult=1, dialog_title=_("Print Recipes"), - dialog_parent=None, change_units=True): - command = self.get_command(label='Enter print command', - sublabel='Please enter the command you would like to use to print.', - default_value='lpr') - # TO TEST LOUSY COMMAND-ENTERING CODE, UNCOMMENT THE FOLLOWING - #command = 'asdf' - while os.system('which %s'%command.split()[0]) != 0: - label = _("Enter print command") - sublabel = _("Unable to find command \"%s\".")%command - sublabel += _('Please enter the command you would like to use to print.') - command=self.get_command(label=_('Enter print command'), - sublabel=label) - lpr = os.popen(command,'w') - de.show_message( - label=_('Printing via %s')%command, - sublabel=_('If you install python-gnome, you will be able to print with a much more attractive interface.')) - for r in recs: - exporter.exporter_mult(rd, r, out=lpr,mult=mult,change_units=change_units) - lpr.close() - - def get_command (self, label="",sublabel="",default_value=None): - cmd = de.getEntry(label=label, - sublabel=sublabel, - entryLabel=_('Command:'), - default_value=default_value) - if not cmd: raise "User cancelled!" - else: return cmd - - -class SimpleWriter: - def __init__ (self, file=None, dialog_parent=None, show_dialog=True): - if file: - self.out = open(file,'w') - else: - self.out = os.popen('lpr','w') - if show_dialog: - de.show_message( - label='Printing via LPR', - sublabel='If you install python-gnome, you will be able to print with a much more attractive interface.') - - def write_header (self, text): - self.out.write("%s\n---\n"%text) - - def write_subheader (self, text): - self.out.write("\n\n%s\n---\n"%text) - - def write_paragraph (self, text): - self.out.write("%s\n"%text) - - def close (self): - self.out.close() - - diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/exporters/printer.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/exporters/printer.py --- gourmet-0.15.1/src/lib/exporters/printer.py 2009-05-20 01:48:57.000000000 +0100 +++ gourmet-0.15.2/src/lib/exporters/printer.py 2009-11-24 11:52:53.000000000 +0000 @@ -1,56 +1,93 @@ -from gourmet.gdebug import debug +from gettext import gettext as _ +import gettext +import gourmet.plugin_loader as plugin_loader +from gourmet.plugin import PrinterPlugin +from gourmet.threadManager import get_thread_manager, get_thread_manager_gui import os -# We grab the printer of choice and import methods from it. Each printer -# should provide a RecRenderer class which will do the actual printing. +class NoRecRenderer (): -def load_gnomeprint (): - try: - import gnomeprint - global RecRenderer,SimpleWriter - if hasattr(gnomeprint,'pango_create_context') and hasattr(gnomeprint,'pango_get_default_font_map'): - from gnomeprinter import RecRenderer, SimpleWriter - else: - # pre-pango gnomeprint - debug("Using out-of-date gnomeprint (no pango layout support in printing)",0) - from gnomeprinter_obsolete import RecRenderer, SimpleWriter - except ImportError: - debug('Gnome Printer is not available',0) - return True - -def load_winprinter (): - global RecRenderer,SimpleWriter - if os.name == 'nt': - from winprinter import RecRenderer, SimpleWriter - else: - return True + def __init__ (self, *args, **kwargs): + from gourmet.gtk_extras.dialog_extras import show_message + show_message(label=_('Unable to print: no print plugins are active!'), + sublabel=_("To print, activate a plugin that provides printing support, such as the 'Printing & PDF export' plugin."), + ) + raise NotImplementedError +class NoSimpleWriter (): -def load_lprprint (): - if os.name == 'nt': return True - global RecRenderer,SimpleWriter - from lprprinter import RecRenderer, SimpleWriter - - -printers = {'gnomeprint':load_gnomeprint, - 'win':load_winprinter, - 'lpr':load_lprprint} - -from gourmet.OptionParser import options - -printer_names = ['lpr','win','gnomeprint'] -printer = options.printer - -try: - printer_names.remove(printer) -except ValueError: - print 'Printer type: ',printer,' not recognized!' - printer = printer_names.pop() - -# A return value of True means we failed to import -# so we'd better keep trying -while printers[printer]() and printers: - print "Loading ",printer," failed:", - printer = printer_names.pop() - print "trying ",printer + def __init__ (self, *args, **kwargs): + from gourmet.gtk_extras.dialog_extras import show_message + show_message( + label=_('Unable to print: no print plugins are active!'), + sublabel=_("To print, activate a plugin that provides printing support, such as the 'Printing & PDF export' plugin."), + ) + raise NotImplementedError + +class PrintManager (plugin_loader.Pluggable): + + __single = None + + def __init__ (self): + if PrintManager.__single: + raise PrintManager.__single + else: + PrintManager.__single = self + self.sws = [(-1,NoSimpleWriter)] + self.rrs = [(-1,NoRecRenderer)] + plugin_loader.Pluggable.__init__(self, + [PrinterPlugin] + ) + + def register_plugin (self, plugin): + assert(type(plugin.simpleWriterPriority)==int) + assert(plugin.SimpleWriter) + self.sws.append((plugin.simpleWriterPriority,plugin.SimpleWriter)) + assert(type(plugin.recWriterPriority)==int) + assert(plugin.RecWriter) + self.rrs.append((plugin.recWriterPriority,plugin.RecWriter)) + + def unregister_plugin (self, plugin): + self.sws.remove(plugin.simpleWriterPriority,plugin.SimpleWriter) + self.rrs.remove(plugin.recWriterPriority,plugin.RecWriter) + + def get_simple_writer (self): + self.sws.sort() + return self.sws[-1][1] + + def get_rec_renderer (self): + self.rrs.sort() + return self.rrs[-1][1] + + def print_recipes (self, rd, recs, parent=None, change_units=None, **kwargs): + renderer = self.get_rec_renderer() + if len(recs) == 1: + title = 'Print recipe "%s"'%recs[0].title + else: + title = gettext.ngettext( + 'Print %s recipe', + 'Print %s recipes', + len(recs))%len(recs) + try: + renderer(rd,recs, + dialog_title=title, + dialog_parent=parent, + change_units=change_units, + **kwargs) + except: + from gourmet.gtk_extras.dialog_extras import show_traceback + show_traceback(label='Error printing', + sublabel=_('Well this is embarassing. Something went wrong printing your recipe.') + ) + + def show_error (self, *args): + from gourmet.gtk_extras.dialog_extras import show_message + show_message(sublabel='There was an error printing. Apologies') +def get_print_manager (): + try: + return PrintManager() + except PrintManager, pm: + return pm + +#printManager = get_print_manager() diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/exporters/winprinter.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/exporters/winprinter.py --- gourmet-0.15.1/src/lib/exporters/winprinter.py 2009-05-20 01:48:57.000000000 +0100 +++ gourmet-0.15.2/src/lib/exporters/winprinter.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,79 +0,0 @@ -import tempfile, gtk -from pdf_exporter import PdfWriter, PdfExporterMultiDoc, get_pdf_prefs - -from gettext import gettext as _ -from gettext import ngettext -import gourmet.gtk_extras.dialog_extras as de -import gourmet.gglobals as gglobals -from gourmet.convert import FRACTIONS_NORMAL -import exporter - -import win32api - - -def print_file_with_windows (filename): - # Method from: - # http://tgolden.sc.sabren.com/python/win32_how_do_i/print.html#shellexecute - if de.getBoolean(label=_('Print'), - sublabel=_('Ready to print your recipe through the PDF file %s. Unfortunately, we have no print preview - shall we go ahead and print?')%filename): - win32api.ShellExecute( - 0, - "print", - filename, - None, - ".", - 0 - ) - d = de.MessageDialog(label=_('Print job sent'), - sublabel=_("Print job has been sent. If something goes wrong, you can open the PDF file and try printing again.")) - else: - d = de.MessageDialog(label=_('Print job cancelled'), - sublabel=_("If you'd like, you can open the PDF file.") - ) - b = gtk.Button(stock=gtk.STOCK_JUMP_TO) - b.connect('clicked',lambda *args: gglobals.launch_url(filename)) - d.vbox.pack_end(b,expand=False); b.show() - d.run() - - -class RecRenderer: - def __init__ (self, rd, recs, mult=1, dialog_title=_("Print Recipes"), - dialog_parent=None, **kwargs): - filename = tempfile.mktemp('.pdf') - pdf_args = get_pdf_prefs() - kwargs['pdf_args']=pdf_args - e = PdfExporterMultiDoc(rd,recs,filename, **kwargs) - e.run() - print_file_with_windows(filename) - #show_disappointing_message() - #debug('printing not supported; showed dialog',0) - -class SimpleWriter (PdfWriter): - - def __init__ (self, file=None, dialog_parent=None, show_dialog=True): - self.filename = tempfile.mktemp('.pdf') - self.outfile = open(self.filename,'wb') - #PdfWriter.__init__(self) - self.setup_document(self.outfile, - **get_pdf_prefs({ - 'page_layout':(ngettext('%s Column','%s Columns',2)%2), - }) - ) - - def close (self): - PdfWriter.close(self) - self.outfile.close() - print_file_with_windows(self.filename) - -if __name__ == '__main__': - sw = SimpleWriter() - sw.write_header("This is a big heading") - sw.write_paragraph("""This is a paragraph. -This is perhaps a silly sort of paragraph to write, but I'm in the mood for silly paragraphs. -In fact, I'm in the mood for extraordinarily silly paragraphs. Paragraphs so silly they go on and on and on and on and (not being tired continuing) on and so forth until (by now the reader tiring) they take a sudden left turn, careening around the bend (passing colorless, sleeping, furious green ideas), plummetting downward (toward what or whom I don't know, whether or not there is a netherworld being among the many things, such as the existence of fairies, which escape my knowledge), falling fast and furious until hitting that final (cliched) rock bottom and returning upward. -This is my final paragraph.""") - sw.write_subheader("Foo") - sw.write_paragraph("This is the section named foo. "*12) - sw.write_subheader("Final Section") - sw.write_paragraph("And this is the final section." * 3) - sw.close() diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/GourmetRecipeManager.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/GourmetRecipeManager.py --- gourmet-0.15.1/src/lib/GourmetRecipeManager.py 2009-11-03 03:03:06.000000000 +0000 +++ gourmet-0.15.2/src/lib/GourmetRecipeManager.py 2009-12-01 01:39:48.000000000 +0000 @@ -4,7 +4,7 @@ import gtk.glade, gtk, gobject, gtk.gdk, traceback import batchEditor import recipeManager -import exporters.printer as printer +from exporters.printer import get_print_manager import prefs, prefsGui, shopgui, reccard, fnmatch, tempfile import exporters, importers from exporters.exportManager import get_export_manager @@ -206,7 +206,11 @@ # initiate autosave stuff autosave every 3 minutes # (milliseconds * 1000 milliseconds/second * 60 # seconds/minute) - gobject.timeout_add(1000*60*3,lambda *args: self.rd.save() or True) + def autosave (): + self.rd.save() + return True + AUTOSAVE_EACH_N_MINUTES = 2 + gobject.timeout_add(1000*60*AUTOSAVE_EACH_N_MINUTES,autosave) # connect hooks to modify our view whenever and # whenceever our recipes are updated... self.rd.modify_hooks.append(self.update_attribute_models) @@ -735,18 +739,13 @@ def print_recs (self, *args): debug('printing recipes',3) recs = self.get_selected_recs_from_rec_tree() - renderer = printer.RecRenderer(self.rd, recs, - dialog_title=gettext.ngettext('Print %s recipe', - 'Print %s recipes', - len(recs))%len(recs), - dialog_parent = self.app, - change_units = self.prefs.get('readableUnits',True) - ) - #tm = get_thread_manager() - #tmg = get_thread_manager_gui() - #tm.add_thread(renderer) - #tmg.register_thread_with_dialog(_('Print recipes'),renderer) - #tmg.show() + printManager = get_print_manager() + printManager.print_recipes( + self.rd, + recs, + parent=self.app, + change_units=self.prefs.get('readableUnits',True) + ) def import_webpageg (self, *args): self.importManager.offer_web_import(parent=self.app.get_toplevel()) @@ -1011,9 +1010,23 @@ tab_label=gtk.Label(_('Search recipes'))) self.main.add(self.main_notebook) self.recipe_index_interface.show() + self.main_notebook.show(); self.main_notebook.set_show_tabs(False) + + # Set up right-clicking again + self.rectree.connect('popup-menu',self.rectree_popup) + def popcb (tv, event): + if event.button==3: + self.rectree_popup(tv,event) + return True + self.rectree.connect('button-press-event',popcb) self.main.show() + def rectree_popup (self, tv, event, *args): + menu = self.ui_manager.get_widget("/RecipeIndexMenuBar/Actions/").get_submenu() + menu.popup(None,None,None,event.button,event.time) + return True + def setup_actions (self): self.ui_manager = gtk.UIManager() self.ui_manager.add_ui_from_string(ui) diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/gtk_extras/optionTable.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/gtk_extras/optionTable.py --- gourmet-0.15.1/src/lib/gtk_extras/optionTable.py 2009-05-20 01:48:57.000000000 +0100 +++ gourmet-0.15.2/src/lib/gtk_extras/optionTable.py 2009-11-22 16:09:46.000000000 +0000 @@ -1,6 +1,25 @@ #!/usr/bin/env python import gtk, cb_extras, gobject +class CustomOption (gtk.HBox): + + __gsignals__ = { + 'changed':(gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + []), + } + + def __init__ (self): + gobject.GObject.__init__(self) + gtk.HBox.__init__(self) + raise NotImplementedError + + def get_value (self): + raise NotImplementedError + + def set_value (self, val): + raise NotImplementedError + class OptionTable (gtk.Table): __gsignals__ = { @@ -18,8 +37,6 @@ self.ypadding = ypadding self.option_label=option_label self.value_label=value_label - # if pygtk let me emit a signal, I'd just emit a changed signal for any change. - # but since it doesn't, I let you connect a function by binding changedcb self.changedcb=changedcb cols = 2 rows = len(self.options) @@ -51,7 +68,11 @@ xoptions=gtk.SHRINK, yoptions=gtk.SHRINK) lab.show() for l,v in self.options: - if type(v)==type(True): + if isinstance(v,CustomOption): + w = v + self.widgets.append([v,'get_value','set_value']) + v.connect('changed',lambda * args: self.emit('changed')) + elif type(v)==type(True): w=gtk.CheckButton() w.set_active(v) # widgets contains the widget, the get method and the set method @@ -67,7 +88,7 @@ if self.changedcb: w.connect('changed',self.changedcb) elif type(v)==type(1) or type(v)==type(float(1)): - adj = gtk.Adjustment(value=0, lower=0, upper=100*v, step_incr=v*0.1, page_incr=v*0.5) + adj = gtk.Adjustment(value=0, lower=0, upper=100*(v or 1), step_incr=(v or 1)*0.1, page_incr=(v or 1)*0.5) if type(v)==type(1): # if an integer... w=gtk.SpinButton(adj, digits=0) diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/importers/importer.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/importers/importer.py --- gourmet-0.15.1/src/lib/importers/importer.py 2009-07-15 04:29:25.000000000 +0100 +++ gourmet-0.15.2/src/lib/importers/importer.py 2009-12-12 02:07:05.000000000 +0000 @@ -164,7 +164,7 @@ timeaction = TimeAction('importer.commit_rec',10) for key in ['cuisine','category','title']: if self.rec.has_key(key): - self.rec[key]=re.sub('\s+',' ',self.rec[key]).strip() + self.rec[key]=unicode(re.sub('\s+',' ',self.rec[key]).strip()) # if yields/servings can't be recognized as a number, add them # to the instructions. if self.rec.has_key('yields'): diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/importers/importManager.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/importers/importManager.py --- gourmet-0.15.1/src/lib/importers/importManager.py 2009-08-13 17:02:52.000000000 +0100 +++ gourmet-0.15.2/src/lib/importers/importManager.py 2009-12-02 12:09:33.000000000 +0000 @@ -99,6 +99,7 @@ }, ) else: + print 'Doing import of',reader.url,plugin self.do_import(plugin,'get_web_importer',reader.url,reader.data,reader.content_type) def offer_import (self, parent=None): diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/plugin_loader.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/plugin_loader.py --- gourmet-0.15.1/src/lib/plugin_loader.py 2009-07-16 03:20:38.000000000 +0100 +++ gourmet-0.15.2/src/lib/plugin_loader.py 2009-11-30 11:55:27.000000000 +0000 @@ -169,7 +169,7 @@ self.active_plugin_sets.remove(plugin_set.module) else: print 'Odd',plugin_set.module,'is not listed as active.' - if plugin.get_module(): + if plugin_set.get_module(): for plugin in plugin_set.plugins: if self.instantiated_plugins.has_key(plugin): self.instantiated_plugins[plugin].remove() @@ -194,9 +194,10 @@ try: plugin_instance = self.get_instantiated_plugin(p) except: + import traceback print 'WARNING: Failed to instantiate plugin %s of type %s'%(p,klass) self.errors[p] = traceback.format_exc() - import traceback; traceback.print_exc() + traceback.print_exc() else: #print 'Instantiating plugin',p,plugin_instance,'of',klass pluggable.plugin_plugin(plugin_instance) diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/plugin.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/plugin.py --- gourmet-0.15.1/src/lib/plugin.py 2009-11-03 03:03:07.000000000 +0000 +++ gourmet-0.15.2/src/lib/plugin.py 2009-11-30 11:55:27.000000000 +0000 @@ -149,9 +149,15 @@ for hook in self.hooks_to_add: pluggable.add_hook(*hook) + def remove (self): + for hook in self.hooks_to_add: + self.pluggable.remove_hook(*hook) + self.pluggable.plugins.remove(self) + def add_field (self, field_name, field_fetcher, type, - position=plugin_loader.POST): + position=plugin_loader.POST, + write_empty_field=False): '''Add a text field to our export. field_name is the name of the field. @@ -164,6 +170,10 @@ position is either PRE or POST -- whether we come before or after other text fields. + + if write_empty_field is True, we will write the field + regardless of the value. Otherwise, non-True (i.e. blank) + values will not print. ''' if type==self.TEXT: def do_write (*args): @@ -176,7 +186,7 @@ if klass.do_markup: val = klass.handle_markup(val) if not val: val = '' - if klass.ALLOW_PLUGINS_TO_WRITE_NEW_FIELDS: + if klass.ALLOW_PLUGINS_TO_WRITE_NEW_FIELDS and (val or write_empty_field): klass.write_text(field_name,val) self.hooks_to_add.append((position,'_write_text_',do_write)) else: @@ -189,7 +199,7 @@ val = field_fetcher(klass.r) if klass.do_markup: val = klass.handle_markup(val) - if klass.ALLOW_PLUGINS_TO_WRITE_NEW_FIELDS: + if klass.ALLOW_PLUGINS_TO_WRITE_NEW_FIELDS and (val or write_empty_field): klass.write_attr(field_name,val) self.hooks_to_add.append((position,'_write_attrs_',do_write)) @@ -232,8 +242,8 @@ db.add_hook(plugin_loader.POST,'setup_tables',self.create_tables) self.active = True - def deactivate (self, db): - db.remove_hook(plugin_loader.POST,'setup_tables',self.create_tables) + def remove (self): + self.db.remove_hook(plugin_loader.POST,'setup_tables',self.create_tables) self.active = False def create_tables (self): @@ -530,3 +540,56 @@ def __init__ (self): UIPlugin.__init__(self) + + +class PrinterPlugin (StandardPlugin): + + # SimpleWriter class + SimpleWriter = None + # how good this printer is (0 = use it if nothing else is there, + # and up from there) + simpleWriterPriority = -2 + RecWriter = None # RecWriter class + recWriterPriority = -2 + pass + + def activate (self, pluggable): + pluggable.register_plugin(self) + + def deactivate (self, pluggable): + pluggable.unregister_plugin(self) + +class PrefsPlugin (StandardPlugin): + + '''Add a tab to the preferences notebook. + + Pretty much all of the handling is offloaded to the widget you add. + + If you want to handle applying using the prefsGui system, you can do it with... + + self.prefsGui.apply_prefs_dic['prefname']=function + + where function takes then name and value of the preference as its arguments. + ''' + + label = None + widget = None + + def activate (self, pluggable): + self.prefsGui = pluggable + self.notebook = pluggable.notebook + if self.label and self.widget: + self.page_no = self.notebook.append_page(self.widget,tab_label=gtk.Label(self.label)) + self.widget.show() + + def deactivate (self, pluggable): + self.notebook = None + self.prefsGui = None + + def remove (self): + if self.notebook: + self.notebook.remove_page(self.page_no) + + def set_pref (self, name, value): + self.prefsGui.set_pref(name,value) + diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/plugins/check_for_unicode_16/__init__.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/plugins/check_for_unicode_16/__init__.py --- gourmet-0.15.1/src/lib/plugins/check_for_unicode_16/__init__.py 1970-01-01 01:00:00.000000000 +0100 +++ gourmet-0.15.2/src/lib/plugins/check_for_unicode_16/__init__.py 2009-12-15 01:34:01.000000000 +0000 @@ -0,0 +1,13 @@ +from gourmet.plugin import ToolPlugin +from gourmet.prefs import get_prefs + +class EnableUTF16Plugin (ToolPlugin): + ui = '' + + def activate (self, pluggable): + get_prefs()['utf-16'] = True + + def remove (self): + get_prefs()['utf-16'] = False + +plugins = [EnableUTF16Plugin] diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/plugins/import_export/pdf.gourmet-plugin /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/plugins/import_export/pdf.gourmet-plugin --- gourmet-0.15.1/src/lib/plugins/import_export/pdf.gourmet-plugin 2009-06-05 03:02:49.000000000 +0100 +++ gourmet-0.15.2/src/lib/plugins/import_export/pdf.gourmet-plugin 2009-11-20 02:44:12.000000000 +0000 @@ -2,7 +2,7 @@ Module = pdf_plugin Version = 1.0 API_Version = 1.0 -_Name = PDF Export -_Comment = Export recipes as PDF; this plugin allows a variety of page layouts. +_Name = Printing & PDF Export +_Comment = Print recipes or export them as PDF; this plugin allows a variety of page layouts. _Category = Importer/Exporter Authors = Thomas M. Hinkle \ No newline at end of file diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/plugins/import_export/pdf.gourmet-plugin.in /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/plugins/import_export/pdf.gourmet-plugin.in --- gourmet-0.15.1/src/lib/plugins/import_export/pdf.gourmet-plugin.in 2009-05-20 01:48:57.000000000 +0100 +++ gourmet-0.15.2/src/lib/plugins/import_export/pdf.gourmet-plugin.in 2009-11-20 02:44:08.000000000 +0000 @@ -2,7 +2,7 @@ Module = pdf_plugin Version = 1.0 API_Version = 1.0 -_Name = PDF Export -_Comment = Export recipes as PDF; this plugin allows a variety of page layouts. +_Name = Printing & PDF Export +_Comment = Print recipes or export them as PDF; this plugin allows a variety of page layouts. _Category = Importer/Exporter Authors = Thomas M. Hinkle \ No newline at end of file diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/plugins/import_export/pdf_plugin/__init__.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/plugins/import_export/pdf_plugin/__init__.py --- gourmet-0.15.1/src/lib/plugins/import_export/pdf_plugin/__init__.py 2009-05-20 01:48:57.000000000 +0100 +++ gourmet-0.15.2/src/lib/plugins/import_export/pdf_plugin/__init__.py 2009-11-17 02:13:48.000000000 +0000 @@ -1,2 +1,4 @@ -import pdf_exporter_plugin -plugins = [pdf_exporter_plugin.PdfExporterPlugin] +import pdf_exporter_plugin,print_plugin +plugins = [pdf_exporter_plugin.PdfExporterPlugin, + print_plugin.PDFPrintPlugin + ] diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/plugins/import_export/pdf_plugin/pdf_exporter.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/plugins/import_export/pdf_plugin/pdf_exporter.py --- gourmet-0.15.1/src/lib/plugins/import_export/pdf_plugin/pdf_exporter.py 2009-11-05 03:19:43.000000000 +0000 +++ gourmet-0.15.2/src/lib/plugins/import_export/pdf_plugin/pdf_exporter.py 2009-11-22 16:24:06.000000000 +0000 @@ -1,4 +1,4 @@ -import gtk +import gtk, gobject import reportlab from reportlab.pdfbase import pdfmetrics from reportlab.lib.units import inch,mm @@ -15,7 +15,9 @@ from gourmet import gglobals from gourmet.gtk_extras import dialog_extras as de from gourmet.gtk_extras import optionTable +from gourmet.gtk_extras import cb_extras from gourmet import ImageExtras +from gourmet.prefs import get_prefs import xml.sax.saxutils import gourmet.exporters.exporter as exporter import types, re @@ -25,7 +27,7 @@ PASS_REPORTLAB_UNICODE = (reportlab.Version.find('2')==0) -DEFAULT_PDF_ARGS = {'bottom_margin': 72.0, 'pagesize': 'letter', 'right_margin': 72.0, 'top_margin': 72.0, 'left_margin': 72.0, 'pagemode': 'portrait', 'base_font_size': 10.0, 'mode': ('column', 1)} +DEFAULT_PDF_ARGS = {'bottom_margin': 72, 'pagesize': 'letter', 'right_margin': 72, 'top_margin': 72, 'left_margin': 72, 'pagemode': 'portrait', 'base_font_size': 10, 'mode': ('column', 1)} # Code for MCLine from: # http://two.pairlist.net/pipermail/reportlab-users/2005-February/003695.html @@ -212,7 +214,7 @@ class PdfWriter: - def __init__ (self): + def __init__ (self, allrecs=[]): pass def setup_document (self, file, mode=('column',1), size='default', pagesize='letter', @@ -399,9 +401,9 @@ styleSheet=None, txt=[], pdf_args=DEFAULT_PDF_ARGS, + all_recipes=[], # For learning about references... **kwargs): - self.links = [] # Keep track of what recipes we link to to - # make sure we use them... + self.all_recipes = all_recipes PdfWriter.__init__(self) if type(out) in types.StringTypes: self.out = file(out,'wb') @@ -631,32 +633,27 @@ ) def write_ingref (self, amount, unit, item, refid, optional): - reffed = self.rd.get_rec(refid) - if not reffed: - reffed = self.rd.fetch_one(self.rd.recipe_table,title=item,deleted=False) - if reffed: - refid = reffed.id - if not reffed: + if refid in [r.id for r in self.all_recipes]: + txt = "" + for blob in [amount,unit,item,(optional and _('optional') or '')]: + if blob == item: + blob = ''%refid + blob + '' + elif not blob: + continue + if txt: txt += " %s"%blob + else: txt = blob + hanging = inch*0.25 + self.write_paragraph( + txt, + attributes=' firstLineIndent="-%(hanging)s" leftIndent="%(hanging)s"'%locals() + ) + else: return self.write_ing(amount,unit,item,optional=optional) - txt = "" - for blob in [amount,unit,item,(optional and _('optional') or '')]: - if blob == item: - blob = ''%refid + blob + '' - if not blob: continue - if txt: txt += " %s"%blob - else: txt = blob - hanging = inch*0.25 - self.links.append(refid) - self.write_paragraph( - txt, - attributes=' firstLineIndent="-%(hanging)s" leftIndent="%(hanging)s"'%locals() - ) class PdfExporterMultiDoc (exporter.ExporterMultirec, PdfWriter): def __init__ (self, rd, recipes, out, progress_func=None, conv=None, pdf_args=DEFAULT_PDF_ARGS, **kwargs): - self.links = [] PdfWriter.__init__(self) if type(out) in types.StringTypes: out = file(out,'wb') @@ -666,6 +663,7 @@ kwargs['styleSheet'] = self.styleSheet kwargs['txt'] = self.txt kwargs['pdf_args'] = pdf_args + kwargs['all_recipes']=recipes exporter.ExporterMultirec.__init__( self, rd, recipes, out, @@ -709,14 +707,110 @@ PDF_PREF_DEFAULT={ 'page_size':_('Letter'), 'orientation':_('Portrait'), - 'font_size':10.0, + 'font_size':10, 'page_layout':_('Plain'), - 'left_margin':1.0, - 'right_margin':1.0, - 'top_margin':1.0, - 'bottom_margin':1.0, + 'left_margin':1.0*inch, + 'right_margin':1.0*inch, + 'top_margin':1.0*inch, + 'bottom_margin':1.0*inch, } +class CustomUnitOption (optionTable.CustomOption): + + '''An option for optionTable with adjustable units -- used for margins. + ''' + + units = { + '"':inch, + _('cm'):10*mm, + _('points'):1, + } + + min_val = 0.125*inch + max_val = 8*inch + + adjustments = { + inch:(0.125,0.5), + 10*mm:(0.5,1), + 1:(5,25), + } + + def __init__ (self, default_value = inch): + gobject.GObject.__init__(self) + gtk.HBox.__init__(self) + self.__quiet__ = False + self.unit_combo = gtk.combo_box_new_text() + for key in self.units: + self.unit_combo.append_text(key) + unit = get_prefs().get('default_margin_unit',_('cm')) + if unit not in self.units: unit = _('cm') + self.last_unit = self.units[unit] + cb_extras.setup_typeahead(self.unit_combo) + cb_extras.cb_set_active_text(self.unit_combo,unit) + self.unit_combo.connect('changed',self.unit_changed_cb) + self.value_adjustment = gtk.Adjustment( + value=self.adjust_to_unit(default_value), + lower= self.min_val / self.last_unit, + upper = self.max_val / self.last_unit, + step_incr = self.adjustments[self.last_unit][0], + page_incr = self.adjustments[self.last_unit][1], + ) + def emit_changed (*args): + self.emit('changed') + self.value_adjustment.connect('changed',emit_changed) + self.value_widget = gtk.SpinButton(self.value_adjustment,digits=2) + self.value_widget.connect('changed',emit_changed) + self.value_widget.show(); self.unit_combo.show() + self.pack_start(self.value_widget) + self.pack_start(self.unit_combo) + + def set_unit (self, unit): + cb_extras.cb_set_active_text(self.unit_combo,unit) + + def unit_changed_cb (self, widget): + new_unit = self.units[self.unit_combo.get_active_text()] + get_prefs()['default_margin_unit'] = self.unit_combo.get_active_text() + old_val = self.value_adjustment.get_value() * self.last_unit + self.last_unit = self.units[self.unit_combo.get_active_text()] + new_val = self.adjust_to_unit(old_val) + self.value_adjustment.set_upper(self.max_val / self.last_unit) + self.value_adjustment.set_lower(self.min_val / self.last_unit) + self.value_adjustment.set_step_increment(self.adjustments[self.last_unit][0]) + self.value_adjustment.set_page_increment(self.adjustments[self.last_unit][1]) + self.value_adjustment.set_value(new_val) + if not self.__quiet__: + self.emit('changed') + + def adjust_to_unit (self, raw_val): + '''Round the value to an appropriate number for our current + unit + ''' + val = raw_val / self.last_unit + adj = self.adjustments[self.last_unit][0] + # "Round" to the increment adjustment specified for our unit + floor = int(val/adj) * adj + ceiling = (int(val/adj)+1) * adj + # Pick whatever is closest... + if abs(floor - val) > abs(ceiling - val): + return ceiling + else: + return floor + + def get_value (self): + return self.last_unit * self.value_adjustment.get_value() + + def set_value (self, value): + self.value_adjustment.set_value(value/self.last_unit) + if not self.__quiet__: + self.emit('changed') + + def sync_to_other_cuo (self, cuo): + def change_cb (other_cuo): + self.__quiet__ = True + self.set_unit(other_cuo.unit_combo.get_active_text()) + self.__quiet__ = False + cuo.connect('changed',change_cb) + class PdfPrefGetter: page_sizes = { _('11x17"'):'elevenSeventeen', @@ -748,32 +842,41 @@ } OPT_PS,OPT_PO,OPT_FS,OPT_PL,OPT_LM,OPT_RM,OPT_TM,OPT_BM = range(8) - - def __init__ (self, defaults=PDF_PREF_DEFAULT): + + def __init__ (self,): + self.prefs = get_prefs() + defaults = self.prefs.get('PDF_EXP',PDF_PREF_DEFAULT) self.size_strings = self.page_sizes.keys() self.size_strings.sort() for n in range(2,5): self.layouts[ngettext('%s Column','%s Columns',n)%n]=('column',n) + self.make_reverse_dicts() self.layout_strings = self.layouts.keys() self.layout_strings.sort() + margin_widgets = [ + CustomUnitOption(defaults.get(pref,PDF_PREF_DEFAULT[pref])) + for pref in ['left_margin','right_margin','top_margin','bottom_margin'] + ] + # Make unit changes to one widget affect all the others! + for m in margin_widgets: + for mm in margin_widgets: + if mm is not m: + m.sync_to_other_cuo(mm) + self.opts = [ [_('Paper _Size')+':',(defaults.get('page_size',PDF_PREF_DEFAULT['page_size']), self.size_strings)], [_('_Orientation')+':',(defaults.get('orientation',PDF_PREF_DEFAULT['orientation']), self.page_modes.keys())], - [_('_Font Size')+':',defaults.get('font_size',PDF_PREF_DEFAULT['font_size'])] + [_('_Font Size')+':',int(defaults.get('font_size',PDF_PREF_DEFAULT['font_size']))] , [_('Page _Layout'),(defaults.get('page_layout',PDF_PREF_DEFAULT['page_layout']), self.layout_strings)], - [_('Left Margin')+':',defaults.get('left_margin',PDF_PREF_DEFAULT['left_margin'])] - , - [_('Right Margin')+':',defaults.get('right_margin',PDF_PREF_DEFAULT['right_margin'])] - , - [_('Top Margin')+':',defaults.get('top_margin',PDF_PREF_DEFAULT['top_margin'])] - , - [_('Bottom Margin')+':',defaults.get('bottom_margin',PDF_PREF_DEFAULT['bottom_margin'])] - , + [_('Left Margin')+':',margin_widgets[0]], + [_('Right Margin')+':',margin_widgets[1]], + [_('Top Margin')+':',margin_widgets[2]], + [_('Bottom Margin')+':',margin_widgets[3]], ] self.page_drawer = PdfPageDrawer(yalign=0.0) @@ -784,6 +887,14 @@ self.page_drawer.set_size_request(200,100) self.page_drawer.show() + def make_reverse_dicts (self): + self.page_sizes_r = {}; self.layouts_r = {}; self.page_modes_r = {} + for dict,dict_r in [ + (self.page_sizes,self.page_sizes_r), + (self.layouts,self.layouts_r), + (self.page_modes,self.page_modes_r)]: + for k,v in dict.items(): dict_r[v]=k + def setup_widgets (self): self.pd = de.PreferencesDialog(self.opts,option_label=None,value_label=None, label='PDF Options', @@ -797,14 +908,20 @@ def get_args_from_opts (self, opts): args = {} - args['pagesize']=self.page_sizes[opts[self.OPT_PS][1]] # PAGE SIZE - args['pagemode']=self.page_modes[opts[self.OPT_PO][1]] # PAGE MODE - args['base_font_size']=opts[self.OPT_FS][1] # FONT SIZE - args['mode']=self.layouts[opts[self.OPT_PL][1]] # LAYOUT/MODE - args['left_margin']=opts[self.OPT_LM][1]*inch - args['right_margin']=opts[self.OPT_RM][1]*inch - args['top_margin']=opts[self.OPT_TM][1]*inch - args['bottom_margin']=opts[self.OPT_BM][1]*inch + if not get_prefs().has_key('PDF_EXP'): + get_prefs()['PDF_EXP'] = {} + prefs = get_prefs()['PDF_EXP'] + args['pagesize'] = self.page_sizes[opts[self.OPT_PS][1]] # PAGE SIZE + prefs['page_size'] = self.page_sizes_r[args['pagesize']] + args['pagemode'] = self.page_modes[opts[self.OPT_PO][1]] # PAGE MODE + prefs['orientation'] = self.page_modes_r[args['pagemode']] + prefs['font_size'] = args['base_font_size'] = opts[self.OPT_FS][1] # FONT SIZE + args['mode'] = self.layouts[opts[self.OPT_PL][1]] # LAYOUT/MODE + prefs['page_layout'] = self.layouts_r[args['mode']] + prefs['left_margin'] = args['left_margin'] = opts[self.OPT_LM][1] + prefs['right_margin'] = args['right_margin'] = opts[self.OPT_RM][1] + prefs['top_margin'] = args['top_margin'] = opts[self.OPT_TM][1] + prefs['bottom_margin'] = args['bottom_margin'] = opts[self.OPT_BM][1] return args def change_cb (self, option_table, *args,**kwargs): @@ -903,11 +1020,29 @@ self.widg.pack_start(self.page_drawer,fill=True,expand=True) self.widg.show_all() -def get_pdf_prefs (defaults=PDF_PREF_DEFAULT): - pdf_pref_getter = PdfPrefGetter(defaults=defaults) +def get_pdf_prefs (defaults=None): + if defaults: print 'WARNING: ignoring provided defaults and using prefs system instead' + pdf_pref_getter = PdfPrefGetter() return pdf_pref_getter.run() if __name__ == '__main__': + w = gtk.Window() + cuo = CustomUnitOption(44) + cuo2 = CustomUnitOption(98) + cuo.sync_to_other_cuo(cuo2) + cuo2.sync_to_other_cuo(cuo) + vb = gtk.VBox() + l = gtk.Label('Hello World') + vb.add(l) + vb.pack_start(cuo) + vb.pack_start(cuo2) + w.add(vb) + vb.show(); cuo.show(); cuo2.show() + w.show() + w.connect('delete_event',gtk.main_quit) + gtk.main() + raise 'Hell' + from tempfile import tempdir import os.path #opts = get_pdf_prefs(); print opts diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/plugins/import_export/pdf_plugin/print_plugin.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/plugins/import_export/pdf_plugin/print_plugin.py --- gourmet-0.15.1/src/lib/plugins/import_export/pdf_plugin/print_plugin.py 2009-11-05 03:27:47.000000000 +0000 +++ gourmet-0.15.2/src/lib/plugins/import_export/pdf_plugin/print_plugin.py 2009-11-22 02:07:46.000000000 +0000 @@ -5,33 +5,142 @@ import os.path import pdf_exporter import tempfile +import reportlab.lib.pagesizes as pagesizes +from gourmet.plugin import PrinterPlugin -class PDFPrinter: +rl2gtk_papersizes = { + tuple([int(round(s)) for s in pagesizes.letter]) : gtk.PAPER_NAME_LETTER, + tuple([int(round(s)) for s in pagesizes.legal]) : gtk.PAPER_NAME_LEGAL, + tuple([int(round(s)) for s in pagesizes.B5]):gtk.PAPER_NAME_B5, + tuple([int(round(s)) for s in pagesizes.A5]):gtk.PAPER_NAME_A5, + tuple([int(round(s)) for s in pagesizes.A4]):gtk.PAPER_NAME_A4, + tuple([int(round(s)) for s in pagesizes.A3]):gtk.PAPER_NAME_A3, + } - def __init__ (self, rd, recs): - self.rd = rd - self.recs = recs +class PDFPrinter: + def setup_printer (self, parent=None): + po = gtk.PrintOperation() + #po.set_n_pages(self.d.get_n_pages()) + po.connect('draw_page',self.draw_page) + po.connect('begin-print',self.begin_print) + po.connect('create-custom-widget',self.create_custom_widget) + po.props.custom_tab_label = _('Page Layout') + po.connect('custom-widget-apply',self.custom_widget_apply) + po.set_export_filename('/tmp/foo.pdf') + po.run(gtk.PRINT_OPERATION_ACTION_PRINT_DIALOG, parent=parent) + + def set_document (self, filename, operation,context): + if not filename.startswith('file'): + filename = 'file://' + os.path.realpath(filename) + self.d = poppler.document_new_from_file(filename,None) + operation.set_n_pages(self.d.get_n_pages()) + # Assume all pages are same + page = self.d.get_page(0) + w,h = page.get_size() + if w > h: + w,h = h,w + ori = gtk.PAGE_ORIENTATION_LANDSCAPE + else: + ori = gtk.PAGE_ORIENTATION_PORTRAIT + page_setup = gtk.PageSetup() + page_setup.set_orientation(ori) + size = int(round(w)),int(round(h)) + gtk_size = rl2gtk_papersizes.get(size,None) + if gtk_size: + ps = gtk.PaperSize(gtk_size) + else: + ps = gtk.paper_size_new_custom('','',w,h,gtk.UNIT_POINTS) + page_setup.set_paper_size(ps) + operation.set_default_page_setup(page_setup) + def draw_page (self,operation, context, page_num): page = self.d.get_page(page_num) + w,h = page.get_size() + #page_setup = context.get_page_setup() + #ps = gtk.paper_size_new_custom('','',w,h,gtk.UNIT_POINTS) + #page_setup.set_paper_size(ps) page.render_for_printing(context.get_cairo_context()) - def begin_print (self, operation, context): - fn = tempfile.mktemp() - pe = PdfExporterMultiDoc(self.rd,self.recs,fn,pdf_args=self.args) - pe.run() - self.d = poppler.document_new_from_file(fn,None) - def create_custom_widget (self, operation): - print 'create!' self.ppt = pdf_exporter.PdfPrefTable() + self.opts = self.ppt.opts + self.args = self.ppt.get_args_from_opts(self.opts) return self.ppt.widg - + def custom_widget_apply (self, operation, widget): - self.opts = self.ppt.opts - print self.opts self.args = self.ppt.get_args_from_opts(self.opts) +def record_args (func): + + def _ (self, *args, **kwargs): + self.export_commands.append( + (func.__name__,args,kwargs) + ) + return _ + +class PDFSimpleWriter (PDFPrinter): + + def __init__ (self, dialog_parent=None): + self.parent = dialog_parent + self.export_commands = [] + + @record_args + def write_header (self, *args, **kwargs): pass + + @record_args + def write_subheader (self, *args, **kwargs): pass + + @record_args + def write_paragraph (self, *args, **kwargs): pass + + def close (self, *args, **kwargs): + self.export_commands.append(('close',[],{})) + self.setup_printer(self.parent) + + def begin_print (self, operation, context): + fn = tempfile.mktemp() + writer = pdf_exporter.PdfWriter() + writer.setup_document(fn,**self.args) + # Playback all the commands we recorded + for commandname,args,kwargs in self.export_commands: + func = getattr(writer,commandname) + func(*args,**kwargs) + # And now we trust the documents been written... + self.set_document(fn,operation,context) + + +class PDFRecipePrinter (PDFPrinter): + + def __init__ (self, rd, recs, + mult=1, dialog_title=_('Print Recipes'), + dialog_parent=None, change_units=True): + self.printing_error = False + self.change_units = change_units + self.mult = mult + self.parent = dialog_parent + self.rd = rd + self.recs = recs + self.setup_printer(self.parent) + + def begin_print (self, operation, context): + fn = tempfile.mktemp() + pe = pdf_exporter.PdfExporterMultiDoc(self.rd,self.recs,fn,pdf_args=self.args, + change_units=self.change_units, mult=self.mult) + pe.connect('error',self.handle_error) + pe.run() + if self.printing_error: + print 'PRINTING ERROR!' + raise "There was an error generating PDF" + self.set_document(fn, operation,context) + + def handle_error (self,obj,errno, summary, traceback): + print 'There was an error generating a PDF to print.' + print summary + print traceback + self.printing_error = True + raise + def setup_printer (pp): po = gtk.PrintOperation() po.set_n_pages(pp.d.get_n_pages()) @@ -46,5 +155,24 @@ if not pdf_filename.startswith('file'): pdf_filename = 'file://' + os.path.realpath(pdf_filename) setup_printer(PDFPrinter(pdf_filename)) - -print_pdf('/home/tom/list.pdf') + +def test_simplewriter (): + pwriter = PDFSimpleWriter() + pwriter.write_header("TEST HEADER") + pwriter.write_subheader('Test subheading') + pwriter.write_paragraph('This is a test ' * 10) + pwriter.write_paragraph('This is a test ' * 15) + for n in range(3): + pwriter.write_subheader('Test subheading for time number %s'%(n+2)) + for i in range(5,(5*(n+1))): + pwriter.write_paragraph('So is this a test? Or is it. '*i) + pwriter.close() + +class PDFPrintPlugin (PrinterPlugin): + SimpleWriter = PDFSimpleWriter + simpleWriterPriority = 1 + RecWriter = PDFRecipePrinter + recWriterPriority = 1 + +if __name__ == '__main__': + test_simplewriter() diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/plugins/nutritional_information/export_plugin.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/plugins/nutritional_information/export_plugin.py --- gourmet-0.15.1/src/lib/plugins/nutritional_information/export_plugin.py 2009-06-18 11:05:23.000000000 +0100 +++ gourmet-0.15.2/src/lib/plugins/nutritional_information/export_plugin.py 2009-11-30 11:55:27.000000000 +0000 @@ -1,17 +1,22 @@ from gourmet.plugin import BaseExporterPlugin from gourmet.recipeManager import default_rec_manager +import gourmet.defaults +from gourmet.prefs import get_prefs from nutritionLabel import MAIN_NUT_LAYOUT, MAJOR, MINOR, TINY, SEP, SHOW_PERCENT, DONT_SHOW_PERCENT, SEP from gettext import gettext as _ +from xml.sax.saxutils import escape class NutritionBaseExporterPlugin (BaseExporterPlugin): def __init__ (self): BaseExporterPlugin.__init__(self) - self.add_field('Nutritional Information', - self.get_nutritional_info_as_text_blob, - self.TEXT) + if get_prefs().get('include_nutritional_info_in_export',True): + self.add_field('Nutritional Information', + self.get_nutritional_info_as_text_blob, + self.TEXT) def get_nutritional_info_as_text_blob (self, rec): + if not get_prefs().get('include_nutritional_info_in_export',True): return None txt = '' footnotes = '' rd = default_rec_manager() @@ -19,16 +24,20 @@ nutinfo = nd.get_nutinfo_for_inglist(rd.get_ings(rec),rd) ings = rd.get_ings(rec) vapor = nutinfo._get_vapor() + if len(vapor)==len(ings): return None + if len(vapor) >= 1 and not get_prefs().get('include_partial_nutritional_info',False): + return None if rec.yields and rec.yield_unit: - txt += '%s'%((rec.yields and _('Nutritional information reflects amount per %s.'%rec.yield_unit)) + singular_unit = gourmet.defaults.get_pluralized_form(rec.yield_unit,1) + txt += '%s'%((rec.yields and _('Nutritional information reflects amount per %s.'%singular_unit)) or _('Nutritional information reflects amounts for entire recipe')) - if len(vapor)==len(ings): return None + if vapor: txt = txt + '*' footnotes = '\n*' + _('Nutritional information is missing for %s ingredients: %s')%( len(vapor), - ', '.join([nv.__ingobject__.item for nv in vapor]) + ', '.join([escape(nv.__ingobject__.item) for nv in vapor]) ) for itm in MAIN_NUT_LAYOUT: if itm == SEP: diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/plugins/nutritional_information/__init__.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/plugins/nutritional_information/__init__.py --- gourmet-0.15.1/src/lib/plugins/nutritional_information/__init__.py 2009-05-20 01:48:57.000000000 +0100 +++ gourmet-0.15.2/src/lib/plugins/nutritional_information/__init__.py 2009-11-30 11:55:27.000000000 +0000 @@ -1,8 +1,10 @@ import data_plugin, main_plugin, reccard_plugin, export_plugin, shopping_plugin +import nutPrefsPlugin plugins = [ data_plugin.NutritionDataPlugin, main_plugin.NutritionMainPlugin, reccard_plugin.NutritionDisplayPlugin, export_plugin.NutritionBaseExporterPlugin, shopping_plugin.ShoppingNutritionalInfoPlugin, + nutPrefsPlugin.NutritionPrefs, ] diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/plugins/nutritional_information/nutPrefsPlugin.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/plugins/nutritional_information/nutPrefsPlugin.py --- gourmet-0.15.1/src/lib/plugins/nutritional_information/nutPrefsPlugin.py 1970-01-01 01:00:00.000000000 +0100 +++ gourmet-0.15.2/src/lib/plugins/nutritional_information/nutPrefsPlugin.py 2009-12-01 00:57:37.000000000 +0000 @@ -0,0 +1,39 @@ +from gourmet.plugin import PrefsPlugin +from gourmet.prefs import get_prefs +import gtk + +partialp = 'include_partial_nutritional_info' +includep = 'include_nutritional_info_in_export' + +class NutritionPrefs (PrefsPlugin): + + label = _("Nutritional Information") + + def __init__ (self, *args, **kwargs): + # Create main widget + self.widget = gtk.VBox() + self.prefs = get_prefs() + label = gtk.Label('Hello world') + self.include_tb = gtk.CheckButton('Include nutritional information in print-outs and exports') + self.partial_tb = gtk.CheckButton('Include partial nutritional information in print-outs and exports?') + self.include_tb.set_active(self.prefs.get(includep,True)) + self.partial_tb.set_active(self.prefs.get(partialp,False)) + self.include_tb.connect('toggled',self.toggle_cb) + self.partial_tb.connect('toggled',self.toggle_cb) + self.widget.pack_start(self.include_tb, expand=False, fill=False) + self.widget.pack_start(self.partial_tb, expand=False, fill=False) + self.widget.set_border_width(12) + self.widget.set_spacing(6) + self.widget.show_all() + + def toggle_cb (self, tb): + if tb==self.include_tb: + if tb.get_active(): + self.prefs[includep] = True + else: + self.prefs[includep] = False + # Force false... + self.partial_tb.set_active(False) + self.prefs[partialp] = False + if tb == self.partial_tb: + self.prefs[partialp] = tb.get_active() diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/plugins/nutritional_information/nutritionInfoEditor.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/plugins/nutritional_information/nutritionInfoEditor.py --- gourmet-0.15.1/src/lib/plugins/nutritional_information/nutritionInfoEditor.py 2009-05-20 01:48:57.000000000 +0100 +++ gourmet-0.15.2/src/lib/plugins/nutritional_information/nutritionInfoEditor.py 2009-11-20 11:48:37.000000000 +0000 @@ -1,4 +1,4 @@ -import gtk, gtk.glade, gobject +import gtk, gtk.glade, gobject, pango import gourmet.gtk_extras.pageable_store as pageable_store import gourmet.gglobals as gglobals import os, re @@ -87,7 +87,7 @@ except TypeError: pass else: - renderer.set_property('wrap-mode',gtk.WRAP_WORD) + renderer.set_property('wrap-mode',pango.WRAP_WORD) renderer.set_property('wrap-width',200) #if n==self.VALUE_COL: # renderer.set_property('editable',True) diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/plugins/nutritional_information/nutritionLabel.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/plugins/nutritional_information/nutritionLabel.py --- gourmet-0.15.1/src/lib/plugins/nutritional_information/nutritionLabel.py 2009-06-18 11:05:23.000000000 +0100 +++ gourmet-0.15.2/src/lib/plugins/nutritional_information/nutritionLabel.py 2009-11-20 11:31:05.000000000 +0000 @@ -1,5 +1,6 @@ import gtk, pango, gobject from gettext import gettext as _ +import gourmet.defaults MAJOR = 0 MINOR = 1 @@ -456,7 +457,8 @@ if self.custom_label: self.yieldLabel.set_markup(''+self.custom_label+'') elif self.yields: - self.yieldLabel.set_markup(''+_('Amount per %s'%self.yield_unit)+'') + singular_unit = gourmet.defaults.get_pluralized_form(self.yield_unit,1) + self.yieldLabel.set_markup(''+_('Amount per %s'%singular_unit)+'') else: self.yieldLabel.set_markup(''+_('Amount per recipe')+'') diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/plugins/nutritional_information/nutrition.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/plugins/nutritional_information/nutrition.py --- gourmet-0.15.1/src/lib/plugins/nutritional_information/nutrition.py 2009-05-20 01:48:57.000000000 +0100 +++ gourmet-0.15.2/src/lib/plugins/nutritional_information/nutrition.py 2009-12-03 04:00:00.000000000 +0000 @@ -613,10 +613,8 @@ print att,":",getattr(self.ings,att) vv = self.ings._get_vapor() if vv: - print '(but we have some vapor)' for v in vv: explanation = v._wheres_the_vapor() - print 'Vapor for ',v.__key__ if explanation==KEY_VAPOR: print 'No key' if explanation==UNIT_VAPOR: print "Can't handle unit ",v.__unit__ if explanation==AMOUNT_VAPOR: print "What am I to do with the amount ",v.__amt__ diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/plugins/nutritional_information/reccard_plugin.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/plugins/nutritional_information/reccard_plugin.py --- gourmet-0.15.1/src/lib/plugins/nutritional_information/reccard_plugin.py 2009-06-18 11:05:23.000000000 +0100 +++ gourmet-0.15.2/src/lib/plugins/nutritional_information/reccard_plugin.py 2009-12-01 01:41:50.000000000 +0000 @@ -17,7 +17,6 @@ _custom_handlers_setup = False def __init__ (self, recipe_display): - print 'Initialize NutritionDisplayModule for',recipe_display self.recipe_display = recipe_display self.nutritional_highlighting = True self.prefs = self.recipe_display.rg.prefs @@ -68,7 +67,11 @@ def enter_page (self): self.nutritional_highlighting = True if not self.nutritionLabel.active_name: - self.nutritionLabel.toggles[self.prefs.get('nutrition_to_highlight','kcal')].activate() + if self.prefs.get('nutrition_to_highlight','kcal') in self.nutritionLabel.toggles: + self.nutritionLabel.toggles[ + self.prefs.get( + 'nutrition_to_highlight','kcal') + ].activate() # Save what servings were and set them to "1" so that the # ingredient amounts display how much goes into each servings # (assuming there is a yield value) @@ -103,7 +106,7 @@ tot_amt = sum([getattr(self.nutinfo,p) or 0 for p in props]) if nut_amt: perc = float(nut_amt)/tot_amt - if self.recipe_display.serves_orig: nut_amt = nut_amt/self.recipe_display.serves_orig + if self.recipe_display.yields_orig: nut_amt = nut_amt/self.recipe_display.yields_orig label = self.nutritionLabel.active_unit if not self.nutritionLabel.active_unit: label = self.nutritionLabel.active_label.lower() @@ -124,10 +127,8 @@ istr = ''%weight + istr + '' if isinstance(nutinfo_for_ing, NutritionVapor): - print 'Vapor!',nutinfo_for_ing istr = ''+istr+'' return istr - class NutritionDisplayPlugin (RecDisplayPlugin): diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/plugins/utf16.gourmet-plugin /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/plugins/utf16.gourmet-plugin --- gourmet-0.15.1/src/lib/plugins/utf16.gourmet-plugin 1970-01-01 01:00:00.000000000 +0100 +++ gourmet-0.15.2/src/lib/plugins/utf16.gourmet-plugin 2009-12-15 01:44:51.000000000 +0000 @@ -0,0 +1,8 @@ +[Gourmet Plugin] +Module = check_for_unicode_16 +Version = 1.0 +API_Version = 1.0 +_Name = Check for Unicode-16 in text files +_Comment = Enable this if your utf-16 text files aren't importing cleanly into Gourmet. Disable this if you never use UTF16 and you're constantly being annoyed by the 'Encoding' dialog when you import files. +_Category = Importer/Exporter +Authors = Thomas M. Hinkle diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/plugins/utf16.gourmet-plugin.in /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/plugins/utf16.gourmet-plugin.in --- gourmet-0.15.1/src/lib/plugins/utf16.gourmet-plugin.in 1970-01-01 01:00:00.000000000 +0100 +++ gourmet-0.15.2/src/lib/plugins/utf16.gourmet-plugin.in 2009-12-15 01:34:01.000000000 +0000 @@ -0,0 +1,8 @@ +[Gourmet Plugin] +Module = check_for_unicode_16 +Version = 1.0 +API_Version = 1.0 +_Name = Check for Unicode-16 in text files +_Comment = Enable this if your utf-16 text files aren't importing cleanly into Gourmet. Disable this if you never use UTF16 and you're constantly being annoyed by the 'Encoding' dialog when you import files. +_Category = Importer/Exporter +Authors = Thomas M. Hinkle diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/prefsGui.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/prefsGui.py --- gourmet-0.15.1/src/lib/prefsGui.py 2009-05-20 01:48:57.000000000 +0100 +++ gourmet-0.15.2/src/lib/prefsGui.py 2009-11-30 11:55:27.000000000 +0000 @@ -1,8 +1,9 @@ import gtk, gtk.glade, os.path import gglobals from gtk_extras import optionTable +import plugin_loader, plugin -class PreferencesGui: +class PreferencesGui (plugin_loader.Pluggable): """The glue between our glade preferences dialog and our prefs modules. Instead of "connecting", as would be normal with pygtk objects, we set up handlers in the @@ -28,9 +29,9 @@ toggle_options={'remember_optionals_by_default':'remember_optionals_by_default', 'readableUnits':'toggle_readable_units', 'useFractions':'useFractions', - 'email_include_body':'email_body_checkbutton', - 'email_include_html':'email_html_checkbutton', - 'emailer_dont_ask':'remember_email_checkbutton', + #'email_include_body':'email_body_checkbutton', + #'email_include_html':'email_html_checkbutton', + #'emailer_dont_ask':'remember_email_checkbutton', }, number_options = {'recipes_per_page':'recipesPerPageSpinButton'}, @@ -52,7 +53,7 @@ buttons = {button_name : callback} """ - + self.prefs = prefs self.glade = gtk.glade.XML(glade) self.notebook = self.glade.get_widget('notebook') @@ -81,6 +82,7 @@ self.prefs.set_hooks.append(self.update_pref) self.pref_tables={} self.glade.get_widget('close_button').connect('clicked',lambda *args: self.hide_dialog()) + plugin_loader.Pluggable.__init__(self,[plugin.PrefsPlugin]) def build_pref_dictionary (self): """Build our preferences dictionary pref_dic diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/reccard.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/reccard.py --- gourmet-0.15.1/src/lib/reccard.py 2009-11-03 03:03:07.000000000 +0000 +++ gourmet-0.15.2/src/lib/reccard.py 2009-12-12 02:02:11.000000000 +0000 @@ -14,7 +14,7 @@ from gtk_extras import treeview_extras as te from gtk_extras import cb_extras as cb from gtk_extras import chooserNotebook -import exporters.printer as printer +from exporters.printer import get_print_manager from gdebug import * from gglobals import * from gettext import gettext as _ @@ -28,6 +28,7 @@ from plugin import RecDisplayModule, RecEditorModule, ToolPlugin, RecDisplayPlugin, RecEditorPlugin, IngredientControllerPlugin import plugin_loader import timeScanner +import defaults # TODO # @@ -611,11 +612,12 @@ if de.getBoolean(label=_("You have unsaved changes."), sublabel=_("Apply changes before printing?")): self.saveEditsCB() - printer.RecRenderer(self.rg.rd, [self.current_rec], mult=self.mult, - dialog_title=_("Print Recipe %s"%(self.current_rec.title)), - dialog_parent=self.window, - change_units=self.prefs.get('readableUnits',True) - ) + printManager = get_print_manager() + printManager.print_recipes( + self.rg.rd, [self.current_rec], mult=self.mult, + parent=self.window, + change_units=self.prefs.get('readableUnits',True) + ) def link_cb (self, *args): launch_url(self.link) @@ -629,6 +631,14 @@ def update_yields_multiplier (self, val): yields = self.yieldsDisplaySpin.get_value() + if yields == self.current_rec.yields: + self.yield_unitDisplay.set_text(self.current_rec.yield_unit) + if yields != self.current_rec.yields: + # Consider pluralizing... + plur_form = defaults.defaults.get_pluralized_form(self.current_rec.yield_unit,yields) + if plur_form != self.yield_unitDisplay.get_text(): + # Change text! + self.yield_unitDisplay.set_text(plur_form) if float(yields) != self.yields_orig: self.mult = float(yields)/self.yields_orig else: @@ -1098,7 +1108,7 @@ self.glade.signal_connect('addQuickIngredient',self.quick_add) def quick_add (self, *args): - txt = self.quickEntry.get_text() + txt = unicode(self.quickEntry.get_text()) prev_iter,group_iter = self.ingtree_ui.get_previous_iter_and_group_iter() add_with_undo(self, lambda *args: self.add_ingredient_from_line(txt, @@ -1406,10 +1416,10 @@ def save (self, recdic): for c in self.reccom: - recdic[c]=self.rw[c].entry.get_text() + recdic[c]=unicode(self.rw[c].entry.get_text()) for e in self.recent: if e in INT_REC_ATTRS: recdic[e]=self.rw[e].get_value() - else: recdic[e]=self.rw[e].get_text() + else: recdic[e]=unicode(self.rw[e].get_text()) if self.imageBox.edited: recdic['image'],recdic['thumb']=self.imageBox.commit() self.imageBox.edited=False diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/shopgui.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/shopgui.py --- gourmet-0.15.1/src/lib/shopgui.py 2009-11-03 03:03:07.000000000 +0000 +++ gourmet-0.15.2/src/lib/shopgui.py 2009-12-01 11:32:52.000000000 +0000 @@ -5,7 +5,7 @@ from gtk_extras import dialog_extras as de from gtk_extras import treeview_extras as te from gtk_extras import fix_action_group_importance -import exporters.printer as printer +from exporters.printer import get_print_manager from gdebug import * from gglobals import * from gettext import gettext as _ @@ -680,7 +680,7 @@ self.main.pack_start(self.vp); self.vp.show() vb.show() self.w.add(self.main) - self.w.show(); self.main.show() + self.main.show() self.w.add_accel_group(self.ui_manager.get_accel_group()) def setup_add_box (self): @@ -859,8 +859,21 @@ # Saving and printing def doSave (self, filename): debug("doSave (self, filename):",5) - import exporters.lprprinter - self._printList(exporters.lprprinter.SimpleWriter,file=filename,show_dialog=False) + #import exporters.lprprinter + #self._printList(exporters.lprprinter.SimpleWriter,file=filename,show_dialog=False) + ofi = file(filename,'w') + ofi.write(_("Shopping list for %s")%time.strftime("%x") + '\n\n') + ofi.write(_("For the following recipes:"+'\n')) + ofi.write('--------------------------------\n') + for r,mult in self.recs.values(): + itm = "%s"%r.title + if mult != 1: + itm += _(" x%s")%mult + ofi.write(itm+'\n') + write_itm = lambda a,i: ofi.write("%s %s"%(a,i) + '\n') + write_subh = lambda h: ofi.write('\n_%s_\n'%h) + self.sh.list_writer(write_subh,write_itm) + ofi.close() def _printList (self, printer, *args, **kwargs): w = printer(*args,**kwargs) @@ -925,7 +938,7 @@ def printList (self, *args): debug("printList (self, *args):",0) - self._printList(printer.SimpleWriter,dialog_parent=self.w) + self._printList(get_print_manager().get_simple_writer(),dialog_parent=self.w) def add_item (self, toggleWidget): if toggleWidget.get_active(): diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/src/lib/version.py /tmp/KYLRrknCT9/gourmet-0.15.2/src/lib/version.py --- gourmet-0.15.1/src/lib/version.py 2009-11-07 03:35:08.000000000 +0000 +++ gourmet-0.15.2/src/lib/version.py 2009-12-15 01:39:59.000000000 +0000 @@ -2,7 +2,7 @@ from gettext import gettext as _ appname = _("Gourmet Recipe Manager") copyright = _("Copyright (c) 2004,2005,2006,2007,2008,2009 Thomas M. Hinkle. GNU GPL v2") -version = "0.15.1" +version = "0.15.2" # repeated in setup.cfg description = _("Gourmet Recipe Manager is an application to store, organize and search recipes. Gourmet also makes it easy to create shopping lists from recipes. Gourmet imports recipes from a number of sources, including MealMaster and MasterCook archives and several popular websites. Gourmet can export recipes as text, MealMaster files, HTML web pages, and a custom XML format for exchange with other Gourmet users. Gourmet supports linking images with recipes. Gourmet can also calculate nutritional information for recipes based on the ingredients.") authors = ["Thomas M. Hinkle ", diff -Nru /tmp/Ab6j0d1sfy/gourmet-0.15.1/TODO /tmp/KYLRrknCT9/gourmet-0.15.2/TODO --- gourmet-0.15.1/TODO 2009-06-05 02:55:51.000000000 +0100 +++ gourmet-0.15.2/TODO 2009-12-01 11:33:05.000000000 +0000 @@ -1,4 +1,9 @@ TODO +* Look into drag-n-drop in shopgui + + +* Put Right Click Menu back [X] +* Make nutritional export plugin a preference [X] * Python 2.6 Compatability - interactive importer & Threads module (Threads now complained if not initialized and we set name).[X]