From f0d3f3afdfa314e1e8cd7d8da790878008a46aad Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Wed, 24 Jun 2009 12:59:33 -0400 Subject: Radically reorganize source code. - Collect all shell modules into a new top-level 'modules' directory: $(top_srcdir)/modules/addressbook $(top_srcdir)/modules/calendar $(top_srcdir)/modules/mail Nothing is allowed to link to these, not plugins nor other modules. THIS SOLVES BUG #571275 AND OPENS THE DOOR TO PORTING TO MAC OS X. - Mimic the libevolution-mail-shared library from master (except drop the "shared" suffix) and have libevolution-mail-importers and all mail-related plugins link to it. - Discard the a11y subdirectories and have the files live alongside their counterpart widgets. --- INSTALL | 237 -- Makefile.am | 24 +- addressbook/gui/Makefile.am | 2 +- addressbook/gui/component/Makefile.am | 129 - addressbook/gui/component/addressbook-config.c | 1250 -------- addressbook/gui/component/addressbook-config.h | 52 - .../apps_evolution_addressbook.schemas.in | 82 - addressbook/gui/component/autocompletion-config.c | 137 - addressbook/gui/component/autocompletion-config.h | 37 - addressbook/gui/component/e-book-shell-backend.c | 576 ---- addressbook/gui/component/e-book-shell-backend.h | 70 - addressbook/gui/component/e-book-shell-content.c | 492 ---- addressbook/gui/component/e-book-shell-content.h | 110 - addressbook/gui/component/e-book-shell-migrate.c | 1230 -------- addressbook/gui/component/e-book-shell-migrate.h | 41 - addressbook/gui/component/e-book-shell-sidebar.c | 232 -- addressbook/gui/component/e-book-shell-sidebar.h | 79 - .../gui/component/e-book-shell-view-actions.c | 1011 ------- .../gui/component/e-book-shell-view-actions.h | 91 - .../gui/component/e-book-shell-view-private.c | 621 ---- .../gui/component/e-book-shell-view-private.h | 129 - addressbook/gui/component/e-book-shell-view.c | 318 -- addressbook/gui/component/e-book-shell-view.h | 66 - addressbook/gui/component/eab-composer-util.c | 197 -- addressbook/gui/component/eab-composer-util.h | 31 - .../gui/component/evolution-module-addressbook.c | 45 - addressbook/gui/component/ldap-config.glade | 1454 --------- addressbook/gui/component/openldap-extract.h | 1427 --------- addressbook/gui/widgets/Makefile.am | 16 +- addressbook/gui/widgets/a11y/ea-addressbook-view.c | 123 - addressbook/gui/widgets/a11y/ea-addressbook-view.h | 57 - addressbook/gui/widgets/a11y/ea-addressbook.c | 84 - addressbook/gui/widgets/a11y/ea-addressbook.h | 33 - addressbook/gui/widgets/a11y/ea-minicard-view.c | 413 --- addressbook/gui/widgets/a11y/ea-minicard-view.h | 59 - addressbook/gui/widgets/a11y/ea-minicard.c | 273 -- addressbook/gui/widgets/a11y/ea-minicard.h | 58 - addressbook/gui/widgets/e-addressbook-view.c | 2 +- addressbook/gui/widgets/e-minicard-view.c | 2 +- addressbook/gui/widgets/e-minicard.c | 2 +- addressbook/gui/widgets/ea-addressbook-view.c | 123 + addressbook/gui/widgets/ea-addressbook-view.h | 57 + addressbook/gui/widgets/ea-addressbook.c | 84 + addressbook/gui/widgets/ea-addressbook.h | 33 + addressbook/gui/widgets/ea-minicard-view.c | 413 +++ addressbook/gui/widgets/ea-minicard-view.h | 59 + addressbook/gui/widgets/ea-minicard.c | 273 ++ addressbook/gui/widgets/ea-minicard.h | 58 + calendar/Makefile.am | 2 +- calendar/gui/Makefile.am | 51 +- calendar/gui/a11y/ea-cal-view-event.c | 573 ---- calendar/gui/a11y/ea-cal-view-event.h | 58 - calendar/gui/a11y/ea-cal-view.c | 426 --- calendar/gui/a11y/ea-cal-view.h | 58 - calendar/gui/a11y/ea-calendar-helpers.c | 156 - calendar/gui/a11y/ea-calendar-helpers.h | 41 - calendar/gui/a11y/ea-calendar.c | 204 -- calendar/gui/a11y/ea-calendar.h | 37 - calendar/gui/a11y/ea-day-view-cell.c | 396 --- calendar/gui/a11y/ea-day-view-cell.h | 85 - calendar/gui/a11y/ea-day-view-main-item.c | 1289 -------- calendar/gui/a11y/ea-day-view-main-item.h | 58 - calendar/gui/a11y/ea-day-view.c | 277 -- calendar/gui/a11y/ea-day-view.h | 57 - calendar/gui/a11y/ea-gnome-calendar.c | 351 --- calendar/gui/a11y/ea-gnome-calendar.h | 60 - calendar/gui/a11y/ea-jump-button.c | 224 -- calendar/gui/a11y/ea-jump-button.h | 58 - calendar/gui/a11y/ea-week-view-cell.c | 478 --- calendar/gui/a11y/ea-week-view-cell.h | 85 - calendar/gui/a11y/ea-week-view-main-item.c | 1247 -------- calendar/gui/a11y/ea-week-view-main-item.h | 59 - calendar/gui/a11y/ea-week-view.c | 321 -- calendar/gui/a11y/ea-week-view.h | 59 - calendar/gui/ea-cal-view-event.c | 573 ++++ calendar/gui/ea-cal-view-event.h | 58 + calendar/gui/ea-cal-view.c | 426 +++ calendar/gui/ea-cal-view.h | 58 + calendar/gui/ea-calendar-helpers.c | 156 + calendar/gui/ea-calendar-helpers.h | 41 + calendar/gui/ea-calendar.c | 204 ++ calendar/gui/ea-calendar.h | 37 + calendar/gui/ea-day-view-cell.c | 396 +++ calendar/gui/ea-day-view-cell.h | 85 + calendar/gui/ea-day-view-main-item.c | 1289 ++++++++ calendar/gui/ea-day-view-main-item.h | 58 + calendar/gui/ea-day-view.c | 277 ++ calendar/gui/ea-day-view.h | 57 + calendar/gui/ea-gnome-calendar.c | 351 +++ calendar/gui/ea-gnome-calendar.h | 60 + calendar/gui/ea-jump-button.c | 224 ++ calendar/gui/ea-jump-button.h | 58 + calendar/gui/ea-week-view-cell.c | 478 +++ calendar/gui/ea-week-view-cell.h | 85 + calendar/gui/ea-week-view-main-item.c | 1247 ++++++++ calendar/gui/ea-week-view-main-item.h | 59 + calendar/gui/ea-week-view.c | 321 ++ calendar/gui/ea-week-view.h | 59 + calendar/module/Makefile.am | 81 - calendar/module/e-cal-shell-backend.c | 666 ----- calendar/module/e-cal-shell-backend.h | 70 - calendar/module/e-cal-shell-content.c | 827 ------ calendar/module/e-cal-shell-content.h | 108 - calendar/module/e-cal-shell-migrate.c | 796 ----- calendar/module/e-cal-shell-migrate.h | 38 - calendar/module/e-cal-shell-settings.c | 59 - calendar/module/e-cal-shell-settings.h | 33 - calendar/module/e-cal-shell-sidebar.c | 759 ----- calendar/module/e-cal-shell-sidebar.h | 101 - calendar/module/e-cal-shell-view-actions.c | 1202 -------- calendar/module/e-cal-shell-view-actions.h | 153 - calendar/module/e-cal-shell-view-memopad.c | 526 ---- calendar/module/e-cal-shell-view-private.c | 650 ---- calendar/module/e-cal-shell-view-private.h | 170 -- calendar/module/e-cal-shell-view-taskpad.c | 654 ---- calendar/module/e-cal-shell-view.c | 226 -- calendar/module/e-cal-shell-view.h | 69 - calendar/module/e-memo-shell-backend.c | 613 ---- calendar/module/e-memo-shell-backend.h | 70 - calendar/module/e-memo-shell-content.c | 676 ----- calendar/module/e-memo-shell-content.h | 96 - calendar/module/e-memo-shell-migrate.c | 257 -- calendar/module/e-memo-shell-migrate.h | 38 - calendar/module/e-memo-shell-sidebar.c | 718 ----- calendar/module/e-memo-shell-sidebar.h | 95 - calendar/module/e-memo-shell-view-actions.c | 949 ------ calendar/module/e-memo-shell-view-actions.h | 87 - calendar/module/e-memo-shell-view-private.c | 524 ---- calendar/module/e-memo-shell-view-private.h | 126 - calendar/module/e-memo-shell-view.c | 222 -- calendar/module/e-memo-shell-view.h | 67 - calendar/module/e-task-shell-backend.c | 621 ---- calendar/module/e-task-shell-backend.h | 70 - calendar/module/e-task-shell-content.c | 700 ----- calendar/module/e-task-shell-content.h | 100 - calendar/module/e-task-shell-migrate.c | 664 ----- calendar/module/e-task-shell-migrate.h | 38 - calendar/module/e-task-shell-sidebar.c | 696 ----- calendar/module/e-task-shell-sidebar.h | 97 - calendar/module/e-task-shell-view-actions.c | 1154 -------- calendar/module/e-task-shell-view-actions.h | 105 - calendar/module/e-task-shell-view-private.c | 744 ----- calendar/module/e-task-shell-view-private.h | 141 - calendar/module/e-task-shell-view.c | 255 -- calendar/module/e-task-shell-view.h | 67 - calendar/module/evolution-module-calendar.c | 65 - configure.ac | 15 +- doc/reference/shell/tmpl/e-shell-backend.sgml | 132 + doc/reference/shell/tmpl/e-shell-settings.sgml | 151 + mail/Makefile.am | 175 +- mail/e-attachment-handler-mail.c | 524 ---- mail/e-attachment-handler-mail.h | 65 - mail/e-mail-browser.c | 8 +- mail/e-mail-browser.h | 4 +- mail/e-mail-reader-utils.c | 8 +- mail/e-mail-reader.c | 59 +- mail/e-mail-reader.h | 32 +- mail/e-mail-shell-backend.c | 766 ----- mail/e-mail-shell-backend.h | 82 - mail/e-mail-shell-content.c | 1053 ------- mail/e-mail-shell-content.h | 94 - mail/e-mail-shell-migrate.c | 3104 ------------------- mail/e-mail-shell-migrate.h | 38 - mail/e-mail-shell-settings.c | 521 ---- mail/e-mail-shell-settings.h | 33 - mail/e-mail-shell-sidebar.c | 644 ---- mail/e-mail-shell-sidebar.h | 81 - mail/e-mail-shell-view-actions.c | 1806 ------------ mail/e-mail-shell-view-actions.h | 257 -- mail/e-mail-shell-view-private.c | 905 ------ mail/e-mail-shell-view-private.h | 173 -- mail/e-mail-shell-view.c | 260 -- mail/e-mail-shell-view.h | 72 - mail/em-account-editor.c | 3114 -------------------- mail/em-account-editor.h | 86 - mail/em-account-prefs.c | 323 -- mail/em-account-prefs.h | 69 - mail/em-composer-prefs.c | 621 ---- mail/em-composer-prefs.h | 93 - mail/em-folder-tree.h | 1 - mail/em-mailer-prefs.c | 1332 --------- mail/em-mailer-prefs.h | 141 - mail/em-network-prefs.c | 499 ---- mail/em-network-prefs.h | 102 - mail/em-utils.c | 104 +- mail/em-utils.h | 6 +- mail/evolution-module-mail.c | 59 - mail/importers/Makefile.am | 33 + mail/importers/evolution-mbox-importer.c | 1 - mail/importers/mail-importer.c | 14 +- mail/mail-autofilter.c | 17 +- mail/mail-config.c | 12 +- mail/mail-folder-cache.c | 5 +- mail/mail-mt.c | 11 +- mail/mail-ops.c | 14 +- mail/mail-send-recv.c | 1 - mail/mail-session.c | 12 +- mail/mail-session.h | 4 +- mail/mail-tools.c | 6 +- mail/mail-vfolder.c | 43 +- modules/Makefile.am | 3 + modules/addressbook/Makefile.am | 129 + modules/addressbook/addressbook-config.c | 1250 ++++++++ modules/addressbook/addressbook-config.h | 52 + .../apps_evolution_addressbook.schemas.in | 82 + modules/addressbook/autocompletion-config.c | 137 + modules/addressbook/autocompletion-config.h | 37 + modules/addressbook/e-book-shell-backend.c | 576 ++++ modules/addressbook/e-book-shell-backend.h | 70 + modules/addressbook/e-book-shell-content.c | 492 ++++ modules/addressbook/e-book-shell-content.h | 110 + modules/addressbook/e-book-shell-migrate.c | 1230 ++++++++ modules/addressbook/e-book-shell-migrate.h | 41 + modules/addressbook/e-book-shell-sidebar.c | 232 ++ modules/addressbook/e-book-shell-sidebar.h | 79 + modules/addressbook/e-book-shell-view-actions.c | 1011 +++++++ modules/addressbook/e-book-shell-view-actions.h | 91 + modules/addressbook/e-book-shell-view-private.c | 621 ++++ modules/addressbook/e-book-shell-view-private.h | 129 + modules/addressbook/e-book-shell-view.c | 318 ++ modules/addressbook/e-book-shell-view.h | 66 + modules/addressbook/eab-composer-util.c | 197 ++ modules/addressbook/eab-composer-util.h | 31 + modules/addressbook/evolution-module-addressbook.c | 45 + modules/addressbook/ldap-config.glade | 1454 +++++++++ modules/addressbook/openldap-extract.h | 1427 +++++++++ modules/calendar/Makefile.am | 81 + modules/calendar/e-cal-shell-backend.c | 666 +++++ modules/calendar/e-cal-shell-backend.h | 70 + modules/calendar/e-cal-shell-content.c | 827 ++++++ modules/calendar/e-cal-shell-content.h | 108 + modules/calendar/e-cal-shell-migrate.c | 796 +++++ modules/calendar/e-cal-shell-migrate.h | 38 + modules/calendar/e-cal-shell-settings.c | 59 + modules/calendar/e-cal-shell-settings.h | 33 + modules/calendar/e-cal-shell-sidebar.c | 759 +++++ modules/calendar/e-cal-shell-sidebar.h | 101 + modules/calendar/e-cal-shell-view-actions.c | 1202 ++++++++ modules/calendar/e-cal-shell-view-actions.h | 153 + modules/calendar/e-cal-shell-view-memopad.c | 526 ++++ modules/calendar/e-cal-shell-view-private.c | 650 ++++ modules/calendar/e-cal-shell-view-private.h | 170 ++ modules/calendar/e-cal-shell-view-taskpad.c | 654 ++++ modules/calendar/e-cal-shell-view.c | 226 ++ modules/calendar/e-cal-shell-view.h | 69 + modules/calendar/e-memo-shell-backend.c | 613 ++++ modules/calendar/e-memo-shell-backend.h | 70 + modules/calendar/e-memo-shell-content.c | 676 +++++ modules/calendar/e-memo-shell-content.h | 96 + modules/calendar/e-memo-shell-migrate.c | 257 ++ modules/calendar/e-memo-shell-migrate.h | 38 + modules/calendar/e-memo-shell-sidebar.c | 718 +++++ modules/calendar/e-memo-shell-sidebar.h | 95 + modules/calendar/e-memo-shell-view-actions.c | 949 ++++++ modules/calendar/e-memo-shell-view-actions.h | 87 + modules/calendar/e-memo-shell-view-private.c | 524 ++++ modules/calendar/e-memo-shell-view-private.h | 126 + modules/calendar/e-memo-shell-view.c | 222 ++ modules/calendar/e-memo-shell-view.h | 67 + modules/calendar/e-task-shell-backend.c | 621 ++++ modules/calendar/e-task-shell-backend.h | 70 + modules/calendar/e-task-shell-content.c | 700 +++++ modules/calendar/e-task-shell-content.h | 100 + modules/calendar/e-task-shell-migrate.c | 664 +++++ modules/calendar/e-task-shell-migrate.h | 38 + modules/calendar/e-task-shell-sidebar.c | 696 +++++ modules/calendar/e-task-shell-sidebar.h | 97 + modules/calendar/e-task-shell-view-actions.c | 1154 ++++++++ modules/calendar/e-task-shell-view-actions.h | 105 + modules/calendar/e-task-shell-view-private.c | 744 +++++ modules/calendar/e-task-shell-view-private.h | 141 + modules/calendar/e-task-shell-view.c | 255 ++ modules/calendar/e-task-shell-view.h | 67 + modules/calendar/evolution-module-calendar.c | 65 + modules/mail/Makefile.am | 56 + modules/mail/e-attachment-handler-mail.c | 524 ++++ modules/mail/e-attachment-handler-mail.h | 65 + modules/mail/e-mail-shell-backend.c | 787 +++++ modules/mail/e-mail-shell-backend.h | 82 + modules/mail/e-mail-shell-content.c | 1053 +++++++ modules/mail/e-mail-shell-content.h | 94 + modules/mail/e-mail-shell-migrate.c | 3104 +++++++++++++++++++ modules/mail/e-mail-shell-migrate.h | 38 + modules/mail/e-mail-shell-settings.c | 521 ++++ modules/mail/e-mail-shell-settings.h | 33 + modules/mail/e-mail-shell-sidebar.c | 644 ++++ modules/mail/e-mail-shell-sidebar.h | 81 + modules/mail/e-mail-shell-view-actions.c | 1806 ++++++++++++ modules/mail/e-mail-shell-view-actions.h | 257 ++ modules/mail/e-mail-shell-view-private.c | 905 ++++++ modules/mail/e-mail-shell-view-private.h | 173 ++ modules/mail/e-mail-shell-view.c | 260 ++ modules/mail/e-mail-shell-view.h | 72 + modules/mail/em-account-editor.c | 3113 +++++++++++++++++++ modules/mail/em-account-editor.h | 86 + modules/mail/em-account-prefs.c | 323 ++ modules/mail/em-account-prefs.h | 69 + modules/mail/em-composer-prefs.c | 621 ++++ modules/mail/em-composer-prefs.h | 93 + modules/mail/em-mailer-prefs.c | 1332 +++++++++ modules/mail/em-mailer-prefs.h | 141 + modules/mail/em-network-prefs.c | 499 ++++ modules/mail/em-network-prefs.h | 102 + modules/mail/evolution-module-mail.c | 59 + plugins/attachment-reminder/Makefile.am | 2 +- plugins/audio-inline/Makefile.am | 6 +- plugins/bogo-junk-plugin/Makefile.am | 6 +- plugins/external-editor/Makefile.am | 2 +- plugins/imap-features/Makefile.am | 8 +- plugins/mail-notification/Makefile.am | 8 +- plugins/mark-all-read/Makefile.am | 4 +- plugins/sa-junk-plugin/Makefile.am | 6 +- plugins/vcard-inline/Makefile.am | 2 +- po/POTFILES.in | 114 +- widgets/misc/Makefile.am | 12 +- widgets/misc/a11y/ea-calendar-cell.c | 387 --- widgets/misc/a11y/ea-calendar-cell.h | 86 - widgets/misc/a11y/ea-calendar-item.c | 1314 --------- widgets/misc/a11y/ea-calendar-item.h | 68 - widgets/misc/a11y/ea-widgets.c | 32 - widgets/misc/a11y/ea-widgets.h | 32 - widgets/misc/e-calendar-item.c | 2 +- widgets/misc/ea-calendar-cell.c | 387 +++ widgets/misc/ea-calendar-cell.h | 86 + widgets/misc/ea-calendar-item.c | 1314 +++++++++ widgets/misc/ea-calendar-item.h | 68 + widgets/misc/ea-widgets.c | 32 + widgets/misc/ea-widgets.h | 32 + widgets/table/Makefile.am | 64 +- widgets/table/a11y/gal-a11y-e-cell-popup.c | 144 - widgets/table/a11y/gal-a11y-e-cell-popup.h | 62 - widgets/table/a11y/gal-a11y-e-cell-registry.c | 149 - widgets/table/a11y/gal-a11y-e-cell-registry.h | 72 - widgets/table/a11y/gal-a11y-e-cell-text.c | 737 ----- widgets/table/a11y/gal-a11y-e-cell-text.h | 64 - widgets/table/a11y/gal-a11y-e-cell-toggle.c | 191 -- widgets/table/a11y/gal-a11y-e-cell-toggle.h | 64 - widgets/table/a11y/gal-a11y-e-cell-tree.c | 260 -- widgets/table/a11y/gal-a11y-e-cell-tree.h | 64 - widgets/table/a11y/gal-a11y-e-cell-vbox.c | 225 -- widgets/table/a11y/gal-a11y-e-cell-vbox.h | 63 - widgets/table/a11y/gal-a11y-e-cell.c | 644 ---- widgets/table/a11y/gal-a11y-e-cell.h | 113 - .../a11y/gal-a11y-e-table-click-to-add-factory.c | 106 - .../a11y/gal-a11y-e-table-click-to-add-factory.h | 50 - widgets/table/a11y/gal-a11y-e-table-click-to-add.c | 344 --- widgets/table/a11y/gal-a11y-e-table-click-to-add.h | 55 - .../table/a11y/gal-a11y-e-table-column-header.c | 229 -- .../table/a11y/gal-a11y-e-table-column-header.h | 55 - widgets/table/a11y/gal-a11y-e-table-factory.c | 99 - widgets/table/a11y/gal-a11y-e-table-factory.h | 51 - widgets/table/a11y/gal-a11y-e-table-item-factory.c | 105 - widgets/table/a11y/gal-a11y-e-table-item-factory.h | 50 - widgets/table/a11y/gal-a11y-e-table-item.c | 1327 --------- widgets/table/a11y/gal-a11y-e-table-item.h | 59 - widgets/table/a11y/gal-a11y-e-table.c | 308 -- widgets/table/a11y/gal-a11y-e-table.h | 59 - widgets/table/a11y/gal-a11y-e-tree-factory.c | 98 - widgets/table/a11y/gal-a11y-e-tree-factory.h | 50 - widgets/table/a11y/gal-a11y-e-tree.c | 191 -- widgets/table/a11y/gal-a11y-e-tree.h | 58 - widgets/table/e-cell-popup.c | 4 +- widgets/table/e-cell-text.c | 4 +- widgets/table/e-cell-toggle.c | 4 +- widgets/table/e-cell-tree.c | 4 +- widgets/table/e-cell-vbox.c | 4 +- widgets/table/e-table-click-to-add.c | 2 +- widgets/table/e-table-item.c | 4 +- widgets/table/e-table.c | 2 +- widgets/table/e-tree.c | 2 +- widgets/table/gal-a11y-e-cell-popup.c | 144 + widgets/table/gal-a11y-e-cell-popup.h | 62 + widgets/table/gal-a11y-e-cell-registry.c | 149 + widgets/table/gal-a11y-e-cell-registry.h | 72 + widgets/table/gal-a11y-e-cell-text.c | 737 +++++ widgets/table/gal-a11y-e-cell-text.h | 64 + widgets/table/gal-a11y-e-cell-toggle.c | 191 ++ widgets/table/gal-a11y-e-cell-toggle.h | 64 + widgets/table/gal-a11y-e-cell-tree.c | 260 ++ widgets/table/gal-a11y-e-cell-tree.h | 64 + widgets/table/gal-a11y-e-cell-vbox.c | 225 ++ widgets/table/gal-a11y-e-cell-vbox.h | 63 + widgets/table/gal-a11y-e-cell.c | 644 ++++ widgets/table/gal-a11y-e-cell.h | 113 + .../table/gal-a11y-e-table-click-to-add-factory.c | 106 + .../table/gal-a11y-e-table-click-to-add-factory.h | 50 + widgets/table/gal-a11y-e-table-click-to-add.c | 344 +++ widgets/table/gal-a11y-e-table-click-to-add.h | 55 + widgets/table/gal-a11y-e-table-column-header.c | 229 ++ widgets/table/gal-a11y-e-table-column-header.h | 55 + widgets/table/gal-a11y-e-table-factory.c | 99 + widgets/table/gal-a11y-e-table-factory.h | 51 + widgets/table/gal-a11y-e-table-item-factory.c | 105 + widgets/table/gal-a11y-e-table-item-factory.h | 50 + widgets/table/gal-a11y-e-table-item.c | 1327 +++++++++ widgets/table/gal-a11y-e-table-item.h | 59 + widgets/table/gal-a11y-e-table.c | 308 ++ widgets/table/gal-a11y-e-table.h | 59 + widgets/table/gal-a11y-e-tree-factory.c | 98 + widgets/table/gal-a11y-e-tree-factory.h | 50 + widgets/table/gal-a11y-e-tree.c | 191 ++ widgets/table/gal-a11y-e-tree.h | 58 + widgets/text/Makefile.am | 8 +- widgets/text/a11y/gal-a11y-e-text-factory.c | 101 - widgets/text/a11y/gal-a11y-e-text-factory.h | 50 - widgets/text/a11y/gal-a11y-e-text.c | 1134 ------- widgets/text/a11y/gal-a11y-e-text.h | 57 - widgets/text/e-text.c | 2 +- widgets/text/gal-a11y-e-text-factory.c | 101 + widgets/text/gal-a11y-e-text-factory.h | 50 + widgets/text/gal-a11y-e-text.c | 1134 +++++++ widgets/text/gal-a11y-e-text.h | 57 + win32/Makefile.am | 7 - 413 files changed, 62011 insertions(+), 62019 deletions(-) delete mode 100644 INSTALL delete mode 100644 addressbook/gui/component/Makefile.am delete mode 100644 addressbook/gui/component/addressbook-config.c delete mode 100644 addressbook/gui/component/addressbook-config.h delete mode 100644 addressbook/gui/component/apps_evolution_addressbook.schemas.in delete mode 100644 addressbook/gui/component/autocompletion-config.c delete mode 100644 addressbook/gui/component/autocompletion-config.h delete mode 100644 addressbook/gui/component/e-book-shell-backend.c delete mode 100644 addressbook/gui/component/e-book-shell-backend.h delete mode 100644 addressbook/gui/component/e-book-shell-content.c delete mode 100644 addressbook/gui/component/e-book-shell-content.h delete mode 100644 addressbook/gui/component/e-book-shell-migrate.c delete mode 100644 addressbook/gui/component/e-book-shell-migrate.h delete mode 100644 addressbook/gui/component/e-book-shell-sidebar.c delete mode 100644 addressbook/gui/component/e-book-shell-sidebar.h delete mode 100644 addressbook/gui/component/e-book-shell-view-actions.c delete mode 100644 addressbook/gui/component/e-book-shell-view-actions.h delete mode 100644 addressbook/gui/component/e-book-shell-view-private.c delete mode 100644 addressbook/gui/component/e-book-shell-view-private.h delete mode 100644 addressbook/gui/component/e-book-shell-view.c delete mode 100644 addressbook/gui/component/e-book-shell-view.h delete mode 100644 addressbook/gui/component/eab-composer-util.c delete mode 100644 addressbook/gui/component/eab-composer-util.h delete mode 100644 addressbook/gui/component/evolution-module-addressbook.c delete mode 100644 addressbook/gui/component/ldap-config.glade delete mode 100644 addressbook/gui/component/openldap-extract.h delete mode 100644 addressbook/gui/widgets/a11y/ea-addressbook-view.c delete mode 100644 addressbook/gui/widgets/a11y/ea-addressbook-view.h delete mode 100644 addressbook/gui/widgets/a11y/ea-addressbook.c delete mode 100644 addressbook/gui/widgets/a11y/ea-addressbook.h delete mode 100644 addressbook/gui/widgets/a11y/ea-minicard-view.c delete mode 100644 addressbook/gui/widgets/a11y/ea-minicard-view.h delete mode 100644 addressbook/gui/widgets/a11y/ea-minicard.c delete mode 100644 addressbook/gui/widgets/a11y/ea-minicard.h create mode 100644 addressbook/gui/widgets/ea-addressbook-view.c create mode 100644 addressbook/gui/widgets/ea-addressbook-view.h create mode 100644 addressbook/gui/widgets/ea-addressbook.c create mode 100644 addressbook/gui/widgets/ea-addressbook.h create mode 100644 addressbook/gui/widgets/ea-minicard-view.c create mode 100644 addressbook/gui/widgets/ea-minicard-view.h create mode 100644 addressbook/gui/widgets/ea-minicard.c create mode 100644 addressbook/gui/widgets/ea-minicard.h delete mode 100644 calendar/gui/a11y/ea-cal-view-event.c delete mode 100644 calendar/gui/a11y/ea-cal-view-event.h delete mode 100644 calendar/gui/a11y/ea-cal-view.c delete mode 100644 calendar/gui/a11y/ea-cal-view.h delete mode 100644 calendar/gui/a11y/ea-calendar-helpers.c delete mode 100644 calendar/gui/a11y/ea-calendar-helpers.h delete mode 100644 calendar/gui/a11y/ea-calendar.c delete mode 100644 calendar/gui/a11y/ea-calendar.h delete mode 100644 calendar/gui/a11y/ea-day-view-cell.c delete mode 100644 calendar/gui/a11y/ea-day-view-cell.h delete mode 100644 calendar/gui/a11y/ea-day-view-main-item.c delete mode 100644 calendar/gui/a11y/ea-day-view-main-item.h delete mode 100644 calendar/gui/a11y/ea-day-view.c delete mode 100644 calendar/gui/a11y/ea-day-view.h delete mode 100644 calendar/gui/a11y/ea-gnome-calendar.c delete mode 100644 calendar/gui/a11y/ea-gnome-calendar.h delete mode 100644 calendar/gui/a11y/ea-jump-button.c delete mode 100644 calendar/gui/a11y/ea-jump-button.h delete mode 100644 calendar/gui/a11y/ea-week-view-cell.c delete mode 100644 calendar/gui/a11y/ea-week-view-cell.h delete mode 100644 calendar/gui/a11y/ea-week-view-main-item.c delete mode 100644 calendar/gui/a11y/ea-week-view-main-item.h delete mode 100644 calendar/gui/a11y/ea-week-view.c delete mode 100644 calendar/gui/a11y/ea-week-view.h create mode 100644 calendar/gui/ea-cal-view-event.c create mode 100644 calendar/gui/ea-cal-view-event.h create mode 100644 calendar/gui/ea-cal-view.c create mode 100644 calendar/gui/ea-cal-view.h create mode 100644 calendar/gui/ea-calendar-helpers.c create mode 100644 calendar/gui/ea-calendar-helpers.h create mode 100644 calendar/gui/ea-calendar.c create mode 100644 calendar/gui/ea-calendar.h create mode 100644 calendar/gui/ea-day-view-cell.c create mode 100644 calendar/gui/ea-day-view-cell.h create mode 100644 calendar/gui/ea-day-view-main-item.c create mode 100644 calendar/gui/ea-day-view-main-item.h create mode 100644 calendar/gui/ea-day-view.c create mode 100644 calendar/gui/ea-day-view.h create mode 100644 calendar/gui/ea-gnome-calendar.c create mode 100644 calendar/gui/ea-gnome-calendar.h create mode 100644 calendar/gui/ea-jump-button.c create mode 100644 calendar/gui/ea-jump-button.h create mode 100644 calendar/gui/ea-week-view-cell.c create mode 100644 calendar/gui/ea-week-view-cell.h create mode 100644 calendar/gui/ea-week-view-main-item.c create mode 100644 calendar/gui/ea-week-view-main-item.h create mode 100644 calendar/gui/ea-week-view.c create mode 100644 calendar/gui/ea-week-view.h delete mode 100644 calendar/module/Makefile.am delete mode 100644 calendar/module/e-cal-shell-backend.c delete mode 100644 calendar/module/e-cal-shell-backend.h delete mode 100644 calendar/module/e-cal-shell-content.c delete mode 100644 calendar/module/e-cal-shell-content.h delete mode 100644 calendar/module/e-cal-shell-migrate.c delete mode 100644 calendar/module/e-cal-shell-migrate.h delete mode 100644 calendar/module/e-cal-shell-settings.c delete mode 100644 calendar/module/e-cal-shell-settings.h delete mode 100644 calendar/module/e-cal-shell-sidebar.c delete mode 100644 calendar/module/e-cal-shell-sidebar.h delete mode 100644 calendar/module/e-cal-shell-view-actions.c delete mode 100644 calendar/module/e-cal-shell-view-actions.h delete mode 100644 calendar/module/e-cal-shell-view-memopad.c delete mode 100644 calendar/module/e-cal-shell-view-private.c delete mode 100644 calendar/module/e-cal-shell-view-private.h delete mode 100644 calendar/module/e-cal-shell-view-taskpad.c delete mode 100644 calendar/module/e-cal-shell-view.c delete mode 100644 calendar/module/e-cal-shell-view.h delete mode 100644 calendar/module/e-memo-shell-backend.c delete mode 100644 calendar/module/e-memo-shell-backend.h delete mode 100644 calendar/module/e-memo-shell-content.c delete mode 100644 calendar/module/e-memo-shell-content.h delete mode 100644 calendar/module/e-memo-shell-migrate.c delete mode 100644 calendar/module/e-memo-shell-migrate.h delete mode 100644 calendar/module/e-memo-shell-sidebar.c delete mode 100644 calendar/module/e-memo-shell-sidebar.h delete mode 100644 calendar/module/e-memo-shell-view-actions.c delete mode 100644 calendar/module/e-memo-shell-view-actions.h delete mode 100644 calendar/module/e-memo-shell-view-private.c delete mode 100644 calendar/module/e-memo-shell-view-private.h delete mode 100644 calendar/module/e-memo-shell-view.c delete mode 100644 calendar/module/e-memo-shell-view.h delete mode 100644 calendar/module/e-task-shell-backend.c delete mode 100644 calendar/module/e-task-shell-backend.h delete mode 100644 calendar/module/e-task-shell-content.c delete mode 100644 calendar/module/e-task-shell-content.h delete mode 100644 calendar/module/e-task-shell-migrate.c delete mode 100644 calendar/module/e-task-shell-migrate.h delete mode 100644 calendar/module/e-task-shell-sidebar.c delete mode 100644 calendar/module/e-task-shell-sidebar.h delete mode 100644 calendar/module/e-task-shell-view-actions.c delete mode 100644 calendar/module/e-task-shell-view-actions.h delete mode 100644 calendar/module/e-task-shell-view-private.c delete mode 100644 calendar/module/e-task-shell-view-private.h delete mode 100644 calendar/module/e-task-shell-view.c delete mode 100644 calendar/module/e-task-shell-view.h delete mode 100644 calendar/module/evolution-module-calendar.c create mode 100644 doc/reference/shell/tmpl/e-shell-backend.sgml create mode 100644 doc/reference/shell/tmpl/e-shell-settings.sgml delete mode 100644 mail/e-attachment-handler-mail.c delete mode 100644 mail/e-attachment-handler-mail.h delete mode 100644 mail/e-mail-shell-backend.c delete mode 100644 mail/e-mail-shell-backend.h delete mode 100644 mail/e-mail-shell-content.c delete mode 100644 mail/e-mail-shell-content.h delete mode 100644 mail/e-mail-shell-migrate.c delete mode 100644 mail/e-mail-shell-migrate.h delete mode 100644 mail/e-mail-shell-settings.c delete mode 100644 mail/e-mail-shell-settings.h delete mode 100644 mail/e-mail-shell-sidebar.c delete mode 100644 mail/e-mail-shell-sidebar.h delete mode 100644 mail/e-mail-shell-view-actions.c delete mode 100644 mail/e-mail-shell-view-actions.h delete mode 100644 mail/e-mail-shell-view-private.c delete mode 100644 mail/e-mail-shell-view-private.h delete mode 100644 mail/e-mail-shell-view.c delete mode 100644 mail/e-mail-shell-view.h delete mode 100644 mail/em-account-editor.c delete mode 100644 mail/em-account-editor.h delete mode 100644 mail/em-account-prefs.c delete mode 100644 mail/em-account-prefs.h delete mode 100644 mail/em-composer-prefs.c delete mode 100644 mail/em-composer-prefs.h delete mode 100644 mail/em-mailer-prefs.c delete mode 100644 mail/em-mailer-prefs.h delete mode 100644 mail/em-network-prefs.c delete mode 100644 mail/em-network-prefs.h delete mode 100644 mail/evolution-module-mail.c create mode 100644 mail/importers/Makefile.am create mode 100644 modules/Makefile.am create mode 100644 modules/addressbook/Makefile.am create mode 100644 modules/addressbook/addressbook-config.c create mode 100644 modules/addressbook/addressbook-config.h create mode 100644 modules/addressbook/apps_evolution_addressbook.schemas.in create mode 100644 modules/addressbook/autocompletion-config.c create mode 100644 modules/addressbook/autocompletion-config.h create mode 100644 modules/addressbook/e-book-shell-backend.c create mode 100644 modules/addressbook/e-book-shell-backend.h create mode 100644 modules/addressbook/e-book-shell-content.c create mode 100644 modules/addressbook/e-book-shell-content.h create mode 100644 modules/addressbook/e-book-shell-migrate.c create mode 100644 modules/addressbook/e-book-shell-migrate.h create mode 100644 modules/addressbook/e-book-shell-sidebar.c create mode 100644 modules/addressbook/e-book-shell-sidebar.h create mode 100644 modules/addressbook/e-book-shell-view-actions.c create mode 100644 modules/addressbook/e-book-shell-view-actions.h create mode 100644 modules/addressbook/e-book-shell-view-private.c create mode 100644 modules/addressbook/e-book-shell-view-private.h create mode 100644 modules/addressbook/e-book-shell-view.c create mode 100644 modules/addressbook/e-book-shell-view.h create mode 100644 modules/addressbook/eab-composer-util.c create mode 100644 modules/addressbook/eab-composer-util.h create mode 100644 modules/addressbook/evolution-module-addressbook.c create mode 100644 modules/addressbook/ldap-config.glade create mode 100644 modules/addressbook/openldap-extract.h create mode 100644 modules/calendar/Makefile.am create mode 100644 modules/calendar/e-cal-shell-backend.c create mode 100644 modules/calendar/e-cal-shell-backend.h create mode 100644 modules/calendar/e-cal-shell-content.c create mode 100644 modules/calendar/e-cal-shell-content.h create mode 100644 modules/calendar/e-cal-shell-migrate.c create mode 100644 modules/calendar/e-cal-shell-migrate.h create mode 100644 modules/calendar/e-cal-shell-settings.c create mode 100644 modules/calendar/e-cal-shell-settings.h create mode 100644 modules/calendar/e-cal-shell-sidebar.c create mode 100644 modules/calendar/e-cal-shell-sidebar.h create mode 100644 modules/calendar/e-cal-shell-view-actions.c create mode 100644 modules/calendar/e-cal-shell-view-actions.h create mode 100644 modules/calendar/e-cal-shell-view-memopad.c create mode 100644 modules/calendar/e-cal-shell-view-private.c create mode 100644 modules/calendar/e-cal-shell-view-private.h create mode 100644 modules/calendar/e-cal-shell-view-taskpad.c create mode 100644 modules/calendar/e-cal-shell-view.c create mode 100644 modules/calendar/e-cal-shell-view.h create mode 100644 modules/calendar/e-memo-shell-backend.c create mode 100644 modules/calendar/e-memo-shell-backend.h create mode 100644 modules/calendar/e-memo-shell-content.c create mode 100644 modules/calendar/e-memo-shell-content.h create mode 100644 modules/calendar/e-memo-shell-migrate.c create mode 100644 modules/calendar/e-memo-shell-migrate.h create mode 100644 modules/calendar/e-memo-shell-sidebar.c create mode 100644 modules/calendar/e-memo-shell-sidebar.h create mode 100644 modules/calendar/e-memo-shell-view-actions.c create mode 100644 modules/calendar/e-memo-shell-view-actions.h create mode 100644 modules/calendar/e-memo-shell-view-private.c create mode 100644 modules/calendar/e-memo-shell-view-private.h create mode 100644 modules/calendar/e-memo-shell-view.c create mode 100644 modules/calendar/e-memo-shell-view.h create mode 100644 modules/calendar/e-task-shell-backend.c create mode 100644 modules/calendar/e-task-shell-backend.h create mode 100644 modules/calendar/e-task-shell-content.c create mode 100644 modules/calendar/e-task-shell-content.h create mode 100644 modules/calendar/e-task-shell-migrate.c create mode 100644 modules/calendar/e-task-shell-migrate.h create mode 100644 modules/calendar/e-task-shell-sidebar.c create mode 100644 modules/calendar/e-task-shell-sidebar.h create mode 100644 modules/calendar/e-task-shell-view-actions.c create mode 100644 modules/calendar/e-task-shell-view-actions.h create mode 100644 modules/calendar/e-task-shell-view-private.c create mode 100644 modules/calendar/e-task-shell-view-private.h create mode 100644 modules/calendar/e-task-shell-view.c create mode 100644 modules/calendar/e-task-shell-view.h create mode 100644 modules/calendar/evolution-module-calendar.c create mode 100644 modules/mail/Makefile.am create mode 100644 modules/mail/e-attachment-handler-mail.c create mode 100644 modules/mail/e-attachment-handler-mail.h create mode 100644 modules/mail/e-mail-shell-backend.c create mode 100644 modules/mail/e-mail-shell-backend.h create mode 100644 modules/mail/e-mail-shell-content.c create mode 100644 modules/mail/e-mail-shell-content.h create mode 100644 modules/mail/e-mail-shell-migrate.c create mode 100644 modules/mail/e-mail-shell-migrate.h create mode 100644 modules/mail/e-mail-shell-settings.c create mode 100644 modules/mail/e-mail-shell-settings.h create mode 100644 modules/mail/e-mail-shell-sidebar.c create mode 100644 modules/mail/e-mail-shell-sidebar.h create mode 100644 modules/mail/e-mail-shell-view-actions.c create mode 100644 modules/mail/e-mail-shell-view-actions.h create mode 100644 modules/mail/e-mail-shell-view-private.c create mode 100644 modules/mail/e-mail-shell-view-private.h create mode 100644 modules/mail/e-mail-shell-view.c create mode 100644 modules/mail/e-mail-shell-view.h create mode 100644 modules/mail/em-account-editor.c create mode 100644 modules/mail/em-account-editor.h create mode 100644 modules/mail/em-account-prefs.c create mode 100644 modules/mail/em-account-prefs.h create mode 100644 modules/mail/em-composer-prefs.c create mode 100644 modules/mail/em-composer-prefs.h create mode 100644 modules/mail/em-mailer-prefs.c create mode 100644 modules/mail/em-mailer-prefs.h create mode 100644 modules/mail/em-network-prefs.c create mode 100644 modules/mail/em-network-prefs.h create mode 100644 modules/mail/evolution-module-mail.c delete mode 100644 widgets/misc/a11y/ea-calendar-cell.c delete mode 100644 widgets/misc/a11y/ea-calendar-cell.h delete mode 100644 widgets/misc/a11y/ea-calendar-item.c delete mode 100644 widgets/misc/a11y/ea-calendar-item.h delete mode 100644 widgets/misc/a11y/ea-widgets.c delete mode 100644 widgets/misc/a11y/ea-widgets.h create mode 100644 widgets/misc/ea-calendar-cell.c create mode 100644 widgets/misc/ea-calendar-cell.h create mode 100644 widgets/misc/ea-calendar-item.c create mode 100644 widgets/misc/ea-calendar-item.h create mode 100644 widgets/misc/ea-widgets.c create mode 100644 widgets/misc/ea-widgets.h delete mode 100644 widgets/table/a11y/gal-a11y-e-cell-popup.c delete mode 100644 widgets/table/a11y/gal-a11y-e-cell-popup.h delete mode 100644 widgets/table/a11y/gal-a11y-e-cell-registry.c delete mode 100644 widgets/table/a11y/gal-a11y-e-cell-registry.h delete mode 100644 widgets/table/a11y/gal-a11y-e-cell-text.c delete mode 100644 widgets/table/a11y/gal-a11y-e-cell-text.h delete mode 100644 widgets/table/a11y/gal-a11y-e-cell-toggle.c delete mode 100644 widgets/table/a11y/gal-a11y-e-cell-toggle.h delete mode 100644 widgets/table/a11y/gal-a11y-e-cell-tree.c delete mode 100644 widgets/table/a11y/gal-a11y-e-cell-tree.h delete mode 100644 widgets/table/a11y/gal-a11y-e-cell-vbox.c delete mode 100644 widgets/table/a11y/gal-a11y-e-cell-vbox.h delete mode 100644 widgets/table/a11y/gal-a11y-e-cell.c delete mode 100644 widgets/table/a11y/gal-a11y-e-cell.h delete mode 100644 widgets/table/a11y/gal-a11y-e-table-click-to-add-factory.c delete mode 100644 widgets/table/a11y/gal-a11y-e-table-click-to-add-factory.h delete mode 100644 widgets/table/a11y/gal-a11y-e-table-click-to-add.c delete mode 100644 widgets/table/a11y/gal-a11y-e-table-click-to-add.h delete mode 100644 widgets/table/a11y/gal-a11y-e-table-column-header.c delete mode 100644 widgets/table/a11y/gal-a11y-e-table-column-header.h delete mode 100644 widgets/table/a11y/gal-a11y-e-table-factory.c delete mode 100644 widgets/table/a11y/gal-a11y-e-table-factory.h delete mode 100644 widgets/table/a11y/gal-a11y-e-table-item-factory.c delete mode 100644 widgets/table/a11y/gal-a11y-e-table-item-factory.h delete mode 100644 widgets/table/a11y/gal-a11y-e-table-item.c delete mode 100644 widgets/table/a11y/gal-a11y-e-table-item.h delete mode 100644 widgets/table/a11y/gal-a11y-e-table.c delete mode 100644 widgets/table/a11y/gal-a11y-e-table.h delete mode 100644 widgets/table/a11y/gal-a11y-e-tree-factory.c delete mode 100644 widgets/table/a11y/gal-a11y-e-tree-factory.h delete mode 100644 widgets/table/a11y/gal-a11y-e-tree.c delete mode 100644 widgets/table/a11y/gal-a11y-e-tree.h create mode 100644 widgets/table/gal-a11y-e-cell-popup.c create mode 100644 widgets/table/gal-a11y-e-cell-popup.h create mode 100644 widgets/table/gal-a11y-e-cell-registry.c create mode 100644 widgets/table/gal-a11y-e-cell-registry.h create mode 100644 widgets/table/gal-a11y-e-cell-text.c create mode 100644 widgets/table/gal-a11y-e-cell-text.h create mode 100644 widgets/table/gal-a11y-e-cell-toggle.c create mode 100644 widgets/table/gal-a11y-e-cell-toggle.h create mode 100644 widgets/table/gal-a11y-e-cell-tree.c create mode 100644 widgets/table/gal-a11y-e-cell-tree.h create mode 100644 widgets/table/gal-a11y-e-cell-vbox.c create mode 100644 widgets/table/gal-a11y-e-cell-vbox.h create mode 100644 widgets/table/gal-a11y-e-cell.c create mode 100644 widgets/table/gal-a11y-e-cell.h create mode 100644 widgets/table/gal-a11y-e-table-click-to-add-factory.c create mode 100644 widgets/table/gal-a11y-e-table-click-to-add-factory.h create mode 100644 widgets/table/gal-a11y-e-table-click-to-add.c create mode 100644 widgets/table/gal-a11y-e-table-click-to-add.h create mode 100644 widgets/table/gal-a11y-e-table-column-header.c create mode 100644 widgets/table/gal-a11y-e-table-column-header.h create mode 100644 widgets/table/gal-a11y-e-table-factory.c create mode 100644 widgets/table/gal-a11y-e-table-factory.h create mode 100644 widgets/table/gal-a11y-e-table-item-factory.c create mode 100644 widgets/table/gal-a11y-e-table-item-factory.h create mode 100644 widgets/table/gal-a11y-e-table-item.c create mode 100644 widgets/table/gal-a11y-e-table-item.h create mode 100644 widgets/table/gal-a11y-e-table.c create mode 100644 widgets/table/gal-a11y-e-table.h create mode 100644 widgets/table/gal-a11y-e-tree-factory.c create mode 100644 widgets/table/gal-a11y-e-tree-factory.h create mode 100644 widgets/table/gal-a11y-e-tree.c create mode 100644 widgets/table/gal-a11y-e-tree.h delete mode 100644 widgets/text/a11y/gal-a11y-e-text-factory.c delete mode 100644 widgets/text/a11y/gal-a11y-e-text-factory.h delete mode 100644 widgets/text/a11y/gal-a11y-e-text.c delete mode 100644 widgets/text/a11y/gal-a11y-e-text.h create mode 100644 widgets/text/gal-a11y-e-text-factory.c create mode 100644 widgets/text/gal-a11y-e-text-factory.h create mode 100644 widgets/text/gal-a11y-e-text.c create mode 100644 widgets/text/gal-a11y-e-text.h diff --git a/INSTALL b/INSTALL deleted file mode 100644 index d3c5b40a94..0000000000 --- a/INSTALL +++ /dev/null @@ -1,237 +0,0 @@ -Installation Instructions -************************* - -Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, -2006, 2007 Free Software Foundation, Inc. - -This file is free documentation; the Free Software Foundation gives -unlimited permission to copy, distribute and modify it. - -Basic Installation -================== - -Briefly, the shell commands `./configure; make; make install' should -configure, build, and install this package. The following -more-detailed instructions are generic; see the `README' file for -instructions specific to this package. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, and a -file `config.log' containing compiler output (useful mainly for -debugging `configure'). - - It can also use an optional file (typically called `config.cache' -and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. Caching is -disabled by default to prevent problems with accidental use of stale -cache files. - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If you are using the cache, and at -some point `config.cache' contains results you don't want to keep, you -may remove or edit it. - - The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You need `configure.ac' if -you want to change it or regenerate `configure' using a newer version -of `autoconf'. - -The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. - - Running `configure' might take a while. While running, it prints - some messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package. - - 4. Type `make install' to install the programs and any data files and - documentation. - - 5. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - - 6. Often, you can also type `make uninstall' to remove the installed - files again. - -Compilers and Options -===================== - -Some systems require unusual options for compilation or linking that the -`configure' script does not know about. Run `./configure --help' for -details on some of the pertinent environment variables. - - You can give `configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: - - ./configure CC=c99 CFLAGS=-g LIBS=-lposix - - *Note Defining Variables::, for more details. - -Compiling For Multiple Architectures -==================================== - -You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you can use GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. - - With a non-GNU `make', it is safer to compile the package for one -architecture at a time in the source code directory. After you have -installed the package for one architecture, use `make distclean' before -reconfiguring for another architecture. - -Installation Names -================== - -By default, `make install' installs the package's commands under -`/usr/local/bin', include files under `/usr/local/include', etc. You -can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX'. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -pass the option `--exec-prefix=PREFIX' to `configure', the package uses -PREFIX as the prefix for installing programs and libraries. -Documentation and other data files still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=DIR' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - -Optional Features -================= - -Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - -Specifying the System Type -========================== - -There may be some features `configure' cannot figure out automatically, -but needs to determine by the type of machine the package will run on. -Usually, assuming the package is built to be run on the _same_ -architectures, `configure' can figure that out, but if it prints a -message saying it cannot guess the machine type, give it the -`--build=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name which has the form: - - CPU-COMPANY-SYSTEM - -where SYSTEM can have one of these forms: - - OS KERNEL-OS - - See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the machine type. - - If you are _building_ compiler tools for cross-compiling, you should -use the option `--target=TYPE' to select the type of system they will -produce code for. - - If you want to _use_ a cross compiler, that generates code for a -platform different from the build platform, you should specify the -"host" platform (i.e., that on which the generated programs will -eventually be run) with `--host=TYPE'. - -Sharing Defaults -================ - -If you want to set default values for `configure' scripts to share, you -can create a site shell script called `config.site' that gives default -values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Defining Variables -================== - -Variables not defined in a site shell script can be set in the -environment passed to `configure'. However, some packages may run -configure again during the build, and the customized values of these -variables may be lost. In order to avoid this problem, you should set -them in the `configure' command line, using `VAR=value'. For example: - - ./configure CC=/usr/local2/bin/gcc - -causes the specified `gcc' to be used as the C compiler (unless it is -overridden in the site shell script). - -Unfortunately, this technique does not work for `CONFIG_SHELL' due to -an Autoconf bug. Until the bug is fixed you can use this workaround: - - CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash - -`configure' Invocation -====================== - -`configure' recognizes the following options to control how it operates. - -`--help' -`-h' - Print a summary of the options to `configure', and exit. - -`--version' -`-V' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`--cache-file=FILE' - Enable the cache: use and save the results of the tests in FILE, - traditionally `config.cache'. FILE defaults to `/dev/null' to - disable caching. - -`--config-cache' -`-C' - Alias for `--cache-file=config.cache'. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`configure' also accepts some other, not widely useful, options. Run -`configure --help' for more details. - diff --git a/Makefile.am b/Makefile.am index 12e626866d..d7c022c4ed 100644 --- a/Makefile.am +++ b/Makefile.am @@ -35,29 +35,6 @@ if ENABLE_SMIME SMIME_DIR=smime endif -# Disabled component and plugin directories during shell rewrite. - -#SUBDIRS = \ -# win32 \ -# data \ -# e-util \ -# a11y \ -# widgets \ -# shell \ -# filter \ -# $(SMIME_DIR) \ -# addressbook \ -# calendar \ -# art \ -# composer \ -# mail \ -# plugins \ -# ui \ -# views \ -# tools \ -# po \ -# sounds - SUBDIRS = \ win32 \ data \ @@ -74,6 +51,7 @@ SUBDIRS = \ calendar \ art \ plugins \ + modules \ doc \ ui \ views \ diff --git a/addressbook/gui/Makefile.am b/addressbook/gui/Makefile.am index 73c12f9bf2..7f08bf425d 100644 --- a/addressbook/gui/Makefile.am +++ b/addressbook/gui/Makefile.am @@ -1,3 +1,3 @@ -SUBDIRS = merging widgets contact-editor contact-list-editor component +SUBDIRS = merging widgets contact-editor contact-list-editor -include $(top_srcdir)/git.mk diff --git a/addressbook/gui/component/Makefile.am b/addressbook/gui/component/Makefile.am deleted file mode 100644 index cd9dfc1434..0000000000 --- a/addressbook/gui/component/Makefile.am +++ /dev/null @@ -1,129 +0,0 @@ -if OS_WIN32 -WIN32_BOOTSTRAP_LIBS = $(top_builddir)/win32/libevolution-mail-shared.la -endif - -INCLUDES = \ - -DG_LOG_DOMAIN=\"evolution-addressbook\" \ - -I$(top_srcdir) \ - -I$(top_srcdir)/widgets \ - -I$(top_srcdir)/shell \ - -I$(top_builddir)/shell \ - -I$(top_srcdir)/widgets/menus \ - -I$(top_srcdir)/widgets/misc \ - -I$(top_srcdir)/addressbook/util \ - -I$(top_srcdir)/addressbook/gui/contact-editor \ - -I$(top_srcdir)/addressbook/gui/contact-list-editor \ - -I$(top_srcdir)/addressbook/gui/widgets \ - -I$(top_srcdir)/a11y/addressbook \ - -DEVOLUTION_ETSPECDIR=\""$(etspecdir)"\" \ - -DEVOLUTION_GALVIEWSDIR=\""$(viewsdir)"\" \ - -DEVOLUTION_GLADEDIR=\""$(gladedir)"\" \ - -DEVOLUTION_LOCALEDIR=\""$(localedir)"\" \ - -DEVOLUTION_UIDIR=\""$(evolutionuidir)"\" \ - -DPREFIX=\""$(prefix)"\" \ - $(LDAP_CFLAGS) \ - $(EVOLUTION_ADDRESSBOOK_CFLAGS) - -module_LTLIBRARIES = libevolution-module-addressbook.la - -libevolution_module_addressbook_la_SOURCES = \ - evolution-module-addressbook.c \ - addressbook-config.c \ - addressbook-config.h \ - autocompletion-config.c \ - autocompletion-config.h \ - eab-composer-util.c \ - eab-composer-util.h \ - e-book-shell-backend.c \ - e-book-shell-backend.h \ - e-book-shell-content.c \ - e-book-shell-content.h \ - e-book-shell-migrate.c \ - e-book-shell-migrate.h \ - e-book-shell-sidebar.c \ - e-book-shell-sidebar.h \ - e-book-shell-view.c \ - e-book-shell-view.h \ - e-book-shell-view-actions.c \ - e-book-shell-view-actions.h \ - e-book-shell-view-private.c \ - e-book-shell-view-private.h - -if ENABLE_SMIME -SMIME_LIB=$(top_builddir)/smime/gui/libevolution-smime.la -endif - -libevolution_module_addressbook_la_LIBADD = \ - $(SMIME_LIB) \ - $(top_builddir)/e-util/libeutil.la \ - $(top_builddir)/composer/libcomposer.la \ - $(top_builddir)/addressbook/printing/libecontactprint.la \ - $(top_builddir)/shell/libeshell.la \ - $(top_builddir)/addressbook/gui/merging/libeabbookmerging.la \ - $(top_builddir)/addressbook/gui/widgets/libeabwidgets.la \ - $(top_builddir)/filter/libfilter.la \ - $(top_builddir)/addressbook/util/libeabutil.la \ - $(top_builddir)/addressbook/gui/contact-editor/libecontacteditor.la \ - $(top_builddir)/addressbook/gui/contact-list-editor/libecontactlisteditor.la \ - $(top_builddir)/widgets/table/libetable.la \ - $(top_builddir)/widgets/text/libetext.la \ - $(top_builddir)/widgets/misc/libemiscwidgets.la \ - $(top_builddir)/widgets/menus/libmenus.la \ - $(top_builddir)/addressbook/importers/libevolution-addressbook-importers.la \ - $(EVOLUTION_ADDRESSBOOK_LIBS) $(LDAP_LIBS) - - -libevolution_module_addressbook_la_LDFLAGS = \ - -module -avoid-version $(NO_UNDEFINED) - -# GConf schemas - -schemadir = $(GCONF_SCHEMA_FILE_DIR) -schema_in_files = apps_evolution_addressbook.schemas.in -schema_DATA = $(schema_in_files:.schemas.in=.schemas) - -@INTLTOOL_SCHEMAS_RULE@ - -if OS_WIN32 -install-data-local: - if test -z "$(DESTDIR)" ; then \ - for p in $(schema_DATA) ; do \ - (echo set GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE); \ - echo $(GCONFTOOL) --makefile-install-rule $$p) >_temp.bat; \ - cmd /c _temp.bat; \ - done \ - fi -else -install-data-local: - if test -z "$(DESTDIR)" ; then \ - for p in $(schema_DATA) ; do \ - GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $$p; \ - done \ - fi -endif - -glade_DATA = \ - ldap-config.glade - -DISTCLEANFILES = $(schema_DATA) - -EXTRA_DIST = \ - $(glade_DATA) \ - $(schema_in_files) \ - openldap-extract.h - -dist-hook: - cd $(distdir); rm -f $(BUILT_SOURCES) - -if ENABLE_PURIFY -PLINK = $(LIBTOOL) --mode=link $(PURIFY) $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ - -all-local: evolution-addressbook.pure - -evolution-addressbook.pure: evolution-addressbook - @rm -f evolution-addressbook.pure - $(PLINK) $(evolution_addressbook_LDFLAGS) $(evolution_addressbook_OBJECTS) $(evolution_addressbook_LDADD) $(LIBS) - -endif - --include $(top_srcdir)/git.mk diff --git a/addressbook/gui/component/addressbook-config.c b/addressbook/gui/component/addressbook-config.c deleted file mode 100644 index e663de03da..0000000000 --- a/addressbook/gui/component/addressbook-config.c +++ /dev/null @@ -1,1250 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Chris Toshok - * Chris Lahey - * Michael Zucchi - * And no doubt others ... - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -/*#define STANDALONE*/ - -#include - -#include -#include -#include - -#include -#include - -#ifdef G_OS_WIN32 -/* Include early and work around DATADIR lossage */ -#define DATADIR crap_DATADIR -#include -#undef DATADIR -#endif - -#include - -#include "addressbook.h" -#include "addressbook-config.h" - -#include "e-util/e-error.h" -#include "e-util/e-util-private.h" - -#include "addressbook/gui/widgets/eab-config.h" - -#define d(x) - -#ifdef HAVE_LDAP -#ifndef G_OS_WIN32 -#include -#ifndef SUNLDAP -#include -#endif -#else -#include -#include "openldap-extract.h" -#endif -#endif - -#define LDAP_PORT_STRING "389" -#define LDAPS_PORT_STRING "636" - -#define GLADE_FILE_NAME "ldap-config.glade" - -GtkWidget* supported_bases_create_table (gchar *name, gchar *string1, gchar *string2, - gint num1, gint num2); - -/* default objectclasses */ -#define TOP "top" -#define PERSON "person" -#define ORGANIZATIONALPERSON "organizationalPerson" -#define INETORGPERSON "inetOrgPerson" -#define EVOLUTIONPERSON "evolutionPerson" -#define CALENTRY "calEntry" - - -typedef struct _AddressbookSourceDialog AddressbookSourceDialog; - -struct _AddressbookSourceDialog { - GladeXML *gui; - - EABConfig *config; /* the config manager */ - - GtkWidget *window; - - /* Source selection (druid only) */ - ESourceList *source_list; - GSList *menu_source_groups; - - /* ESource we're currently editing */ - ESource *source; - /* The original source in edit mode. Also used to flag when we are in edit mode. */ - ESource *original_source; - - /* Source group we're creating/editing a source in */ - ESourceGroup *source_group; - - /* info page fields */ - GtkWidget *host; - GtkWidget *auth_combobox; - AddressbookLDAPAuthType auth; - GtkWidget *auth_principal; - - /* connecting page fields */ - GtkWidget *port_comboentry; - GtkWidget *ssl_combobox; - AddressbookLDAPSSLType ssl; - - /* searching page fields */ - GtkWidget *rootdn; - AddressbookLDAPScopeType scope; - GtkWidget *scope_combobox; - GtkWidget *search_filter; - GtkWidget *timeout_scale; - GtkWidget *limit_spinbutton; - GtkWidget *canbrowsecheck; - - /* display name page fields */ - GtkWidget *display_name; -}; - - - -#ifdef HAVE_LDAP - -static const gchar * -ldap_unparse_auth (AddressbookLDAPAuthType auth_type) -{ - switch (auth_type) { - case ADDRESSBOOK_LDAP_AUTH_NONE: - return "none"; - case ADDRESSBOOK_LDAP_AUTH_SIMPLE_EMAIL: - return "ldap/simple-email"; - case ADDRESSBOOK_LDAP_AUTH_SIMPLE_BINDDN: - return "ldap/simple-binddn"; - default: - g_return_val_if_reached ("none"); - } -} - -static AddressbookLDAPAuthType -ldap_parse_auth (const gchar *auth) -{ - if (!auth) - return ADDRESSBOOK_LDAP_AUTH_NONE; - - if (!strcmp (auth, "ldap/simple-email") || !strcmp (auth, "simple")) - return ADDRESSBOOK_LDAP_AUTH_SIMPLE_EMAIL; - else if (!strcmp (auth, "ldap/simple-binddn")) - return ADDRESSBOOK_LDAP_AUTH_SIMPLE_BINDDN; - else - return ADDRESSBOOK_LDAP_AUTH_NONE; -} - -static const gchar * -ldap_unparse_scope (AddressbookLDAPScopeType scope_type) -{ - switch (scope_type) { - case ADDRESSBOOK_LDAP_SCOPE_BASE: - return "base"; - case ADDRESSBOOK_LDAP_SCOPE_ONELEVEL: - return "one"; - case ADDRESSBOOK_LDAP_SCOPE_SUBTREE: - return "sub"; - default: - g_return_val_if_reached (""); - } -} - -static const gchar * -ldap_unparse_ssl (AddressbookLDAPSSLType ssl_type) -{ - switch (ssl_type) { - case ADDRESSBOOK_LDAP_SSL_NEVER: - return "never"; - case ADDRESSBOOK_LDAP_SSL_WHENEVER_POSSIBLE: - return "whenever_possible"; - case ADDRESSBOOK_LDAP_SSL_ALWAYS: - return "always"; - default: - g_return_val_if_reached (""); - } -} - -static AddressbookLDAPSSLType -ldap_parse_ssl (const gchar *ssl) -{ - if (!ssl) - return ADDRESSBOOK_LDAP_SSL_WHENEVER_POSSIBLE; /* XXX good default? */ - - if (!strcmp (ssl, "always")) - return ADDRESSBOOK_LDAP_SSL_ALWAYS; - else if (!strcmp (ssl, "never")) - return ADDRESSBOOK_LDAP_SSL_NEVER; - else - return ADDRESSBOOK_LDAP_SSL_WHENEVER_POSSIBLE; -} - -static const gchar * -ldap_get_ssl_tooltip (AddressbookLDAPSSLType ssl_type) -{ - switch (ssl_type) { - case ADDRESSBOOK_LDAP_SSL_ALWAYS: - return _("Selecting this option means that Evolution will only connect to your LDAP server if your LDAP server supports SSL."); - case ADDRESSBOOK_LDAP_SSL_WHENEVER_POSSIBLE: - return _("Selecting this option means that Evolution will only connect to your LDAP server if your LDAP server supports TLS."); - case ADDRESSBOOK_LDAP_SSL_NEVER: - return _("Selecting this option means that your server does not support either SSL or TLS. This means that your connection will be insecure, and that you will be vulnerable to security exploits."); - } - - return NULL; -} - -static gboolean -source_to_uri_parts (ESource *source, gchar **host, gchar **rootdn, AddressbookLDAPScopeType *scope, gchar **search_filter, gint *port) -{ - gchar *uri; - LDAPURLDesc *lud; - gint ldap_error; - - g_return_val_if_fail (source, FALSE); - - uri = e_source_get_uri (source); - ldap_error = ldap_url_parse ((gchar *) uri, &lud); - g_free (uri); - - if (ldap_error != LDAP_SUCCESS) - return FALSE; - - if (host) - *host = g_strdup (lud->lud_host ? lud->lud_host : ""); - if (rootdn) - *rootdn = g_strdup (lud->lud_dn ? lud->lud_dn : ""); - if (port) - *port = lud->lud_port ? lud->lud_port : LDAP_PORT; - if (scope) - *scope = lud->lud_scope == LDAP_SCOPE_BASE ? ADDRESSBOOK_LDAP_SCOPE_BASE : - lud->lud_scope == LDAP_SCOPE_ONELEVEL ? ADDRESSBOOK_LDAP_SCOPE_ONELEVEL : - lud->lud_scope == LDAP_SCOPE_SUBTREE ? ADDRESSBOOK_LDAP_SCOPE_SUBTREE : - ADDRESSBOOK_LDAP_SCOPE_ONELEVEL; - if (search_filter && lud->lud_filter) - *search_filter = g_strdup (lud->lud_filter); - - ldap_free_urldesc (lud); - return TRUE; -} - -static gboolean -source_group_is_remote (ESourceGroup *group) -{ - return strncmp ("ldap:", e_source_group_peek_base_uri (group), 5) == 0; -} - -/* ldap api foo */ -static LDAP * -addressbook_ldap_init (GtkWidget *window, ESource *source) -{ - LDAP *ldap; - gchar *host; - gint port; - gint ldap_error; - gint protocol_version = LDAP_VERSION3; - - if (!source_to_uri_parts (source, &host, NULL, NULL, NULL, &port)) - return NULL; - - if (!(ldap = ldap_init (host, port))) { - e_error_run ((GtkWindow *) window, "addressbook:ldap-init", NULL); - goto done; - } - - ldap_error = ldap_set_option (ldap, LDAP_OPT_PROTOCOL_VERSION, &protocol_version); - if (LDAP_SUCCESS != ldap_error) - g_warning ("failed to set protocol version to LDAPv3"); - - /* XXX do TLS if it's configured in */ - - done: - g_free (host); - return ldap; -} - -static gint -addressbook_ldap_auth (GtkWidget *window, LDAP *ldap) -{ - gint ldap_error; - - /* XXX use auth info from source */ - ldap_error = ldap_simple_bind_s (ldap, NULL, NULL); - if (LDAP_SUCCESS != ldap_error) - e_error_run ((GtkWindow *) window, "addressbook:ldap-auth", NULL); - - return ldap_error; -} - -static gint -addressbook_root_dse_query (AddressbookSourceDialog *dialog, LDAP *ldap, - const gchar **attrs, LDAPMessage **resp) -{ - gint ldap_error; - struct timeval timeout; - - timeout.tv_sec = (gint) gtk_adjustment_get_value (GTK_RANGE(dialog->timeout_scale)->adjustment); - timeout.tv_usec = 0; - - ldap_error = ldap_search_ext_s (ldap, - LDAP_ROOT_DSE, LDAP_SCOPE_BASE, - "(objectclass=*)", - (gchar **) attrs, 0, NULL, NULL, &timeout, LDAP_NO_LIMIT, resp); - if (LDAP_SUCCESS != ldap_error) - e_error_run (GTK_WINDOW (dialog->window), "addressbook:ldap-search-base", NULL); - - return ldap_error; -} - -/* searching page */ -GtkWidget* -supported_bases_create_table (gchar *name, gchar *string1, gchar *string2, gint num1, gint num2) -{ - GtkWidget *table, *scrolled; - GtkTreeSelection *selection; - GtkCellRenderer *renderer; - GtkListStore *model; - - scrolled = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_IN); - - model = gtk_list_store_new (1, G_TYPE_STRING); - table = gtk_tree_view_new_with_model ((GtkTreeModel *) model); - g_object_unref (model); - renderer = gtk_cell_renderer_text_new (); - gtk_tree_view_insert_column_with_attributes ((GtkTreeView *) table, -1, _("Base"), renderer, "text", 0, NULL); - gtk_tree_view_set_headers_visible ((GtkTreeView *) table, FALSE); - selection = gtk_tree_view_get_selection ((GtkTreeView *) table); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); - - gtk_container_add (GTK_CONTAINER (scrolled), table); - g_object_set_data((GObject *)scrolled, "table", table); - - return scrolled; -} - -static gboolean -do_ldap_root_dse_query (AddressbookSourceDialog *sdialog, GtkListStore *model, ESource *source) -{ - LDAP *ldap; - const gchar *attrs[2]; - gint ldap_error; - gchar **values; - LDAPMessage *resp; - gint i; - - ldap = addressbook_ldap_init (sdialog->window, source); - if (!ldap) - return FALSE; - - if (LDAP_SUCCESS != addressbook_ldap_auth (sdialog->window, ldap)) - goto fail; - - attrs[0] = "namingContexts"; - attrs[1] = NULL; - - ldap_error = addressbook_root_dse_query (sdialog, ldap, attrs, &resp); - - if (ldap_error != LDAP_SUCCESS) - goto fail; - - values = ldap_get_values (ldap, resp, "namingContexts"); - if (!values || values[0] == NULL || strlen (values[0]) == 0) { - e_error_run (GTK_WINDOW (sdialog->window), "addressbook:ldap-search-base", NULL); - goto fail; - } - - for (i = 0; values[i]; i++) { - GtkTreeIter iter; - - gtk_list_store_append (model, &iter); - gtk_list_store_set (model, &iter, 0, values[i], -1); - } - - ldap_value_free (values); - ldap_unbind_s (ldap); - return TRUE; - - fail: - ldap_unbind_s (ldap); - return FALSE; -} - -static void -search_base_selection_model_changed (GtkTreeSelection *selection, GtkWidget *dialog) -{ - gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), - GTK_RESPONSE_OK, - gtk_tree_selection_get_selected(selection, NULL, NULL)); -} - -static void -query_for_supported_bases (GtkWidget *button, AddressbookSourceDialog *sdialog) -{ - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeView *table; - GtkWidget *dialog; - GtkWidget *supported_bases_table; - GladeXML *gui; - GtkTreeIter iter; - gchar *gladefile; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - GLADE_FILE_NAME, - NULL); - gui = glade_xml_new (gladefile, "supported-bases-dialog", NULL); - g_free (gladefile); - - dialog = glade_xml_get_widget (gui, "supported-bases-dialog"); - - gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (sdialog->window)); - gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); - - gtk_widget_ensure_style (dialog); - gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 0); - gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area), 12); - - supported_bases_table = glade_xml_get_widget (gui, "supported-bases-table"); - gtk_widget_show_all (supported_bases_table); - - table = g_object_get_data (G_OBJECT (supported_bases_table), "table"); - model = gtk_tree_view_get_model (table); - selection = gtk_tree_view_get_selection (table); - g_signal_connect (selection, "changed", G_CALLBACK (search_base_selection_model_changed), dialog); - search_base_selection_model_changed (selection, dialog); - - if (do_ldap_root_dse_query (sdialog, GTK_LIST_STORE (model), sdialog->source)) { - gtk_widget_show (dialog); - - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK - && gtk_tree_selection_get_selected (selection, &model, &iter)) { - gchar *dn; - - gtk_tree_model_get (model, &iter, 0, &dn, -1); - gtk_entry_set_text((GtkEntry *)sdialog->rootdn, dn); - g_free(dn); - } - } - - gtk_widget_destroy (dialog); -} - -#endif /* HAVE_LDAP */ - -GtkWidget* -addressbook_config_create_new_source (GtkWidget *parent) -{ - return addressbook_config_edit_source(parent, NULL); -} - -/* ********************************************************************** */ - -static void -eabc_type_changed(GtkComboBox *dropdown, AddressbookSourceDialog *sdialog) -{ - gint id = gtk_combo_box_get_active(dropdown); - GtkTreeModel *model; - GtkTreeIter iter; - - model = gtk_combo_box_get_model(dropdown); - if (id == -1 || !gtk_tree_model_iter_nth_child(model, &iter, NULL, id)) - return; - - /* TODO: when we change the group type, we lose all of the pre-filled dialog info */ - - gtk_tree_model_get(model, &iter, 1, &sdialog->source_group, -1); - /* HACK: doesn't work if you don't do this */ - e_source_set_absolute_uri(sdialog->source, NULL); - e_source_set_group(sdialog->source, sdialog->source_group); - - /* BIG HACK: We load the defaults for each type here. - I guess plugins will have to use the do it in their factory callbacks */ - if (!strncmp(e_source_group_peek_base_uri(sdialog->source_group), "groupwise:", 10)) { - GSList *l; - ESource *source; - gchar *tmp; - - l = e_source_group_peek_sources(sdialog->source_group); - if (l && l->data ) { - source = l->data; - e_source_set_property(sdialog->source, "auth", e_source_get_property(source, "auth")); - e_source_set_property(sdialog->source, "user", e_source_get_property(source, "user")); - e_source_set_property(sdialog->source, "user_ssl", e_source_get_property(source, "use_ssl")); - } - - e_source_set_property(sdialog->source, "auth-domain", "Groupwise"); - tmp = g_strconcat (";", e_source_peek_name(sdialog->source), NULL); - e_source_set_relative_uri (sdialog->source, tmp); - g_free (tmp); -#ifdef HAVE_LDAP - } else if (!strncmp(e_source_group_peek_base_uri(sdialog->source_group), "ldap:", 5)) { - gchar *tmp; - - tmp = g_strdup_printf ("%s:%s/%s?" /* trigraph prevention */ "?%s", - "", LDAP_PORT_STRING, - "", - "one"); - e_source_set_relative_uri (sdialog->source, tmp); - g_free (tmp); - e_source_set_property(sdialog->source, "timeout", "3"); - e_source_set_property(sdialog->source, "limit", "100"); -#endif - } else { - e_source_set_relative_uri (sdialog->source, e_source_peek_uid (sdialog->source)); - } - - e_config_target_changed((EConfig *)sdialog->config, E_CONFIG_TARGET_CHANGED_REBUILD); -} - -static GtkWidget * -eabc_general_type(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - GtkComboBox *dropdown; - GtkCellRenderer *cell; - GtkListStore *store; - GtkTreeIter iter; - GSList *l; - GtkWidget *w, *label; - gint i, row = 0; - - if (old) - return old; - - w = gtk_hbox_new(FALSE, 6); - label = gtk_label_new_with_mnemonic(_("_Type:")); - gtk_box_pack_start((GtkBox *)w, label, FALSE, FALSE, 0); - - dropdown = (GtkComboBox *)gtk_combo_box_new(); - cell = gtk_cell_renderer_text_new(); - store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); - i = 0; - for (l=sdialog->menu_source_groups;l;l=g_slist_next(l)) { - ESourceGroup *group = l->data; - - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, e_source_group_peek_name(group), 1, group, -1); - if (e_source_peek_group(sdialog->source) == group) - row = i; - i++; - } - - gtk_cell_layout_pack_start((GtkCellLayout *)dropdown, cell, TRUE); - gtk_cell_layout_set_attributes((GtkCellLayout *)dropdown, cell, "text", 0, NULL); - gtk_combo_box_set_model(dropdown, (GtkTreeModel *)store); - gtk_combo_box_set_active(dropdown, -1); - gtk_combo_box_set_active(dropdown, row); - g_signal_connect(dropdown, "changed", G_CALLBACK(eabc_type_changed), sdialog); - gtk_widget_show((GtkWidget *)dropdown); - gtk_box_pack_start((GtkBox *)w, (GtkWidget *)dropdown, TRUE, TRUE, 0); - gtk_label_set_mnemonic_widget((GtkLabel *)label, (GtkWidget *)dropdown); - - gtk_box_pack_start((GtkBox *)parent, (GtkWidget *)w, FALSE, FALSE, 0); - - gtk_widget_show_all(w); - - return (GtkWidget *)w; -} - -static void -name_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - e_source_set_name (sdialog->source, gtk_entry_get_text (GTK_ENTRY (sdialog->display_name))); -} - -static void -offline_status_changed_cb (GtkWidget *widget, AddressbookSourceDialog *sdialog) -{ - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) - e_source_set_property (sdialog->source, "offline_sync", "1"); - else - e_source_set_property (sdialog->source, "offline_sync", "0"); - -} - -static GtkWidget * -eabc_general_name(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - const gchar *uri; - GtkWidget *w; - GladeXML *gui; - gchar *gladefile; - - if (old) - return old; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - GLADE_FILE_NAME, - NULL); - gui = glade_xml_new (gladefile, item->label, NULL); - g_free (gladefile); - - w = glade_xml_get_widget(gui, item->label); - gtk_box_pack_start((GtkBox *)parent, w, FALSE, FALSE, 0); - - sdialog->display_name = glade_xml_get_widget (gui, "account-editor-display-name-entry"); - g_signal_connect(sdialog->display_name, "changed", G_CALLBACK(name_changed_cb), sdialog); - gtk_entry_set_text((GtkEntry *)sdialog->display_name, e_source_peek_name(sdialog->source)); - - /* Hardcoded: groupwise can't edit the name (or anything else) */ - if (sdialog->original_source) { - uri = e_source_group_peek_base_uri (sdialog->source_group); - if (uri && strncmp(uri, "groupwise:", 10) == 0) { - gtk_widget_set_sensitive (GTK_WIDGET(sdialog->display_name), FALSE); - } - } - - g_object_unref(gui); - - return w; -} - - -static GtkWidget * -eabc_general_offline(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - GtkWidget *offline_setting; - const gchar *offline_sync; - gboolean is_local_book; - - is_local_book = g_str_has_prefix (e_source_group_peek_base_uri (sdialog->source_group), "file:"); - offline_sync = e_source_get_property (sdialog->source, "offline_sync"); - if (old) - return old; - else { - offline_setting = gtk_check_button_new_with_mnemonic (_("Copy _book content locally for offline operation")); - gtk_widget_show (offline_setting); - gtk_container_add (GTK_CONTAINER (parent), offline_setting); - g_signal_connect (offline_setting, "toggled", G_CALLBACK (offline_status_changed_cb), sdialog); - - } - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (offline_setting), (offline_sync && g_str_equal (offline_sync, "1")) ? TRUE : FALSE); - if (is_local_book) - gtk_widget_hide (offline_setting); - return offline_setting; - -} - -#ifdef HAVE_LDAP -static gchar * -form_ldap_search_filter (GtkWidget *w) -{ - gchar *filter; - const gchar *search_filter = gtk_entry_get_text ((GtkEntry *) w); - - /* this function can be used to format the search filter entered */ - if ((strlen (search_filter) !=0) && *search_filter != '(' && *(search_filter + (strlen (search_filter-1))) != ')') - filter = g_strdup_printf ("(%s)", search_filter); - else - filter = g_strdup_printf ("%s", search_filter); - - return filter; -} - -static void -url_changed(AddressbookSourceDialog *sdialog) -{ - gchar *str, *search_filter; - - search_filter = form_ldap_search_filter (sdialog->search_filter); - str = g_strdup_printf ("%s:%s/%s?" /* trigraph prevention */ "?%s?%s", - gtk_entry_get_text (GTK_ENTRY (sdialog->host)), - gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (sdialog->port_comboentry)))), - gtk_entry_get_text (GTK_ENTRY (sdialog->rootdn)), - ldap_unparse_scope (sdialog->scope), - search_filter); - e_source_set_relative_uri (sdialog->source, str); - g_free (search_filter); - g_free (str); -} - -static void -host_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - url_changed(sdialog); -} - -static void -port_entry_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - const gchar *port = gtk_entry_get_text((GtkEntry *)w); - - if (!strcmp (port, LDAPS_PORT_STRING)) { - sdialog->ssl = ADDRESSBOOK_LDAP_SSL_ALWAYS; - gtk_combo_box_set_active (GTK_COMBO_BOX (sdialog->ssl_combobox), sdialog->ssl); - gtk_widget_set_sensitive (sdialog->ssl_combobox, FALSE); - } else { - gtk_widget_set_sensitive (sdialog->ssl_combobox, TRUE); - } - - url_changed(sdialog); -} - -static void -ssl_combobox_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - sdialog->ssl = gtk_combo_box_get_active (GTK_COMBO_BOX (w)); - e_source_set_property (sdialog->source, "ssl", ldap_unparse_ssl (sdialog->ssl)); - - gtk_widget_set_tooltip_text (sdialog->ssl_combobox, ldap_get_ssl_tooltip (sdialog->ssl)); -} - - -static GtkWidget * -eabc_general_host(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - const gchar *tmp; - GtkWidget *w; - gchar *uri, port[16]; - LDAPURLDesc *lud; - GladeXML *gui; - gchar *gladefile; - - if (!source_group_is_remote(sdialog->source_group)) - return NULL; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - GLADE_FILE_NAME, - NULL); - gui = glade_xml_new (gladefile, item->label, NULL); - g_free (gladefile); - - w = glade_xml_get_widget(gui, item->label); - gtk_box_pack_start((GtkBox *)parent, w, FALSE, FALSE, 0); - - uri = e_source_get_uri(sdialog->source); - if (ldap_url_parse(uri, &lud) != LDAP_SUCCESS) - lud = NULL; - g_free(uri); - - sdialog->host = glade_xml_get_widget (gui, "server-name-entry"); - gtk_entry_set_text((GtkEntry *)sdialog->host, lud && lud->lud_host ? lud->lud_host : ""); - g_signal_connect (sdialog->host, "changed", G_CALLBACK (host_changed_cb), sdialog); - - sdialog->port_comboentry = glade_xml_get_widget (gui, "port-comboentry"); - gtk_widget_set_has_tooltip (sdialog->port_comboentry, TRUE); - gtk_widget_set_tooltip_text (sdialog->port_comboentry, _("This is the port on the LDAP server that Evolution will try to connect to. A list of standard ports has been provided. Ask your system administrator what port you should specify.")); - sprintf(port, "%u", lud && lud->lud_port? lud->lud_port : LDAP_PORT); - gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (sdialog->port_comboentry))), port); - g_signal_connect (gtk_bin_get_child (GTK_BIN (sdialog->port_comboentry)), "changed", G_CALLBACK (port_entry_changed_cb), sdialog); - - if (lud) - ldap_free_urldesc (lud); - - sdialog->ssl_combobox = glade_xml_get_widget (gui, "ssl-combobox"); - gtk_widget_set_has_tooltip (sdialog->ssl_combobox, TRUE); - tmp = e_source_get_property (sdialog->source, "ssl"); - sdialog->ssl = tmp ? ldap_parse_ssl (tmp) : ADDRESSBOOK_LDAP_SSL_WHENEVER_POSSIBLE; - gtk_combo_box_set_active (GTK_COMBO_BOX (sdialog->ssl_combobox), sdialog->ssl); - gtk_widget_set_tooltip_text (sdialog->ssl_combobox, ldap_get_ssl_tooltip (sdialog->ssl)); - gtk_widget_set_sensitive (sdialog->ssl_combobox, strcmp (port, LDAPS_PORT_STRING) != 0); - g_signal_connect (sdialog->ssl_combobox, "changed", G_CALLBACK (ssl_combobox_changed_cb), sdialog); - - g_object_unref(gui); - - return w; -} - -static void -auth_entry_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - const gchar *principal = gtk_entry_get_text((GtkEntry *)w); - - /* seems messy ... but the api is */ - switch (sdialog->auth) { - case ADDRESSBOOK_LDAP_AUTH_SIMPLE_BINDDN: - e_source_set_property(sdialog->source, "email_addr", NULL); - e_source_set_property(sdialog->source, "binddn", principal); - break; - case ADDRESSBOOK_LDAP_AUTH_SIMPLE_EMAIL: - e_source_set_property(sdialog->source, "binddn", NULL); - e_source_set_property(sdialog->source, "email_addr", principal); - break; - case ADDRESSBOOK_LDAP_AUTH_NONE: - default: - e_source_set_property(sdialog->source, "email_addr", NULL); - e_source_set_property(sdialog->source, "binddn", NULL); - break; - } -} - -static void -auth_combobox_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - sdialog->auth = gtk_combo_box_get_active (GTK_COMBO_BOX (w)); - e_source_set_property (sdialog->source, "auth", ldap_unparse_auth (sdialog->auth)); - - /* make sure the right property is set for the auth - ugh, funny api */ - auth_entry_changed_cb(sdialog->auth_principal, sdialog); -} - -static GtkWidget * -eabc_general_auth(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - GtkWidget *w; - const gchar *tmp; - GladeXML *gui; - gchar *gladefile; - - if (!source_group_is_remote(sdialog->source_group)) - return NULL; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - GLADE_FILE_NAME, - NULL); - gui = glade_xml_new (gladefile, item->label, NULL); - g_free (gladefile); - - w = glade_xml_get_widget(gui, item->label); - gtk_box_pack_start((GtkBox *)parent, w, FALSE, FALSE, 0); - - sdialog->auth_combobox = glade_xml_get_widget (gui, "auth-combobox"); - gtk_widget_set_has_tooltip (sdialog->auth_combobox, TRUE); - gtk_widget_set_tooltip_text (sdialog->auth_combobox, _("This is the method Evolution will use to authenticate you. Note that setting this to \"Email Address\" requires anonymous access to your LDAP server.")); - tmp = e_source_get_property(sdialog->source, "auth"); - sdialog->auth = tmp ? ldap_parse_auth(tmp) : ADDRESSBOOK_LDAP_AUTH_NONE; - gtk_combo_box_set_active (GTK_COMBO_BOX (sdialog->auth_combobox), sdialog->auth); - g_signal_connect (sdialog->auth_combobox, "changed", G_CALLBACK(auth_combobox_changed_cb), sdialog); - - sdialog->auth_principal = glade_xml_get_widget (gui, "auth-entry"); - switch (sdialog->auth) { - case ADDRESSBOOK_LDAP_AUTH_SIMPLE_EMAIL: - tmp = e_source_get_property(sdialog->source, "email_addr"); - break; - case ADDRESSBOOK_LDAP_AUTH_SIMPLE_BINDDN: - tmp = e_source_get_property(sdialog->source, "binddn"); - break; - case ADDRESSBOOK_LDAP_AUTH_NONE: - default: - tmp = ""; - break; - } - gtk_entry_set_text((GtkEntry *)sdialog->auth_principal, tmp?tmp:""); - g_signal_connect (sdialog->auth_principal, "changed", G_CALLBACK (auth_entry_changed_cb), sdialog); - - g_object_unref(gui); - - return w; -} - -static void -rootdn_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - url_changed(sdialog); -} - -static void -search_filter_changed_cb (GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - url_changed (sdialog); -} - -static void -scope_combobox_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - sdialog->scope = gtk_combo_box_get_active (GTK_COMBO_BOX (w)); - url_changed(sdialog); -} - -static GtkWidget * -eabc_details_search(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - GtkWidget *w; - LDAPURLDesc *lud; - gchar *uri; - GladeXML *gui; - gchar *gladefile; - - if (!source_group_is_remote(sdialog->source_group)) - return NULL; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - GLADE_FILE_NAME, - NULL); - gui = glade_xml_new (gladefile, item->label, NULL); - g_free (gladefile); - - w = glade_xml_get_widget(gui, item->label); - gtk_box_pack_start((GtkBox *)parent, w, FALSE, FALSE, 0); - - uri = e_source_get_uri(sdialog->source); - if (ldap_url_parse(uri, &lud) != LDAP_SUCCESS) - lud = NULL; - g_free(uri); - - sdialog->rootdn = glade_xml_get_widget (gui, "rootdn-entry"); - gtk_entry_set_text((GtkEntry *)sdialog->rootdn, lud && lud->lud_dn ? lud->lud_dn : ""); - g_signal_connect (sdialog->rootdn, "changed", G_CALLBACK (rootdn_changed_cb), sdialog); - - sdialog->scope_combobox = glade_xml_get_widget (gui, "scope-combobox"); - gtk_widget_set_has_tooltip (sdialog->scope_combobox, TRUE); - gtk_widget_set_tooltip_text (sdialog->scope_combobox, _("The search scope defines how deep you would like the search to extend down the directory tree. A search scope of \"sub\" will include all entries below your search base. A search scope of \"one\" will only include the entries one level beneath your base.")); - if (lud) { - switch (lud->lud_scope) { - case LDAP_SCOPE_BASE: - sdialog->scope = ADDRESSBOOK_LDAP_SCOPE_BASE; - break; - default: - case LDAP_SCOPE_ONELEVEL: - sdialog->scope = ADDRESSBOOK_LDAP_SCOPE_ONELEVEL; - break; - case LDAP_SCOPE_SUBTREE: - sdialog->scope = ADDRESSBOOK_LDAP_SCOPE_SUBTREE; - break; - } - } - gtk_combo_box_set_active (GTK_COMBO_BOX (sdialog->scope_combobox), sdialog->scope); - g_signal_connect (sdialog->scope_combobox, "changed", G_CALLBACK(scope_combobox_changed_cb), sdialog); - - sdialog->search_filter = glade_xml_get_widget (gui, "search-filter-entry"); - gtk_entry_set_text((GtkEntry *)sdialog->search_filter, lud && lud->lud_filter ? lud->lud_filter : ""); - g_signal_connect (sdialog->search_filter, "changed", G_CALLBACK (search_filter_changed_cb), sdialog); - - g_signal_connect (glade_xml_get_widget(gui, "rootdn-button"), "clicked", - G_CALLBACK(query_for_supported_bases), sdialog); - - if (lud) - ldap_free_urldesc (lud); - - g_object_unref(gui); - - return w; -} - -static void -timeout_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - gchar *timeout; - - timeout = g_strdup_printf("%f", gtk_adjustment_get_value(((GtkRange *)sdialog->timeout_scale)->adjustment)); - e_source_set_property(sdialog->source, "timeout", timeout); - g_free(timeout); -} - -static void -limit_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - gchar limit[16]; - - sprintf(limit, "%d", gtk_spin_button_get_value_as_int((GtkSpinButton *)sdialog->limit_spinbutton)); - e_source_set_property(sdialog->source, "limit", limit); -} - -static void -canbrowse_toggled_cb (GtkWidget *toggle_button, ESource *source) -{ - if (!source || !toggle_button) - return; - - e_source_set_property (source, "can-browse", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle_button)) ? "1" : NULL); -} - -static GtkWidget * -eabc_details_limit(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - GtkWidget *w; - const gchar *tmp; - GladeXML *gui; - gchar *gladefile; - - if (!source_group_is_remote(sdialog->source_group)) - return NULL; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - GLADE_FILE_NAME, - NULL); - gui = glade_xml_new (gladefile, item->label, NULL); - g_free (gladefile); - - w = glade_xml_get_widget(gui, item->label); - gtk_box_pack_start((GtkBox *)parent, w, FALSE, FALSE, 0); - - sdialog->timeout_scale = glade_xml_get_widget (gui, "timeout-scale"); - tmp = e_source_get_property(sdialog->source, "timeout"); - gtk_adjustment_set_value(((GtkRange *)sdialog->timeout_scale)->adjustment, tmp?g_strtod(tmp, NULL):3.0); - g_signal_connect (GTK_RANGE(sdialog->timeout_scale)->adjustment, "value_changed", G_CALLBACK (timeout_changed_cb), sdialog); - - sdialog->limit_spinbutton = glade_xml_get_widget (gui, "download-limit-spinbutton"); - tmp = e_source_get_property(sdialog->source, "limit"); - gtk_spin_button_set_value((GtkSpinButton *)sdialog->limit_spinbutton, tmp?g_strtod(tmp, NULL):100.0); - g_signal_connect (sdialog->limit_spinbutton, "value_changed", G_CALLBACK (limit_changed_cb), sdialog); - - sdialog->canbrowsecheck = glade_xml_get_widget (gui, "canbrowsecheck"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sdialog->canbrowsecheck), e_source_get_property (sdialog->source, "can-browse") && strcmp (e_source_get_property (sdialog->source, "can-browse"), "1") == 0); - g_signal_connect (sdialog->canbrowsecheck, "toggled", G_CALLBACK (canbrowse_toggled_cb), sdialog->source); - - g_object_unref(gui); - - return w; -} -#endif - -static EConfigItem eabc_items[] = { - { E_CONFIG_BOOK, (gchar *) (gchar *) "", }, - { E_CONFIG_PAGE, (gchar *) "00.general", (gchar *) N_("General") }, - { E_CONFIG_SECTION, (gchar *) "00.general/10.display", (gchar *) N_("Address Book") }, - { E_CONFIG_ITEM, (gchar *) "00.general/10.display/10.name", (gchar *) "hbox122", eabc_general_name }, - { E_CONFIG_ITEM, (gchar *) "00.general/10.display/20.offline", NULL, eabc_general_offline }, -#ifdef HAVE_LDAP - { E_CONFIG_SECTION, (gchar *) "00.general/20.server", (gchar *) N_("Server Information") }, - { E_CONFIG_ITEM, (gchar *) "00.general/20.server/00.host", (gchar *) "table31", eabc_general_host }, - { E_CONFIG_SECTION, (gchar *) "00.general/30.auth", (gchar *) N_("Authentication") }, - { E_CONFIG_ITEM, (gchar *) "00.general/30.auth/00.auth", (gchar *) "table32", eabc_general_auth }, - - { E_CONFIG_PAGE, (gchar *) "10.details", (gchar *) N_("Details") }, - { E_CONFIG_SECTION, (gchar *) "10.details/00.search", (gchar *) N_("Searching") }, - { E_CONFIG_ITEM, (gchar *) "10.details/00.search/00.search", (gchar *) "table33", eabc_details_search }, - { E_CONFIG_SECTION, (gchar *) "10.details/10.limit", (gchar *) N_("Downloading") }, - { E_CONFIG_ITEM, (gchar *) "10.details/10.limit/00.limit", (gchar *) "table34", eabc_details_limit }, -#endif - { 0 }, -}; - -/* items needed for the 'new addressbook' window */ -static EConfigItem eabc_new_items[] = { - { E_CONFIG_ITEM, (gchar *) "00.general/10.display/00.type", NULL, eabc_general_type }, - { 0 }, -}; - -static void -eabc_commit(EConfig *ec, GSList *items, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - xmlNodePtr xml; -#if d(!)0 - gchar *txt; -#endif - if (sdialog->original_source) { - d(printf("committing addressbook changes\n")); - - /* these api's kinda suck */ - xml = xmlNewNode(NULL, (const guchar *)"dummy"); - e_source_dump_to_xml_node(sdialog->source, xml); - e_source_update_from_xml_node(sdialog->original_source, xml->children, NULL); - xmlFreeNode(xml); -#if d(!)0 - txt = e_source_to_standalone_xml(sdialog->original_source); - printf("source is now:\n%s\n", txt); - g_free(txt); -#endif - } else { - d(printf("committing new source\n")); - e_source_group_add_source(sdialog->source_group, sdialog->source, -1); - e_source_list_sync(sdialog->source_list, NULL); - } - -#if d(!)0 - txt = e_source_to_standalone_xml(sdialog->source); - printf("running source is now:\n%s\n", txt); - g_free(txt); -#endif -} - -static void -eabc_free(EConfig *ec, GSList *items, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - - g_slist_free(items); - - g_object_unref(sdialog->source); - if (sdialog->original_source) - g_object_unref(sdialog->original_source); - if (sdialog->source_list) - g_object_unref(sdialog->source_list); - g_slist_free(sdialog->menu_source_groups); - - g_object_unref(sdialog->gui); - - g_free(sdialog); -} - -static gboolean -eabc_check_complete(EConfig *ec, const gchar *pageid, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - gint valid = TRUE; - const gchar *tmp; - ESource *source; - - d(printf("check complete, pageid = '%s'\n", pageid?pageid:"")); - /* have name, and unique */ - tmp = e_source_peek_name(sdialog->source); - valid = tmp && tmp[0] != 0 - && ((source = e_source_group_peek_source_by_name(sdialog->source_group, tmp)) == NULL - || source == sdialog->original_source); - -#ifdef HAVE_LDAP - if (valid && source_group_is_remote(sdialog->source_group)) { - gchar *uri = e_source_get_uri(sdialog->source); - LDAPURLDesc *lud; - - /* check host and port set */ - if (ldap_url_parse(uri, &lud) == LDAP_SUCCESS) { - valid = lud->lud_host != NULL - && lud->lud_host[0] != 0 - && lud->lud_port != 0; - ldap_free_urldesc (lud); - } else - valid = FALSE; - g_free(uri); - - /* check auth name provided if auth set */ - if (valid && (tmp = e_source_get_property(sdialog->source, "auth"))) { - switch (ldap_parse_auth(tmp)) { - case ADDRESSBOOK_LDAP_AUTH_SIMPLE_EMAIL: - tmp = e_source_get_property(sdialog->source, "email_addr"); - break; - case ADDRESSBOOK_LDAP_AUTH_SIMPLE_BINDDN: - tmp = e_source_get_property(sdialog->source, "binddn"); - break; - default: - tmp = "dummy"; - break; - } - valid = tmp && tmp[0]; - } - - /* check timeout isn't too short (why don't we just force it?) */ - if (valid) { - tmp = e_source_get_property(sdialog->source, "timeout"); - valid = tmp && g_strtod(tmp, NULL) > 0.0; - } - } -#endif - return valid; -} - -/* debug only: */ -#if d(!)0 -static void -source_changed(ESource *source, AddressbookSourceDialog *sdialog) -{ - gchar *xml; - - xml = e_source_to_standalone_xml(source); - printf("source changed:\n%s\n", xml); - g_free(xml); -} -#endif - -GtkWidget* -addressbook_config_edit_source (GtkWidget *parent, ESource *source) -{ - AddressbookSourceDialog *sdialog = g_new0 (AddressbookSourceDialog, 1); - EABConfig *ec; - gint i; - GSList *items = NULL; - EABConfigTargetSource *target; - gchar *xml; - gchar *gladefile; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - GLADE_FILE_NAME, - NULL); - sdialog->gui = glade_xml_new (gladefile, "account-editor-notebook", NULL); - g_free (gladefile); - - if (source) { - sdialog->original_source = source; - g_object_ref(source); - sdialog->source_group = e_source_peek_group (source); - xml = e_source_to_standalone_xml(source); - sdialog->source = e_source_new_from_standalone_xml(xml); - g_free(xml); - } else { - GConfClient *gconf; - GSList *l; - - sdialog->source = e_source_new("", ""); - gconf = gconf_client_get_default(); - sdialog->source_list = e_source_list_new_for_gconf(gconf, "/apps/evolution/addressbook/sources"); - l = e_source_list_peek_groups(sdialog->source_list); - if (!l) { - g_warning ("Address Book source groups are missing! Check your GConf setup."); - g_object_unref (gconf); - g_free (sdialog); - return NULL; - } - - sdialog->menu_source_groups = g_slist_copy(l); -#ifndef HAVE_LDAP - for (;l;l = g_slist_next(l)) - if (!strncmp("ldap:", e_source_group_peek_base_uri(l->data), 5)) - sdialog->menu_source_groups = g_slist_remove (sdialog->menu_source_groups, l->data); -#endif - sdialog->source_group = (ESourceGroup *)sdialog->menu_source_groups->data; - for (i=0;eabc_new_items[i].path;i++) - items = g_slist_prepend(items, &eabc_new_items[i]); - g_object_unref(gconf); - } - - /* HACK: doesn't work if you don't do this */ - e_source_set_group(sdialog->source, sdialog->source_group); - -#if d(!)0 - xml = e_source_to_standalone_xml(sdialog->source); - printf("but working standalone xml: %s\n", xml); - g_free(xml); - g_signal_connect(sdialog->source, "changed", source_changed, sdialog); -#endif - - sdialog->config = ec = eab_config_new(E_CONFIG_BOOK, "com.novell.evolution.addressbook.config.accountEditor"); - - for (i=0;eabc_items[i].path;i++) { - if (eabc_items[i].label) - eabc_items[i].label = gettext(eabc_items[i].label); - items = g_slist_prepend(items, &eabc_items[i]); - } - - e_config_add_items((EConfig *)ec, items, eabc_commit, NULL, eabc_free, sdialog); - e_config_add_page_check((EConfig *)ec, NULL, eabc_check_complete, sdialog); - - target = eab_config_target_new_source(ec, sdialog->source); - e_config_set_target((EConfig *)ec, (EConfigTarget *)target); - - if(source) - sdialog->window = e_config_create_window((EConfig *)ec, NULL, _("Address Book Properties")); - else - sdialog->window = e_config_create_window((EConfig *)ec, NULL, _("New Address Book")); - - - /* forces initial validation */ - if (!sdialog->original_source) - e_config_target_changed((EConfig *)ec, E_CONFIG_TARGET_CHANGED_STATE); - - return sdialog->window; -} diff --git a/addressbook/gui/component/addressbook-config.h b/addressbook/gui/component/addressbook-config.h deleted file mode 100644 index 26c1788e51..0000000000 --- a/addressbook/gui/component/addressbook-config.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Chris Toshok - * Chris Lahey - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __ADDRESSBOOK_CONFIG_H__ -#define __ADDRESSBOOK_CONFIG_H__ - -#include -#include - -typedef enum { - ADDRESSBOOK_LDAP_AUTH_NONE, - ADDRESSBOOK_LDAP_AUTH_SIMPLE_EMAIL, - ADDRESSBOOK_LDAP_AUTH_SIMPLE_BINDDN -} AddressbookLDAPAuthType; - -typedef enum { - ADDRESSBOOK_LDAP_SCOPE_ONELEVEL, - ADDRESSBOOK_LDAP_SCOPE_SUBTREE, - ADDRESSBOOK_LDAP_SCOPE_BASE, - ADDRESSBOOK_LDAP_SCOPE_LAST -} AddressbookLDAPScopeType; - -typedef enum { - ADDRESSBOOK_LDAP_SSL_ALWAYS, - ADDRESSBOOK_LDAP_SSL_WHENEVER_POSSIBLE, - ADDRESSBOOK_LDAP_SSL_NEVER -} AddressbookLDAPSSLType; - -GtkWidget* addressbook_config_edit_source (GtkWidget *parent, ESource *source); -GtkWidget* addressbook_config_create_new_source (GtkWidget *parent); - -#endif /* __ADDRESSBOOK_CONFIG_H__ */ diff --git a/addressbook/gui/component/apps_evolution_addressbook.schemas.in b/addressbook/gui/component/apps_evolution_addressbook.schemas.in deleted file mode 100644 index 4a336409df..0000000000 --- a/addressbook/gui/component/apps_evolution_addressbook.schemas.in +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - /schemas/apps/evolution/addressbook/completion/uris - /apps/evolution/addressbook/completion/uris - evolution-addressbook - string - - - EFolderList XML for the list of completion URIs - EFolderList XML for the list of completion URIs. - - - - - /schemas/apps/evolution/addressbook/completion/minimum_query_length - /apps/evolution/addressbook/completion/minimum_query_length - evolution-addressbook - int - 3 - - Autocomplete length - The number of characters that must be typed before Evolution will attempt to autocomplete. - - - - - /schemas/apps/evolution/addressbook/completion/show_address - /apps/evolution/addressbook/completion/show_address - evolution-addressbook - bool - false - - Show autocompleted name with an address - Whether force showing the mail address with the name of the autocompleted contact in the entry. - - - - - - - /schemas/apps/evolution/addressbook/select_names/last_used_uri - /apps/evolution/addressbook/select_names/last_used_uri - evolution-addressbook - string - - - URI for the folder last used in the select names dialog - URI for the folder last used in the select names dialog. - - - - - - - /schemas/apps/evolution/addressbook/display/vpane_position - /apps/evolution/addressbook/display/vpane_position - evolution-addressbook - int - - Vertical pane position - Position of the vertical pane, between the card and list views and the preview pane, in pixels. - - - - - /schemas/apps/evolution/addressbook/display/show_preview - /apps/evolution/addressbook/display/show_preview - evolution-addressbook - bool - true - - Show preview pane - Whether to show the preview pane. - - - - - diff --git a/addressbook/gui/component/autocompletion-config.c b/addressbook/gui/component/autocompletion-config.c deleted file mode 100644 index 370c1a1e7e..0000000000 --- a/addressbook/gui/component/autocompletion-config.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * e-shell-config-autocompletion.h - Configuration page for addressbook autocompletion. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Chris Toshok - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "autocompletion-config.h" - -#include -#include -#include -#include -#include - -#include "widgets/misc/e-preferences-window.h" - -static void -source_selection_changed_cb (ESourceSelector *source_selector) -{ - ESourceList *source_list; - GSList *selection; - GSList *l; - GSList *groups; - - source_list = e_source_selector_get_source_list (source_selector); - - /* first we clear all the completion flags from all sources */ - for (groups = e_source_list_peek_groups (source_list); groups; groups = groups->next) { - ESourceGroup *group = E_SOURCE_GROUP (groups->data); - GSList *sources; - - for (sources = e_source_group_peek_sources (group); sources; sources = sources->next) { - ESource *source = E_SOURCE (sources->data); - - e_source_set_property (source, "completion", NULL); - } - } - - /* then we loop over the selector's selection, setting the - property on those sources */ - selection = e_source_selector_get_selection (source_selector); - for (l = selection; l; l = l->next) { - ESource *source = E_SOURCE (l->data); - - e_source_set_property (source, "completion", "true"); - } - e_source_selector_free_selection (selection); - - /* XXX we should pop up a dialog if this fails */ - e_source_list_sync (source_list, NULL); -} - -static void -initialize_selection (ESourceSelector *source_selector) -{ - ESourceList *source_list; - GSList *groups; - - source_list = e_source_selector_get_source_list (source_selector); - - for (groups = e_source_list_peek_groups (source_list); groups; groups = groups->next) { - ESourceGroup *group = E_SOURCE_GROUP (groups->data); - GSList *sources; - - for (sources = e_source_group_peek_sources (group); sources; sources = sources->next) { - ESource *source = E_SOURCE (sources->data); - const gchar *completion; - - completion = e_source_get_property (source, "completion"); - if (completion && !g_ascii_strcasecmp (completion, "true")) - e_source_selector_select_source (source_selector, source); - } - } -} - -void -autocompletion_config_init (EShell *shell) -{ - ESourceList *source_list; - GtkWidget *scrolled_window; - GtkWidget *source_selector; - GtkWidget *preferences_window; - - g_return_if_fail (E_IS_SHELL (shell)); - - source_list = e_source_list_new_for_gconf_default ( - "/apps/evolution/addressbook/sources"); - - /* XXX should we watch for the source list to change and - update it in the control? what about our local changes? */ - /* g_signal_connect (ac->source_list, "changed", G_CALLBACK (source_list_changed), ac); */ - - scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy ( - GTK_SCROLLED_WINDOW (scrolled_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type ( - GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN); - gtk_widget_show (scrolled_window); - - source_selector = e_source_selector_new (source_list); - g_signal_connect ( - source_selector, "selection_changed", - G_CALLBACK (source_selection_changed_cb), NULL); - gtk_container_add (GTK_CONTAINER (scrolled_window), source_selector); - gtk_widget_show (source_selector); - - initialize_selection (E_SOURCE_SELECTOR (source_selector)); - - preferences_window = e_shell_get_preferences_window (shell); - - e_preferences_window_add_page ( - E_PREFERENCES_WINDOW (preferences_window), - "autocompletion", - "preferences-autocompletion", - _("Autocompletion"), - scrolled_window, - 200); -} diff --git a/addressbook/gui/component/autocompletion-config.h b/addressbook/gui/component/autocompletion-config.h deleted file mode 100644 index 5769bdce9d..0000000000 --- a/addressbook/gui/component/autocompletion-config.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * e-shell-config-autocompletion.h - Configuration page for addressbook autocompletion. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Chris Toshok - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef _AUTOCOMPLETION_CONFIG_H -#define _AUTOCOMPLETION_CONFIG_H - -#include -#include - -G_BEGIN_DECLS - -void autocompletion_config_init (EShell *shell); - -G_END_DECLS - -#endif /* _AUTOCOMPLETION_CONFIG_H */ diff --git a/addressbook/gui/component/e-book-shell-backend.c b/addressbook/gui/component/e-book-shell-backend.c deleted file mode 100644 index 68af7ed03b..0000000000 --- a/addressbook/gui/component/e-book-shell-backend.c +++ /dev/null @@ -1,576 +0,0 @@ -/* - * e-book-shell-backend.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-book-shell-backend.h" - -#include - -#include -#include -#include -#include -#include -#include - -#include "shell/e-shell.h" -#include "shell/e-shell-window.h" - -#include "e-util/e-import.h" -#include "addressbook/gui/widgets/eab-gui-util.h" -#include "addressbook/gui/contact-editor/e-contact-editor.h" -#include "addressbook/gui/contact-list-editor/e-contact-list-editor.h" -#include "addressbook/importers/evolution-addressbook-importers.h" - -#include "eab-config.h" -#include "addressbook-config.h" -#include "autocompletion-config.h" - -#include "e-book-shell-migrate.h" -#include "e-book-shell-view.h" - -#ifdef ENABLE_SMIME -#include "smime/gui/component.h" -#include "smime/gui/certificate-manager.h" -#endif - -#define E_BOOK_SHELL_BACKEND_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_BOOK_SHELL_BACKEND, EBookShellBackendPrivate)) - -#define LDAP_BASE_URI "ldap://" -#define PERSONAL_RELATIVE_URI "system" - -struct _EBookShellBackendPrivate { - ESourceList *source_list; -}; - -enum { - PROP_0, - PROP_SOURCE_LIST -}; - -static gpointer parent_class; -static GType book_shell_backend_type; - -static void -book_shell_backend_ensure_sources (EShellBackend *shell_backend) -{ - /* XXX This is basically the same algorithm across all backends. - * Maybe we could somehow integrate this into EShellBackend? */ - - EBookShellBackendPrivate *priv; - ESourceGroup *on_this_computer; - ESourceGroup *on_ldap_servers; - ESource *personal; - GSList *groups, *iter; - const gchar *data_dir; - const gchar *name; - gchar *base_uri; - gchar *filename; - - on_this_computer = NULL; - on_ldap_servers = NULL; - personal = NULL; - - priv = E_BOOK_SHELL_BACKEND_GET_PRIVATE (shell_backend); - - if (!e_book_get_addressbooks (&priv->source_list, NULL)) { - g_warning ("Could not get addressbook sources from GConf!"); - return; - } - - data_dir = e_shell_backend_get_data_dir (shell_backend); - filename = g_build_filename (data_dir, "local", NULL); - base_uri = g_filename_to_uri (filename, NULL, NULL); - g_free (filename); - - groups = e_source_list_peek_groups (priv->source_list); - for (iter = groups; iter != NULL; iter = iter->next) { - ESourceGroup *source_group = iter->data; - const gchar *group_base_uri; - - group_base_uri = e_source_group_peek_base_uri (source_group); - - /* Compare only "file://" part. If the user's home - * changes, we do not want to create another group. */ - if (on_this_computer == NULL && - strncmp (base_uri, group_base_uri, 7) == 0) - on_this_computer = source_group; - - else if (on_ldap_servers == NULL && - strcmp (LDAP_BASE_URI, group_base_uri) == 0) - on_ldap_servers = source_group; - } - - name = _("On This Computer"); - - if (on_this_computer != NULL) { - GSList *sources; - const gchar *group_base_uri; - - /* Force the group name to the current locale. */ - e_source_group_set_name (on_this_computer, name); - - sources = e_source_group_peek_sources (on_this_computer); - group_base_uri = e_source_group_peek_base_uri (on_this_computer); - - /* Make sure this group includes a "Personal" source. */ - for (iter = sources; iter != NULL; iter = iter->next) { - ESource *source = iter->data; - const gchar *relative_uri; - - relative_uri = e_source_peek_relative_uri (source); - if (relative_uri == NULL) - continue; - - if (strcmp (PERSONAL_RELATIVE_URI, relative_uri) != 0) - continue; - - personal = source; - break; - } - - /* Make sure we have the correct base URI. This can - * change when the user's home directory changes. */ - if (strcmp (base_uri, group_base_uri) != 0) { - e_source_group_set_base_uri ( - on_this_computer, base_uri); - - /* XXX We shouldn't need this sync call here as - * set_base_uri() results in synching to GConf, - * but that happens in an idle loop and too late - * to prevent the user from seeing a "Cannot - * Open ... because of invalid URI" error. */ - e_source_list_sync (priv->source_list, NULL); - } - - } else { - ESourceGroup *source_group; - - source_group = e_source_group_new (name, base_uri); - e_source_list_add_group (priv->source_list, source_group, -1); - g_object_unref (source_group); - } - - name = _("Personal"); - - if (personal == NULL) { - ESource *source; - - /* Create the default Personal address book. */ - source = e_source_new (name, PERSONAL_RELATIVE_URI); - e_source_group_add_source (on_this_computer, source, -1); - e_source_set_property (source, "completion", "true"); - g_object_unref (source); - } else { - /* Force the source name to the current locale. */ - e_source_set_name (personal, name); - } - - name = _("On LDAP Servers"); - - if (on_ldap_servers == NULL) { - ESourceGroup *source_group; - - source_group = e_source_group_new (name, LDAP_BASE_URI); - e_source_list_add_group (priv->source_list, source_group, -1); - g_object_unref (source_group); - } else { - /* Force the group name to the current locale. */ - e_source_group_set_name (on_ldap_servers, name); - } - - g_free (base_uri); -} - -static void -book_shell_backend_init_importers (void) -{ - EImportClass *import_class; - EImportImporter *importer; - - import_class = g_type_class_ref (e_import_get_type ()); - - importer = evolution_ldif_importer_peek (); - e_import_class_add_importer (import_class, importer, NULL, NULL); - - importer = evolution_vcard_importer_peek (); - e_import_class_add_importer (import_class, importer, NULL, NULL); - - importer = evolution_csv_outlook_importer_peek (); - e_import_class_add_importer (import_class, importer, NULL, NULL); - - importer = evolution_csv_mozilla_importer_peek (); - e_import_class_add_importer (import_class, importer, NULL, NULL); - - importer = evolution_csv_evolution_importer_peek (); - e_import_class_add_importer (import_class, importer, NULL, NULL); -} - -static void -book_shell_backend_book_loaded_cb (EBook *book, - EBookStatus status, - gpointer user_data) -{ - EContact *contact; - GtkAction *action; - GtkWidget *editor; - const gchar *action_name; - - /* XXX Handle errors better. */ - if (status != E_BOOK_ERROR_OK) - return; - - contact = e_contact_new (); - action = GTK_ACTION (user_data); - action_name = gtk_action_get_name (action); - - if (strcmp (action_name, "contact-new") == 0) - editor = e_contact_editor_new (book, contact, TRUE, TRUE); - - if (strcmp (action_name, "contact-new-list") == 0) - editor = e_contact_list_editor_new (book, contact, TRUE, TRUE); - - eab_editor_show (EAB_EDITOR (editor)); - - g_object_unref (contact); - g_object_unref (book); -} - -static void -action_contact_new_cb (GtkAction *action, - EShellWindow *shell_window) -{ - EShell *shell; - EBook *book = NULL; - GConfClient *client; - ESourceList *source_list; - const gchar *key; - gchar *uid; - - /* This callback is used for both contacts and contact lists. */ - - if (!e_book_get_addressbooks (&source_list, NULL)) { - g_warning ("Could not get addressbook sources from GConf!"); - return; - } - - shell = e_shell_window_get_shell (shell_window); - client = e_shell_get_gconf_client (shell); - - key = "/apps/evolution/addressbook/display/primary_addressbook"; - uid = gconf_client_get_string (client, key, NULL); - - if (uid != NULL) { - ESource *source; - - source = e_source_list_peek_source_by_uid (source_list, uid); - if (source != NULL) - book = e_book_new (source, NULL); - g_free (uid); - } - - if (book == NULL) - book = e_book_new_default_addressbook (NULL); - - e_book_async_open ( - book, FALSE, book_shell_backend_book_loaded_cb, action); -} - -static void -action_address_book_new_cb (GtkAction *action, - EShellWindow *shell_window) -{ - addressbook_config_create_new_source (NULL); -} - -static GtkActionEntry item_entries[] = { - - { "contact-new", - "contact-new", - NC_("New", "_Contact"), - "c", - N_("Create a new contact"), - G_CALLBACK (action_contact_new_cb) }, - - { "contact-new-list", - "stock_contact-list", - N_("Contact _List"), - "l", - N_("Create a new contact list"), - G_CALLBACK (action_contact_new_cb) } -}; - -static GtkActionEntry source_entries[] = { - - { "address-book-new", - "address-book-new", - NC_("New", "Address _Book"), - NULL, - N_("Create a new address book"), - G_CALLBACK (action_address_book_new_cb) } -}; - -static gboolean -book_shell_backend_handle_uri_cb (EShellBackend *shell_backend, - const gchar *uri) -{ - EUri *euri; - const gchar *cp; - gchar *source_uid = NULL; - gchar *contact_uid = NULL; - - if (!g_str_has_prefix (uri, "contacts:")) - return FALSE; - - euri = e_uri_new (uri); - cp = euri->query; - - if (cp == NULL) { - e_uri_free (euri); - return FALSE; - } - - while (*cp != '\0') { - gchar *header; - gchar *content; - gsize length; - gsize content_length; - - length = strcspn (cp, "=&"); - - /* If it's malformed, give up. */ - if (cp[length] != '=') - break; - - header = (gchar *) cp; - header[length] = '\0'; - cp += length + 1; - - content_length = strcspn (cp, "&"); - content = g_strndup (cp, content_length); - - if (g_ascii_strcasecmp (header, "source-uid") == 0) - source_uid = g_strdup (content); - - if (g_ascii_strcasecmp (header, "contact-uid") == 0) - contact_uid = g_strdup (content); - - g_free (content); - - cp += content_length; - if (*cp == '&') { - cp++; - if (strcmp (cp, "amp;")) - cp += 4; - } - } - - /* FIXME */ - /*addressbook_view_edit_contact (view, source_uid, contact_uid);*/ - - g_free (source_uid); - g_free (contact_uid); - - e_uri_free (euri); - - return TRUE; -} - -static void -book_shell_backend_window_created_cb (EShellBackend *shell_backend, - GtkWindow *window) -{ - const gchar *backend_name; - - if (!E_IS_SHELL_WINDOW (window)) - return; - - backend_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name; - - e_shell_window_register_new_item_actions ( - E_SHELL_WINDOW (window), backend_name, - item_entries, G_N_ELEMENTS (item_entries)); - - e_shell_window_register_new_source_actions ( - E_SHELL_WINDOW (window), backend_name, - source_entries, G_N_ELEMENTS (source_entries)); -} - -static void -book_shell_backend_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_SOURCE_LIST: - g_value_set_object ( - value, - e_book_shell_backend_get_source_list ( - E_BOOK_SHELL_BACKEND (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -book_shell_backend_dispose (GObject *object) -{ - EBookShellBackendPrivate *priv; - - priv = E_BOOK_SHELL_BACKEND_GET_PRIVATE (object); - - if (priv->source_list != NULL) { - g_object_unref (priv->source_list); - priv->source_list = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -book_shell_backend_constructed (GObject *object) -{ - EShell *shell; - EShellBackend *shell_backend; - - shell_backend = E_SHELL_BACKEND (object); - shell = e_shell_backend_get_shell (shell_backend); - - /* XXX Why is this here? Address books aren't the only - * things that use S/MIME. Maybe put it in EShell? */ -#ifdef ENABLE_SMIME - smime_component_init (); - certificate_manager_config_init (shell); -#endif - - book_shell_backend_init_importers (); - book_shell_backend_ensure_sources (shell_backend); - - e_plugin_hook_register_type (eab_config_get_type ()); - - g_signal_connect_swapped ( - shell, "handle-uri", - G_CALLBACK (book_shell_backend_handle_uri_cb), - shell_backend); - - g_signal_connect_swapped ( - shell, "window-created", - G_CALLBACK (book_shell_backend_window_created_cb), - shell_backend); - - autocompletion_config_init (shell); -} - -static gboolean -book_shell_backend_is_busy (EShellBackend *shell_backend) -{ - return !eab_editor_request_close_all (); -} - -static gboolean -book_shell_backend_shutdown (EShellBackend *shell_backend) -{ - /* FIXME */ - return TRUE; -} - -static void -book_shell_backend_class_init (EBookShellBackendClass *class) -{ - GObjectClass *object_class; - EShellBackendClass *shell_backend_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (EBookShellBackendPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->get_property = book_shell_backend_get_property; - object_class->dispose = book_shell_backend_dispose; - object_class->constructed = book_shell_backend_constructed; - - shell_backend_class = E_SHELL_BACKEND_CLASS (class); - shell_backend_class->shell_view_type = E_TYPE_BOOK_SHELL_VIEW; - shell_backend_class->name = "addressbook"; - shell_backend_class->aliases = "contacts"; - shell_backend_class->schemes = ""; - shell_backend_class->sort_order = 300; - shell_backend_class->start = NULL; - shell_backend_class->is_busy = book_shell_backend_is_busy; - shell_backend_class->shutdown = book_shell_backend_shutdown; - shell_backend_class->migrate = e_book_shell_backend_migrate; - - g_object_class_install_property ( - object_class, - PROP_SOURCE_LIST, - g_param_spec_object ( - "source-list", - _("Source List"), - _("The registry of address books"), - E_TYPE_SOURCE_LIST, - G_PARAM_READABLE)); -} - -static void -book_shell_backend_init (EBookShellBackend *book_shell_backend) -{ - book_shell_backend->priv = - E_BOOK_SHELL_BACKEND_GET_PRIVATE (book_shell_backend); -} - -GType -e_book_shell_backend_get_type (void) -{ - return book_shell_backend_type; -} - -void -e_book_shell_backend_register_type (GTypeModule *type_module) -{ - const GTypeInfo type_info = { - sizeof (EBookShellBackendClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) book_shell_backend_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (EBookShellBackend), - 0, /* n_preallocs */ - (GInstanceInitFunc) book_shell_backend_init, - NULL /* value_table */ - }; - - book_shell_backend_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_BACKEND, - "EBookShellBackend", &type_info, 0); -} - -ESourceList * -e_book_shell_backend_get_source_list (EBookShellBackend *book_shell_backend) -{ - g_return_val_if_fail ( - E_IS_BOOK_SHELL_BACKEND (book_shell_backend), NULL); - - return book_shell_backend->priv->source_list; -} diff --git a/addressbook/gui/component/e-book-shell-backend.h b/addressbook/gui/component/e-book-shell-backend.h deleted file mode 100644 index c61e43b814..0000000000 --- a/addressbook/gui/component/e-book-shell-backend.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * e-book-shell-backend.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_BOOK_SHELL_BACKEND_H -#define E_BOOK_SHELL_BACKEND_H - -#include -#include - -/* Standard GObject macros */ -#define E_TYPE_BOOK_SHELL_BACKEND \ - (e_book_shell_backend_get_type ()) -#define E_BOOK_SHELL_BACKEND(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_BOOK_SHELL_BACKEND, EBookShellBackend)) -#define E_BOOK_SHELL_BACKEND_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_BOOK_SHELL_BACKEND, EBookShellBackendClass)) -#define E_IS_BOOK_SHELL_BACKEND(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_BOOK_SHELL_BACKEND)) -#define E_IS_BOOK_SHELL_BACKEND_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_BOOK_SHELL_BACKEND)) -#define E_BOOK_SHELL_BACKEND_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_BOOK_SHELL_BACKEND, EBookShellBackendClass)) - -G_BEGIN_DECLS - -typedef struct _EBookShellBackend EBookShellBackend; -typedef struct _EBookShellBackendClass EBookShellBackendClass; -typedef struct _EBookShellBackendPrivate EBookShellBackendPrivate; - -struct _EBookShellBackend { - EShellBackend parent; - EBookShellBackendPrivate *priv; -}; - -struct _EBookShellBackendClass { - EShellBackendClass parent_class; -}; - -GType e_book_shell_backend_get_type (void); -void e_book_shell_backend_register_type - (GTypeModule *type_module); -ESourceList * e_book_shell_backend_get_source_list - (EBookShellBackend *book_shell_backend); - -G_END_DECLS - -#endif /* E_BOOK_SHELL_BACKEND_H */ diff --git a/addressbook/gui/component/e-book-shell-content.c b/addressbook/gui/component/e-book-shell-content.c deleted file mode 100644 index cce03b1575..0000000000 --- a/addressbook/gui/component/e-book-shell-content.c +++ /dev/null @@ -1,492 +0,0 @@ -/* - * e-book-shell-content.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-book-shell-content.h" - -#include - -#include "e-util/gconf-bridge.h" - -#define E_BOOK_SHELL_CONTENT_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_BOOK_SHELL_CONTENT, EBookShellContentPrivate)) - -struct _EBookShellContentPrivate { - GtkWidget *paned; - GtkWidget *notebook; - GtkWidget *preview; -}; - -enum { - PROP_0, - PROP_CURRENT_VIEW, - PROP_PREVIEW_CONTACT, - PROP_PREVIEW_VISIBLE -}; - -static gpointer parent_class; -static GType book_shell_view_type; - -static void -book_shell_content_send_message_cb (EBookShellContent *book_shell_content, - EDestination *destination, - EABContactDisplay *display) -{ - GList node = { destination, NULL, NULL }; - - eab_send_as_to (&node); -} - -static void -book_shell_content_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_CURRENT_VIEW: - e_book_shell_content_set_current_view ( - E_BOOK_SHELL_CONTENT (object), - g_value_get_object (value)); - return; - - case PROP_PREVIEW_CONTACT: - e_book_shell_content_set_preview_contact ( - E_BOOK_SHELL_CONTENT (object), - g_value_get_object (value)); - return; - - case PROP_PREVIEW_VISIBLE: - e_book_shell_content_set_preview_visible ( - E_BOOK_SHELL_CONTENT (object), - g_value_get_boolean (value)); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -book_shell_content_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_CURRENT_VIEW: - g_value_set_object ( - value, e_book_shell_content_get_current_view ( - E_BOOK_SHELL_CONTENT (object))); - return; - - case PROP_PREVIEW_CONTACT: - g_value_set_object ( - value, e_book_shell_content_get_preview_contact ( - E_BOOK_SHELL_CONTENT (object))); - return; - - case PROP_PREVIEW_VISIBLE: - g_value_set_boolean ( - value, e_book_shell_content_get_preview_visible ( - E_BOOK_SHELL_CONTENT (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -book_shell_content_dispose (GObject *object) -{ - EBookShellContentPrivate *priv; - - priv = E_BOOK_SHELL_CONTENT_GET_PRIVATE (object); - - if (priv->paned != NULL) { - g_object_unref (priv->paned); - priv->paned = NULL; - } - - if (priv->notebook != NULL) { - g_object_unref (priv->notebook); - priv->notebook = NULL; - } - - if (priv->preview != NULL) { - g_object_unref (priv->preview); - priv->preview = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -book_shell_content_constructed (GObject *object) -{ - EBookShellContentPrivate *priv; - GConfBridge *bridge; - GtkWidget *container; - GtkWidget *widget; - const gchar *key; - - priv = E_BOOK_SHELL_CONTENT_GET_PRIVATE (object); - - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (parent_class)->constructed (object); - - container = GTK_WIDGET (object); - - widget = gtk_vpaned_new (); - gtk_container_add (GTK_CONTAINER (container), widget); - priv->paned = g_object_ref (widget); - gtk_widget_show (widget); - - container = widget; - - widget = gtk_notebook_new (); - gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE); - gtk_notebook_set_show_border (GTK_NOTEBOOK (widget), FALSE); - gtk_paned_add1 (GTK_PANED (container), widget); - priv->notebook = g_object_ref (widget); - gtk_widget_show (widget); - - widget = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy ( - GTK_SCROLLED_WINDOW (widget), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type ( - GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); - gtk_paned_add2 (GTK_PANED (container), widget); - gtk_widget_show (widget); - - container = widget; - - widget = eab_contact_display_new (); - eab_contact_display_set_mode ( - EAB_CONTACT_DISPLAY (widget), - EAB_CONTACT_DISPLAY_RENDER_NORMAL); - gtk_container_add (GTK_CONTAINER (container), widget); - priv->preview = g_object_ref (widget); - gtk_widget_show (widget); - - g_signal_connect_swapped ( - priv->preview, "send-message", - G_CALLBACK (book_shell_content_send_message_cb), object); - - /* Bind GObject properties to GConf keys. */ - - bridge = gconf_bridge_get (); - - object = G_OBJECT (priv->paned); - key = "/apps/evolution/addressbook/display/vpane_position"; - gconf_bridge_bind_property_delayed (bridge, key, object, "position"); -} - -static guint32 -book_shell_content_check_state (EShellContent *shell_content) -{ - EBookShellContent *book_shell_content; - ESelectionModel *selection_model; - EAddressbookModel *model; - EAddressbookView *view; - guint32 state = 0; - gint n_contacts; - gint n_selected; - - book_shell_content = E_BOOK_SHELL_CONTENT (shell_content); - view = e_book_shell_content_get_current_view (book_shell_content); - model = e_addressbook_view_get_model (view); - - selection_model = e_addressbook_view_get_selection_model (view); - n_contacts = (selection_model != NULL) ? - e_selection_model_row_count (selection_model) : 0; - n_selected = (selection_model != NULL) ? - e_selection_model_selected_count (selection_model) : 0; - - /* FIXME Finish the rest of the flags. */ - if (n_selected == 1) - state |= E_BOOK_SHELL_CONTENT_SELECTION_SINGLE; - if (n_selected > 1) - state |= E_BOOK_SHELL_CONTENT_SELECTION_MULTIPLE; - if (e_addressbook_model_can_stop (model)) - state |= E_BOOK_SHELL_CONTENT_SOURCE_IS_BUSY; - if (e_addressbook_model_get_editable (model)) - state |= E_BOOK_SHELL_CONTENT_SOURCE_IS_EDITABLE; - if (n_contacts == 0) - state |= E_BOOK_SHELL_CONTENT_SOURCE_IS_EMPTY; - - return state; -} - -static void -book_shell_content_class_init (EBookShellContentClass *class) -{ - GObjectClass *object_class; - EShellContentClass *shell_content_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (EBookShellContentPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->set_property = book_shell_content_set_property; - object_class->get_property = book_shell_content_get_property; - object_class->dispose = book_shell_content_dispose; - object_class->constructed = book_shell_content_constructed; - - shell_content_class = E_SHELL_CONTENT_CLASS (class); - shell_content_class->check_state = book_shell_content_check_state; - - g_object_class_install_property ( - object_class, - PROP_CURRENT_VIEW, - g_param_spec_object ( - "current-view", - _("Current View"), - _("The currently selected address book view"), - E_TYPE_ADDRESSBOOK_VIEW, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_PREVIEW_CONTACT, - g_param_spec_object ( - "preview-contact", - _("Previewed Contact"), - _("The contact being shown in the preview pane"), - E_TYPE_CONTACT, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_PREVIEW_VISIBLE, - g_param_spec_boolean ( - "preview-visible", - _("Preview is Visible"), - _("Whether the preview pane is visible"), - TRUE, - G_PARAM_READWRITE)); -} - -static void -book_shell_content_init (EBookShellContent *book_shell_content) -{ - book_shell_content->priv = - E_BOOK_SHELL_CONTENT_GET_PRIVATE (book_shell_content); - - /* Postpone widget construction until we have a shell view. */ -} - -GType -e_book_shell_content_get_type (void) -{ - return book_shell_view_type; -} - -void -e_book_shell_content_register_type (GTypeModule *type_module) -{ - static const GTypeInfo type_info = { - sizeof (EBookShellContentClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) book_shell_content_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (EBookShellContent), - 0, /* n_preallocs */ - (GInstanceInitFunc) book_shell_content_init, - NULL /* value_table */ - }; - - book_shell_view_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_CONTENT, - "EBookShellContent", &type_info, 0); -} - -GtkWidget * -e_book_shell_content_new (EShellView *shell_view) -{ - g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - - return g_object_new ( - E_TYPE_BOOK_SHELL_CONTENT, - "shell-view", shell_view, NULL); -} - -void -e_book_shell_content_insert_view (EBookShellContent *book_shell_content, - EAddressbookView *addressbook_view) -{ - GtkNotebook *notebook; - GtkWidget *child; - - g_return_if_fail (E_IS_BOOK_SHELL_CONTENT (book_shell_content)); - g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (addressbook_view)); - - notebook = GTK_NOTEBOOK (book_shell_content->priv->notebook); - child = GTK_WIDGET (addressbook_view); - gtk_notebook_append_page (notebook, child, NULL); -} - -void -e_book_shell_content_remove_view (EBookShellContent *book_shell_content, - EAddressbookView *addressbook_view) -{ - GtkNotebook *notebook; - GtkWidget *child; - gint page_num; - - g_return_if_fail (E_IS_BOOK_SHELL_CONTENT (book_shell_content)); - g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (addressbook_view)); - - notebook = GTK_NOTEBOOK (book_shell_content->priv->notebook); - child = GTK_WIDGET (addressbook_view); - page_num = gtk_notebook_page_num (notebook, child); - g_return_if_fail (page_num >= 0); - - gtk_notebook_remove_page (notebook, page_num); -} - -EAddressbookView * -e_book_shell_content_get_current_view (EBookShellContent *book_shell_content) -{ - GtkNotebook *notebook; - GtkWidget *widget; - gint page_num; - - g_return_val_if_fail ( - E_IS_BOOK_SHELL_CONTENT (book_shell_content), NULL); - - notebook = GTK_NOTEBOOK (book_shell_content->priv->notebook); - page_num = gtk_notebook_get_current_page (notebook); - widget = gtk_notebook_get_nth_page (notebook, page_num); - g_return_val_if_fail (widget != NULL, NULL); - - return E_ADDRESSBOOK_VIEW (widget); -} - -void -e_book_shell_content_set_current_view (EBookShellContent *book_shell_content, - EAddressbookView *addressbook_view) -{ - GtkNotebook *notebook; - GtkWidget *child; - gint page_num; - - g_return_if_fail (E_IS_BOOK_SHELL_CONTENT (book_shell_content)); - g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (addressbook_view)); - - notebook = GTK_NOTEBOOK (book_shell_content->priv->notebook); - child = GTK_WIDGET (addressbook_view); - page_num = gtk_notebook_page_num (notebook, child); - g_return_if_fail (page_num >= 0); - - gtk_notebook_set_current_page (notebook, page_num); - g_object_notify (G_OBJECT (book_shell_content), "current-view"); -} - -EContact * -e_book_shell_content_get_preview_contact (EBookShellContent *book_shell_content) -{ - EABContactDisplay *display; - - g_return_val_if_fail ( - E_IS_BOOK_SHELL_CONTENT (book_shell_content), NULL); - - display = EAB_CONTACT_DISPLAY (book_shell_content->priv->preview); - - return eab_contact_display_get_contact (display); -} - -void -e_book_shell_content_set_preview_contact (EBookShellContent *book_shell_content, - EContact *preview_contact) -{ - EABContactDisplay *display; - - g_return_if_fail (E_IS_BOOK_SHELL_CONTENT (book_shell_content)); - - display = EAB_CONTACT_DISPLAY (book_shell_content->priv->preview); - - eab_contact_display_set_contact (display, preview_contact); - g_object_notify (G_OBJECT (book_shell_content), "preview-contact"); -} - -gboolean -e_book_shell_content_get_preview_visible (EBookShellContent *book_shell_content) -{ - GtkPaned *paned; - GtkWidget *child; - - g_return_val_if_fail ( - E_IS_BOOK_SHELL_CONTENT (book_shell_content), FALSE); - - paned = GTK_PANED (book_shell_content->priv->paned); - child = gtk_paned_get_child2 (paned); - - return GTK_WIDGET_VISIBLE (child); -} - -void -e_book_shell_content_set_preview_visible (EBookShellContent *book_shell_content, - gboolean preview_visible) -{ - GtkPaned *paned; - GtkWidget *child; - - g_return_if_fail (E_IS_BOOK_SHELL_CONTENT (book_shell_content)); - - paned = GTK_PANED (book_shell_content->priv->paned); - child = gtk_paned_get_child2 (paned); - - if (preview_visible) - gtk_widget_show (child); - else - gtk_widget_hide (child); - - g_object_notify (G_OBJECT (book_shell_content), "preview-visible"); -} - -void -e_book_shell_content_clipboard_copy (EBookShellContent *book_shell_content) -{ - EAddressbookView *addressbook_view; - GtkHTML *html; - gchar *selection; - - g_return_if_fail (E_IS_BOOK_SHELL_CONTENT (book_shell_content)); - - html = GTK_HTML (book_shell_content->priv->preview); - addressbook_view = - e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (addressbook_view != NULL); - - if (!GTK_WIDGET_HAS_FOCUS (html)) { - e_addressbook_view_copy (addressbook_view); - return; - } - - selection = gtk_html_get_selection_html (html, NULL); - if (selection != NULL) - gtk_html_copy (html); - g_free (selection); -} diff --git a/addressbook/gui/component/e-book-shell-content.h b/addressbook/gui/component/e-book-shell-content.h deleted file mode 100644 index ac5ab10e8b..0000000000 --- a/addressbook/gui/component/e-book-shell-content.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * e-book-shell-content.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_BOOK_SHELL_CONTENT_H -#define E_BOOK_SHELL_CONTENT_H - -#include - -#include "shell/e-shell-content.h" -#include "shell/e-shell-view.h" - -#include "addressbook/gui/component/eab-composer-util.h" -#include "addressbook/gui/widgets/e-addressbook-view.h" - -/* Standard GObject macros */ -#define E_TYPE_BOOK_SHELL_CONTENT \ - (e_book_shell_content_get_type ()) -#define E_BOOK_SHELL_CONTENT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_BOOK_SHELL_CONTENT, EBookShellContent)) -#define E_BOOK_SHELL_CONTENT_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_BOOK_SHELL_CONTENT, EBookShellContentClass)) -#define E_IS_BOOK_SHELL_CONTENT(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_BOOK_SHELL_CONTENT)) -#define E_IS_BOOK_SHELL_CONTENT_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_BOOK_SHELL_CONTENT)) -#define E_BOOK_SHELL_CONTENT_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_BOOK_SHELL_CONTENT, EBookShellContentClass)) - -G_BEGIN_DECLS - -typedef struct _EBookShellContent EBookShellContent; -typedef struct _EBookShellContentClass EBookShellContentClass; -typedef struct _EBookShellContentPrivate EBookShellContentPrivate; - -enum { - E_BOOK_SHELL_CONTENT_SELECTION_SINGLE = 1 << 0, - E_BOOK_SHELL_CONTENT_SELECTION_MULTIPLE = 1 << 1, - E_BOOK_SHELL_CONTENT_SELECTION_HAS_EMAIL = 1 << 2, - E_BOOK_SHELL_CONTENT_SELECTION_IS_CONTACT_LIST = 1 << 3, - E_BOOK_SHELL_CONTENT_SELECTION_HAS_HTTP_URI = 1 << 4, - E_BOOK_SHELL_CONTENT_SELECTION_HAS_MAILTO_URI = 1 << 5, - E_BOOK_SHELL_CONTENT_SOURCE_IS_BUSY = 1 << 6, - E_BOOK_SHELL_CONTENT_SOURCE_IS_EDITABLE = 1 << 7, - E_BOOK_SHELL_CONTENT_SOURCE_IS_EMPTY = 1 << 8 -}; - -struct _EBookShellContent { - EShellContent parent; - EBookShellContentPrivate *priv; -}; - -struct _EBookShellContentClass { - EShellContentClass parent_class; -}; - -GType e_book_shell_content_get_type (void); -void e_book_shell_content_register_type - (GTypeModule *type_module); -GtkWidget * e_book_shell_content_new(EShellView *shell_view); -void e_book_shell_content_insert_view - (EBookShellContent *book_shell_content, - EAddressbookView *addressbook_view); -void e_book_shell_content_remove_view - (EBookShellContent *book_shell_content, - EAddressbookView *addressbook_view); -EAddressbookView * - e_book_shell_content_get_current_view - (EBookShellContent *book_shell_content); -void e_book_shell_content_set_current_view - (EBookShellContent *book_shell_content, - EAddressbookView *addressbook_view); -EContact * e_book_shell_content_get_preview_contact - (EBookShellContent *book_shell_content); -void e_book_shell_content_set_preview_contact - (EBookShellContent *book_shell_content, - EContact *preview_contact); -gboolean e_book_shell_content_get_preview_visible - (EBookShellContent *book_shell_content); -void e_book_shell_content_set_preview_visible - (EBookShellContent *book_shell_content, - gboolean preview_visible); -void e_book_shell_content_clipboard_copy - (EBookShellContent *book_shell_content); - -G_END_DECLS - -#endif /* E_BOOK_SHELL_CONTENT_H */ diff --git a/addressbook/gui/component/e-book-shell-migrate.c b/addressbook/gui/component/e-book-shell-migrate.c deleted file mode 100644 index fce6e0a634..0000000000 --- a/addressbook/gui/component/e-book-shell-migrate.c +++ /dev/null @@ -1,1230 +0,0 @@ -/* - * e-book-shell-backend-migrate.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Chris Toshok - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include - -#include - -#include "e-util/e-util.h" -#include "e-util/e-util-private.h" -#include "e-util/e-xml-utils.h" -#include "e-util/e-folder-map.h" - -#include "e-book-shell-migrate.h" - -/*#define SLOW_MIGRATION*/ - -typedef struct { - /* this hash table maps old folder uris to new uids. It's - build in migrate_contact_folder and it's used in - migrate_completion_folders. */ - GHashTable *folder_uid_map; - - ESourceList *source_list; - - const gchar *data_dir; - - GtkWidget *window; - GtkWidget *label; - GtkWidget *folder_label; - GtkWidget *progress; -} MigrationContext; - -static void -setup_progress_dialog (MigrationContext *context) -{ - GtkWidget *vbox, *hbox; - - context->window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (context->window), _("Migrating...")); - gtk_window_set_modal (GTK_WINDOW (context->window), TRUE); - gtk_container_set_border_width (GTK_CONTAINER (context->window), 6); - - vbox = gtk_vbox_new (FALSE, 6); - gtk_widget_show (vbox); - gtk_container_add (GTK_CONTAINER (context->window), vbox); - - context->label = gtk_label_new (""); - gtk_label_set_line_wrap (GTK_LABEL (context->label), TRUE); - gtk_widget_show (context->label); - gtk_box_pack_start (GTK_BOX (vbox), context->label, TRUE, TRUE, 0); - - hbox = gtk_hbox_new (FALSE, 6); - gtk_widget_show (hbox); - gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0); - - context->folder_label = gtk_label_new (""); - gtk_widget_show (context->folder_label); - gtk_box_pack_start (GTK_BOX (hbox), context->folder_label, TRUE, TRUE, 0); - - context->progress = gtk_progress_bar_new (); - gtk_widget_show (context->progress); - gtk_box_pack_start (GTK_BOX (hbox), context->progress, TRUE, TRUE, 0); - - gtk_widget_show (context->window); -} - -static void -dialog_close (MigrationContext *context) -{ - gtk_widget_destroy (context->window); -} - -static void -dialog_set_label (MigrationContext *context, const gchar *str) -{ - gtk_label_set_text (GTK_LABEL (context->label), str); - - while (gtk_events_pending ()) - gtk_main_iteration (); - -#ifdef SLOW_MIGRATION - sleep (1); -#endif -} - -static void -dialog_set_folder_name (MigrationContext *context, const gchar *folder_name) -{ - gchar *text; - - text = g_strdup_printf (_("Migrating '%s':"), folder_name); - gtk_label_set_text (GTK_LABEL (context->folder_label), text); - g_free (text); - - gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (context->progress), 0.0); - - while (gtk_events_pending ()) - gtk_main_iteration (); - -#ifdef SLOW_MIGRATION - sleep (1); -#endif -} - -static void -dialog_set_progress (MigrationContext *context, double percent) -{ - gchar text[5]; - - snprintf (text, sizeof (text), "%d%%", (gint) (percent * 100.0f)); - - gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (context->progress), percent); - gtk_progress_bar_set_text (GTK_PROGRESS_BAR (context->progress), text); - - while (gtk_events_pending ()) - gtk_main_iteration (); - -#ifdef SLOW_MIGRATION - sleep (1); -#endif -} - -static gboolean -check_for_conflict (ESourceGroup *group, gchar *name) -{ - GSList *sources; - GSList *s; - - sources = e_source_group_peek_sources (group); - - for (s = sources; s; s = s->next) { - ESource *source = E_SOURCE (s->data); - - if (!strcmp (e_source_peek_name (source), name)) - return TRUE; - } - - return FALSE; -} - -static gchar * -get_source_name (ESourceGroup *group, const gchar *path) -{ -#ifndef G_OS_WIN32 - gchar **p = g_strsplit (path, "/", 0); -#else - gchar **p = g_strsplit_set (path, "\\/", 0); -#endif - gint i, j, starting_index; - gint num_elements; - gboolean conflict; - GString *s = g_string_new (""); - - for (i = 0; p[i]; i ++); - - num_elements = i; - i--; - - /* p[i] is now the last path element */ - - /* check if it conflicts */ - starting_index = i; - do { - g_string_assign (s, ""); - for (j = starting_index; j < num_elements; j += 2) { - if (j != starting_index) - g_string_append_c (s, '_'); - g_string_append (s, p[j]); - } - - conflict = check_for_conflict (group, s->str); - - - /* if there was a conflict back up 2 levels (skipping the /subfolder/ element) */ - if (conflict) - starting_index -= 2; - - /* we always break out if we can't go any further, - regardless of whether or not we conflict. */ - if (starting_index < 0) - break; - - } while (conflict); - - g_strfreev (p); - - return g_string_free (s, FALSE); -} - -static void -migrate_contacts (MigrationContext *context, EBook *old_book, EBook *new_book) -{ - EBookQuery *query = e_book_query_any_field_contains (""); - GList *l, *contacts; - gint num_added = 0; - gint num_contacts; - - /* both books are loaded, start the actual migration */ - e_book_get_contacts (old_book, query, &contacts, NULL); - e_book_query_unref (query); - - num_contacts = g_list_length (contacts); - for (l = contacts; l; l = l->next) { - EContact *contact = l->data; - GError *e = NULL; - GList *attrs, *attr; - - /* do some last minute massaging of the contact's attributes */ - - attrs = e_vcard_get_attributes (E_VCARD (contact)); - for (attr = attrs; attr;) { - EVCardAttribute *a = attr->data; - - /* evo 1.4 used the non-standard X-EVOLUTION-OFFICE attribute, - evo 1.5 uses the third element in the ORG list attribute. */ - if (!strcmp ("X-EVOLUTION-OFFICE", e_vcard_attribute_get_name (a))) { - GList *v = e_vcard_attribute_get_values (a); - GList *next_attr; - - if (v && v->data) - e_contact_set (contact, E_CONTACT_OFFICE, v->data); - - next_attr = attr->next; - e_vcard_remove_attribute (E_VCARD (contact), a); - attr = next_attr; - } - /* evo 1.4 didn't put TYPE=VOICE in for phone numbers. - evo 1.5 does. - - so we search through the attribute params for - either TYPE=VOICE or TYPE=FAX. If we find - either we do nothing. If we find neither, we - add TYPE=VOICE. - */ - else if (!strcmp ("TEL", e_vcard_attribute_get_name (a))) { - GList *params, *param; - gboolean found = FALSE; - - params = e_vcard_attribute_get_params (a); - for (param = params; param; param = param->next) { - EVCardAttributeParam *p = param->data; - if (!strcmp (EVC_TYPE, e_vcard_attribute_param_get_name (p))) { - GList *v = e_vcard_attribute_param_get_values (p); - while (v && v->data) { - if (!strcmp ("VOICE", v->data) - || !strcmp ("FAX", v->data)) { - found = TRUE; - break; - } - v = v->next; - } - } - } - - if (!found) - e_vcard_attribute_add_param_with_value (a, - e_vcard_attribute_param_new (EVC_TYPE), - "VOICE"); - attr = attr->next; - } - /* Replace "POSTAL" (1.4) addresses with "OTHER" (1.5) */ - else if (!strcmp ("ADR", e_vcard_attribute_get_name (a))) { - GList *params, *param; - gboolean found = FALSE; - EVCardAttributeParam *p; - - params = e_vcard_attribute_get_params (a); - for (param = params; param; param = param->next) { - p = param->data; - if (!strcmp (EVC_TYPE, e_vcard_attribute_param_get_name (p))) { - GList *v = e_vcard_attribute_param_get_values (p); - while (v && v->data ) { - if (!strcmp ("POSTAL", v->data)) { - found = TRUE; - break; - } - v = v->next; - } - if (found) - break; - } - } - - if (found) { - e_vcard_attribute_param_remove_values (p); - e_vcard_attribute_param_add_value (p, "OTHER"); - } - - attr = attr->next; - } - /* this is kinda gross. The new vcard parser - needs ';'s to be escaped by \'s. but the - 1.4 vcard generator would put unescaped xml - (including entities like >) in the value - of attributes, so we need to go through and - escape those ';'s. */ - else if (!strcmp ("EMAIL", e_vcard_attribute_get_name (a))) { - GList *params; - GList *v = e_vcard_attribute_get_values (a); - - /* Add TYPE=OTHER if there is no type set */ - params = e_vcard_attribute_get_params (a); - if (!params) - e_vcard_attribute_add_param_with_value (a, - e_vcard_attribute_param_new (EVC_TYPE), - "OTHER"); - - if (v && v->data) { - if (!strncmp ((gchar *)v->data, "data); - if (v->next) - g_string_append_c (str, ';'); - v = v->next; - } - - e_vcard_attribute_remove_values (a); - e_vcard_attribute_add_value (a, str->str); - g_string_free (str, TRUE); - } - } - - attr = attr->next; - } - else { - attr = attr->next; - } - } - - if (!e_book_add_contact (new_book, - contact, - &e)) - g_warning ("contact add failed: `%s'", e->message); - - num_added ++; - - dialog_set_progress (context, (double)num_added / num_contacts); - } - - g_list_foreach (contacts, (GFunc)g_object_unref, NULL); - g_list_free (contacts); -} - -static void -migrate_contact_folder_to_source (MigrationContext *context, gchar *old_path, ESource *new_source) -{ - gchar *old_uri = g_filename_to_uri (old_path, NULL, NULL); - GError *e = NULL; - - EBook *old_book = NULL, *new_book = NULL; - ESource *old_source; - ESourceGroup *group; - - group = e_source_group_new ("", old_uri); - old_source = e_source_new ("", ""); - e_source_group_add_source (group, old_source, -1); - - dialog_set_folder_name (context, e_source_peek_name (new_source)); - - old_book = e_book_new (old_source, &e); - if (!old_book - || !e_book_open (old_book, TRUE, &e)) { - g_warning ("failed to load source book for migration: `%s'", e->message); - goto finish; - } - - new_book = e_book_new (new_source, &e); - if (!new_book - || !e_book_open (new_book, FALSE, &e)) { - g_warning ("failed to load destination book for migration: `%s'", e->message); - goto finish; - } - - migrate_contacts (context, old_book, new_book); - - finish: - g_object_unref (old_source); - g_object_unref (group); - if (old_book) - g_object_unref (old_book); - if (new_book) - g_object_unref (new_book); - g_free (old_uri); -} - -static void -migrate_contact_folder (MigrationContext *context, gchar *old_path, ESourceGroup *dest_group, gchar *source_name) -{ - ESource *new_source; - - new_source = e_source_new (source_name, source_name); - e_source_set_relative_uri (new_source, e_source_peek_uid (new_source)); - e_source_group_add_source (dest_group, new_source, -1); - - g_hash_table_insert (context->folder_uid_map, g_strdup (old_path), g_strdup (e_source_peek_uid (new_source))); - - migrate_contact_folder_to_source (context, old_path, new_source); - - g_object_unref (new_source); -} - -#define LDAP_BASE_URI "ldap://" -#define PERSONAL_RELATIVE_URI "system" - -static void -create_groups (MigrationContext *context, - ESourceGroup **on_this_computer, - ESourceGroup **on_ldap_servers, - ESource **personal_source) -{ - GSList *groups; - ESourceGroup *group; - gchar *base_uri, *base_uri_proto; - - *on_this_computer = NULL; - *on_ldap_servers = NULL; - *personal_source = NULL; - - base_uri = g_build_filename (context->data_dir, "local", NULL); - - base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL); - - groups = e_source_list_peek_groups (context->source_list); - if (groups) { - /* groups are already there, we need to search for things... */ - GSList *g; - - for (g = groups; g; g = g->next) { - - group = E_SOURCE_GROUP (g->data); - - if (!*on_this_computer && !strcmp (base_uri_proto, e_source_group_peek_base_uri (group))) - *on_this_computer = g_object_ref (group); - else if (!*on_ldap_servers && !strcmp (LDAP_BASE_URI, e_source_group_peek_base_uri (group))) - *on_ldap_servers = g_object_ref (group); - } - } - - if (*on_this_computer) { - /* make sure "Personal" shows up as a source under - this group */ - GSList *sources = e_source_group_peek_sources (*on_this_computer); - GSList *s; - for (s = sources; s; s = s->next) { - ESource *source = E_SOURCE (s->data); - const gchar *relative_uri; - - relative_uri = e_source_peek_relative_uri (source); - if (relative_uri == NULL) - continue; - if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) { - *personal_source = g_object_ref (source); - break; - } - } - } - else { - /* create the local source group */ - group = e_source_group_new (_("On This Computer"), base_uri_proto); - e_source_list_add_group (context->source_list, group, -1); - - *on_this_computer = group; - } - - if (!*personal_source) { - /* Create the default Person addressbook */ - ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); - e_source_group_add_source (*on_this_computer, source, -1); - - e_source_set_property (source, "completion", "true"); - - *personal_source = source; - } - - if (!*on_ldap_servers) { - /* Create the LDAP source group */ - group = e_source_group_new (_("On LDAP Servers"), LDAP_BASE_URI); - e_source_list_add_group (context->source_list, group, -1); - - *on_ldap_servers = group; - } - - g_free (base_uri_proto); - g_free (base_uri); -} - -static gboolean -migrate_local_folders (MigrationContext *context, ESourceGroup *on_this_computer, ESource *personal_source) -{ - gchar *old_path = NULL; - GSList *dirs, *l; - gchar *local_contact_folder = NULL; - - old_path = g_strdup_printf ("%s/evolution/local", g_get_home_dir ()); - - dirs = e_folder_map_local_folders (old_path, "contacts"); - - /* migrate the local addressbook first, to local/system */ - local_contact_folder = g_build_filename (g_get_home_dir (), - "evolution", "local", "Contacts", - NULL); - - for (l = dirs; l; l = l->next) { - gchar *source_name; - /* we handle the system folder differently */ - if (personal_source && !strcmp ((gchar *)l->data, local_contact_folder)) { - g_hash_table_insert (context->folder_uid_map, g_strdup (l->data), g_strdup (e_source_peek_uid (personal_source))); - migrate_contact_folder_to_source (context, local_contact_folder, personal_source); - continue; - } - - source_name = get_source_name (on_this_computer, (gchar *)l->data); - migrate_contact_folder (context, l->data, on_this_computer, source_name); - g_free (source_name); - } - - g_slist_foreach (dirs, (GFunc)g_free, NULL); - g_slist_free (dirs); - g_free (local_contact_folder); - g_free (old_path); - - return TRUE; -} - -static gchar * -get_string_child (xmlNode *node, - const gchar *name) -{ - xmlNode *p; - xmlChar *xml_string; - gchar *retval; - - p = e_xml_get_child_by_name (node, (xmlChar *) name); - if (p == NULL) - return NULL; - - p = e_xml_get_child_by_name (p, (xmlChar *) "text"); - if (p == NULL) /* there's no text between the tags, return the empty string */ - return g_strdup(""); - - xml_string = xmlNodeListGetString (node->doc, p, 1); - retval = g_strdup ((gchar *) xml_string); - xmlFree (xml_string); - - return retval; -} - -static gint -get_integer_child (xmlNode *node, - const gchar *name, - gint defval) -{ - xmlNode *p; - xmlChar *xml_string; - gint retval; - - p = e_xml_get_child_by_name (node, (xmlChar *) name); - if (p == NULL) - return defval; - - p = e_xml_get_child_by_name (p, (xmlChar *) "text"); - if (p == NULL) /* there's no text between the tags, return the default */ - return defval; - - xml_string = xmlNodeListGetString (node->doc, p, 1); - retval = atoi ((gchar *)xml_string); - xmlFree (xml_string); - - return retval; -} - -static gboolean -migrate_ldap_servers (MigrationContext *context, ESourceGroup *on_ldap_servers) -{ - gchar *sources_xml = g_strdup_printf ("%s/evolution/addressbook-sources.xml", - g_get_home_dir ()); - - printf ("trying to migrate from %s\n", sources_xml); - - if (g_file_test (sources_xml, G_FILE_TEST_EXISTS)) { - xmlDoc *doc = xmlParseFile (sources_xml); - xmlNode *root; - xmlNode *child; - gint num_contactservers; - gint servernum; - - if (!doc) - return FALSE; - - root = xmlDocGetRootElement (doc); - if (root == NULL || strcmp ((const gchar *)root->name, "addressbooks") != 0) { - xmlFreeDoc (doc); - return FALSE; - } - - /* count the number of servers, so we can give progress */ - num_contactservers = 0; - for (child = root->children; child; child = child->next) { - if (!strcmp ((const gchar *)child->name, "contactserver")) { - num_contactservers++; - } - } - printf ("found %d contact servers to migrate\n", num_contactservers); - - dialog_set_folder_name (context, _("LDAP Servers")); - - servernum = 0; - for (child = root->children; child; child = child->next) { - if (!strcmp ((const gchar *)child->name, "contactserver")) { - gchar *port, *host, *rootdn, *scope, *authmethod, *ssl; - gchar *emailaddr, *binddn, *limitstr; - gint limit; - gchar *name, *description; - GString *uri = g_string_new (""); - ESource *source; - - name = get_string_child (child, "name"); - description = get_string_child (child, "description"); - port = get_string_child (child, "port"); - host = get_string_child (child, "host"); - rootdn = get_string_child (child, "rootdn"); - scope = get_string_child (child, "scope"); - authmethod = get_string_child (child, "authmethod"); - ssl = get_string_child (child, "ssl"); - emailaddr = get_string_child (child, "emailaddr"); - binddn = get_string_child (child, "binddn"); - limit = get_integer_child (child, "limit", 100); - limitstr = g_strdup_printf ("%d", limit); - - g_string_append_printf (uri, - "%s:%s/%s?"/*trigraph prevention*/"?%s", - host, port, rootdn, scope); - - source = e_source_new (name, uri->str); - e_source_set_property (source, "description", description); - e_source_set_property (source, "limit", limitstr); - e_source_set_property (source, "ssl", ssl); - e_source_set_property (source, "auth", authmethod); - if (emailaddr) - e_source_set_property (source, "email_addr", emailaddr); - if (binddn) - e_source_set_property (source, "binddn", binddn); - - e_source_group_add_source (on_ldap_servers, source, -1); - - g_string_free (uri, TRUE); - g_free (port); - g_free (host); - g_free (rootdn); - g_free (scope); - g_free (authmethod); - g_free (ssl); - g_free (emailaddr); - g_free (binddn); - g_free (limitstr); - g_free (name); - g_free (description); - - servernum++; - dialog_set_progress (context, (double)servernum/num_contactservers); - } - } - - xmlFreeDoc (doc); - } - - g_free (sources_xml); - - return TRUE; -} - -static ESource* -get_source_by_name (ESourceList *source_list, const gchar *name) -{ - GSList *groups; - GSList *g; - - groups = e_source_list_peek_groups (source_list); - if (!groups) - return NULL; - - for (g = groups; g; g = g->next) { - GSList *sources; - GSList *s; - ESourceGroup *group = E_SOURCE_GROUP (g->data); - - sources = e_source_group_peek_sources (group); - if (!sources) - continue; - - for (s = sources; s; s = s->next) { - ESource *source = E_SOURCE (s->data); - const gchar *source_name = e_source_peek_name (source); - - if (!strcmp (name, source_name)) - return source; - } - } - - return NULL; -} - -static gboolean -migrate_completion_folders (MigrationContext *context) -{ - GConfClient *client; - const gchar *key; - gchar *uris_xml; - - printf ("trying to migrate completion folders\n"); - - client = gconf_client_get_default (); - key = "/apps/evolution/addressbook/completion/uris"; - uris_xml = gconf_client_get_string (client, key, NULL); - g_object_unref (client); - - if (uris_xml) { - xmlDoc *doc = xmlParseMemory (uris_xml, strlen (uris_xml)); - xmlNode *root; - xmlNode *child; - - if (!doc) - return FALSE; - - dialog_set_folder_name (context, _("Autocompletion Settings")); - - root = xmlDocGetRootElement (doc); - if (root == NULL || strcmp ((const gchar *)root->name, "EvolutionFolderList") != 0) { - xmlFreeDoc (doc); - return FALSE; - } - - for (child = root->children; child; child = child->next) { - if (!strcmp ((const gchar *)child->name, "folder")) { - gchar *physical_uri = e_xml_get_string_prop_by_name (child, (const guchar *)"physical-uri"); - ESource *source = NULL; - - /* if the physical uri is file://... - we look it up in our folder_uid_map - hashtable. If it's a folder we - converted over, we should get back - a uid we can search for. - - if the physical_uri is anything - else, we strip off the args - (anything after;) before searching - for the uri. */ - - if (!strncmp (physical_uri, "file://", 7)) { - gchar *filename = g_filename_from_uri (physical_uri, NULL, NULL); - gchar *uid = NULL; - - if (filename) - uid = g_hash_table_lookup (context->folder_uid_map, - filename); - g_free (filename); - if (uid) - source = e_source_list_peek_source_by_uid (context->source_list, uid); - } - else { - gchar *name = e_xml_get_string_prop_by_name (child, (const guchar *)"display-name"); - - source = get_source_by_name (context->source_list, name); - - g_free (name); - } - - if (source) { - e_source_set_property (source, "completion", "true"); - } - else { - g_warning ("found completion folder with uri `%s' that " - "doesn't correspond to anything we migrated.", physical_uri); - } - - g_free (physical_uri); - } - } - - g_free (uris_xml); - } - else { - g_message ("no completion folder settings to migrate"); - } - - return TRUE; -} - -static void -migrate_contact_lists_for_local_folders (MigrationContext *context, ESourceGroup *on_this_computer) -{ - GSList *sources, *s; - - sources = e_source_group_peek_sources (on_this_computer); - for (s = sources; s; s = s->next) { - ESource *source = s->data; - EBook *book; - EBookQuery *query; - GList *l, *contacts; - gint num_contacts, num_converted; - - dialog_set_folder_name (context, e_source_peek_name (source)); - - book = e_book_new (source, NULL); - if (!book - || !e_book_open (book, TRUE, NULL)) { - gchar *uri = e_source_get_uri (source); - g_warning ("failed to migrate contact lists for source %s", uri); - g_free (uri); - continue; - } - - query = e_book_query_any_field_contains (""); - e_book_get_contacts (book, query, &contacts, NULL); - e_book_query_unref (query); - - num_converted = 0; - num_contacts = g_list_length (contacts); - for (l = contacts; l; l = l->next) { - EContact *contact = l->data; - GError *e = NULL; - GList *attrs, *attr; - gboolean converted = FALSE; - - attrs = e_contact_get_attributes (contact, E_CONTACT_EMAIL); - for (attr = attrs; attr; attr = attr->next) { - EVCardAttribute *a = attr->data; - GList *v = e_vcard_attribute_get_values (a); - - if (v && v->data) { - if (!strncmp ((gchar *)v->data, "data); - - e_destination_export_to_vcard_attribute (dest, a); - - g_object_unref (dest); - - converted = TRUE; - } - } - } - - if (converted) { - e_contact_set_attributes (contact, E_CONTACT_EMAIL, attrs); - - if (!e_book_commit_contact (book, - contact, - &e)) - g_warning ("contact commit failed: `%s'", e->message); - } - - num_converted ++; - - dialog_set_progress (context, (double)num_converted / num_contacts); - } - - g_list_foreach (contacts, (GFunc)g_object_unref, NULL); - g_list_free (contacts); - - g_object_unref (book); - } -} - -static void -migrate_company_phone_for_local_folders (MigrationContext *context, ESourceGroup *on_this_computer) -{ - GSList *sources, *s; - - sources = e_source_group_peek_sources (on_this_computer); - for (s = sources; s; s = s->next) { - ESource *source = s->data; - EBook *book; - EBookQuery *query; - GList *l, *contacts; - gint num_contacts, num_converted; - - dialog_set_folder_name (context, e_source_peek_name (source)); - - book = e_book_new (source, NULL); - if (!book - || !e_book_open (book, TRUE, NULL)) { - gchar *uri = e_source_get_uri (source); - g_warning ("failed to migrate company phone numbers for source %s", uri); - g_free (uri); - continue; - } - - query = e_book_query_any_field_contains (""); - e_book_get_contacts (book, query, &contacts, NULL); - e_book_query_unref (query); - - num_converted = 0; - num_contacts = g_list_length (contacts); - for (l = contacts; l; l = l->next) { - EContact *contact = l->data; - GError *e = NULL; - GList *attrs, *attr; - gboolean converted = FALSE; - gint num_work_voice = 0; - - attrs = e_vcard_get_attributes (E_VCARD (contact)); - for (attr = attrs; attr;) { - EVCardAttribute *a = attr->data; - GList *next_attr = attr->next; - - if (!strcmp ("TEL", e_vcard_attribute_get_name (a))) { - GList *params, *param; - gboolean found_voice = FALSE; - gboolean found_work = FALSE; - - params = e_vcard_attribute_get_params (a); - for (param = params; param; param = param->next) { - EVCardAttributeParam *p = param->data; - if (!strcmp (EVC_TYPE, e_vcard_attribute_param_get_name (p))) { - GList *v = e_vcard_attribute_param_get_values (p); - while (v && v->data) { - if (!strcmp ("VOICE", v->data)) - found_voice = TRUE; - else if (!strcmp ("WORK", v->data)) - found_work = TRUE; - v = v->next; - } - } - - if (found_work && found_voice) - num_work_voice++; - - if (num_work_voice == 3) { - GList *v = e_vcard_attribute_get_values (a); - - if (v && v->data) - e_contact_set (contact, E_CONTACT_PHONE_COMPANY, v->data); - - e_vcard_remove_attribute (E_VCARD (contact), a); - - converted = TRUE; - break; - } - } - } - - attr = next_attr; - - if (converted) - break; - } - - if (converted) { - if (!e_book_commit_contact (book, - contact, - &e)) - g_warning ("contact commit failed: `%s'", e->message); - } - - num_converted ++; - - dialog_set_progress (context, (double)num_converted / num_contacts); - } - - g_list_foreach (contacts, (GFunc)g_object_unref, NULL); - g_list_free (contacts); - - g_object_unref (book); - } -} - -static void -migrate_pilot_data (const gchar *old_path, const gchar *new_path) -{ - const gchar *dent; - const gchar *ext; - gchar *filename; - GDir *dir; - - if (!(dir = g_dir_open (old_path, 0, NULL))) - return; - - while ((dent = g_dir_read_name (dir))) { - if ((!strncmp (dent, "pilot-map-", 10) && - ((ext = strrchr (dent, '.')) && !strcmp (ext, ".xml"))) || - (!strncmp (dent, "pilot-sync-evolution-addressbook-", 33) && - ((ext = strrchr (dent, '.')) && !strcmp (ext, ".db")))) { - /* src and dest file formats are identical for both map and changelog files */ - guchar inbuf[4096]; - gsize nread, nwritten; - gint fd0, fd1; - gssize n; - - filename = g_build_filename (old_path, dent, NULL); - if ((fd0 = g_open (filename, O_RDONLY | O_BINARY, 0)) == -1) { - g_free (filename); - continue; - } - - g_free (filename); - filename = g_build_filename (new_path, dent, NULL); - if ((fd1 = g_open (filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666)) == -1) { - g_free (filename); - close (fd0); - continue; - } - - do { - do { - n = read (fd0, inbuf, sizeof (inbuf)); - } while (n == -1 && errno == EINTR); - - if (n < 1) - break; - - nread = n; - nwritten = 0; - do { - do { - n = write (fd1, inbuf + nwritten, nread - nwritten); - } while (n == -1 && errno == EINTR); - - if (n > 0) - nwritten += n; - } while (nwritten < nread && n != -1); - - if (n == -1) - break; - } while (1); - - if (n != -1) - n = fsync (fd1); - - if (n == -1) { - g_warning ("Failed to migrate %s: %s", dent, g_strerror (errno)); - g_unlink (filename); - } - - close (fd0); - close (fd1); - g_free (filename); - } - } - - g_dir_close (dir); -} - -static MigrationContext * -migration_context_new (const gchar *data_dir) -{ - MigrationContext *context = g_new (MigrationContext, 1); - - /* set up the mapping from old uris to new uids */ - context->folder_uid_map = g_hash_table_new_full ( - g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_free); - - e_book_get_addressbooks (&context->source_list, NULL); - - context->data_dir = data_dir; - - return context; -} - -static void -migration_context_free (MigrationContext *context) -{ - e_source_list_sync (context->source_list, NULL); - - g_hash_table_destroy (context->folder_uid_map); - - g_object_unref (context->source_list); - - g_free (context); -} - -gboolean -e_book_shell_backend_migrate (EShellBackend *shell_backend, - gint major, - gint minor, - gint micro, - GError **error) -{ - ESourceGroup *on_this_computer; - ESourceGroup *on_ldap_servers; - ESource *personal_source; - MigrationContext *context; - gboolean need_dialog = FALSE; - const gchar *data_dir; - - g_return_val_if_fail (E_IS_SHELL_BACKEND (shell_backend), FALSE); - - data_dir = e_shell_backend_get_data_dir (shell_backend); - context = migration_context_new (data_dir); - - /* we call this unconditionally now - create_groups either - creates the groups/sources or it finds the necessary - groups/sources. */ - create_groups (context, &on_this_computer, &on_ldap_servers, &personal_source); - - /* figure out if we need the dialog displayed */ - if (major == 1 - /* we only need the most recent upgrade point here. - further decomposition will happen below. */ - && (minor < 5 || (minor == 5 && micro <= 10))) - need_dialog = TRUE; - - if (need_dialog) - setup_progress_dialog (context); - - if (major == 1) { - - if (minor < 5 || (minor == 5 && micro <= 2)) { - /* initialize our dialog */ - dialog_set_label (context, - _("The location and hierarchy of the Evolution contact " - "folders has changed since Evolution 1.x.\n\nPlease be " - "patient while Evolution migrates your folders...")); - - if (on_this_computer) - migrate_local_folders (context, on_this_computer, personal_source); - if (on_ldap_servers) - migrate_ldap_servers (context, on_ldap_servers); - - migrate_completion_folders (context); - } - - if (minor < 5 || (minor == 5 && micro <= 7)) { - dialog_set_label (context, - _("The format of mailing list contacts has changed.\n\n" - "Please be patient while Evolution migrates your " - "folders...")); - - migrate_contact_lists_for_local_folders (context, on_this_computer); - } - - if (minor < 5 || (minor == 5 && micro <= 8)) { - dialog_set_label (context, - _("The way Evolution stores some phone numbers has changed.\n\n" - "Please be patient while Evolution migrates your " - "folders...")); - - migrate_company_phone_for_local_folders (context, on_this_computer); - } - - if (minor < 5 || (minor == 5 && micro <= 10)) { - gchar *old_path, *new_path; - - dialog_set_label (context, _("Evolution's Palm Sync changelog and map files have changed.\n\n" - "Please be patient while Evolution migrates your Pilot Sync data...")); - - old_path = g_build_filename (g_get_home_dir (), "evolution", "local", "Contacts", NULL); - new_path = g_build_filename (data_dir, "local", "system", NULL); - migrate_pilot_data (old_path, new_path); - g_free (new_path); - g_free (old_path); - } - - /* we only need to do this next step if people ran - older versions of 1.5. We need to clear out the - absolute URI's that were assigned to ESources - during one phase of development, as they take - precedent over relative uris (but aren't updated - when editing an ESource). */ - if (minor == 5 && micro <= 11) { - GSList *g; - for (g = e_source_list_peek_groups (context->source_list); g; g = g->next) { - ESourceGroup *group = g->data; - GSList *s; - - for (s = e_source_group_peek_sources (group); s; s = s->next) { - ESource *source = s->data; - e_source_set_absolute_uri (source, NULL); - } - } - } - } - - if (need_dialog) - dialog_close (context); - - if (on_this_computer) - g_object_unref (on_this_computer); - if (on_ldap_servers) - g_object_unref (on_ldap_servers); - if (personal_source) - g_object_unref (personal_source); - - - migration_context_free (context); - - return TRUE; -} diff --git a/addressbook/gui/component/e-book-shell-migrate.h b/addressbook/gui/component/e-book-shell-migrate.h deleted file mode 100644 index cb6128910a..0000000000 --- a/addressbook/gui/component/e-book-shell-migrate.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * e-book-shell-migrate.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Chris Toshok (toshok@ximian.com) - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_BOOK_SHELL_MIGRATE_H -#define E_BOOK_SHELL_MIGRATE_H - -#include -#include - -G_BEGIN_DECLS - -gboolean e_book_shell_backend_migrate (EShellBackend *shell_backend, - gint major, - gint minor, - gint micro, - GError **error); - -G_END_DECLS - -#endif /* E_BOOK_SHELL_MIGRATE_H */ diff --git a/addressbook/gui/component/e-book-shell-sidebar.c b/addressbook/gui/component/e-book-shell-sidebar.c deleted file mode 100644 index fc283e28d7..0000000000 --- a/addressbook/gui/component/e-book-shell-sidebar.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * e-book-shell-sidebar.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-book-shell-sidebar.h" - -#include -#include - -#include "e-book-shell-view.h" -#include "e-book-shell-backend.h" -#include "e-addressbook-selector.h" - -#define E_BOOK_SHELL_SIDEBAR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_BOOK_SHELL_SIDEBAR, EBookShellSidebarPrivate)) - -struct _EBookShellSidebarPrivate { - GtkWidget *selector; -}; - -enum { - PROP_0, - PROP_SELECTOR -}; - -static gpointer parent_class; -static GType book_shell_sidebar_type; - -static void -book_shell_sidebar_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_SELECTOR: - g_value_set_object ( - value, e_book_shell_sidebar_get_selector ( - E_BOOK_SHELL_SIDEBAR (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -book_shell_sidebar_dispose (GObject *object) -{ - EBookShellSidebarPrivate *priv; - - priv = E_BOOK_SHELL_SIDEBAR_GET_PRIVATE (object); - - if (priv->selector != NULL) { - g_object_unref (priv->selector); - priv->selector = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -book_shell_sidebar_constructed (GObject *object) -{ - EBookShellSidebarPrivate *priv; - EShellView *shell_view; - EShellBackend *shell_backend; - EShellSidebar *shell_sidebar; - ESourceList *source_list; - GtkContainer *container; - GtkWidget *widget; - - priv = E_BOOK_SHELL_SIDEBAR_GET_PRIVATE (object); - - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (parent_class)->constructed (object); - - shell_sidebar = E_SHELL_SIDEBAR (object); - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - shell_backend = e_shell_view_get_shell_backend (shell_view); - - source_list = e_book_shell_backend_get_source_list ( - E_BOOK_SHELL_BACKEND (shell_backend)); - - container = GTK_CONTAINER (shell_sidebar); - - widget = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy ( - GTK_SCROLLED_WINDOW (widget), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type ( - GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); - gtk_container_add (container, widget); - gtk_widget_show (widget); - - container = GTK_CONTAINER (widget); - - widget = e_addressbook_selector_new (source_list); - e_source_selector_show_selection (E_SOURCE_SELECTOR (widget), FALSE); - gtk_container_add (GTK_CONTAINER (container), widget); - priv->selector = g_object_ref (widget); - gtk_widget_show (widget); -} - -static guint32 -book_shell_sidebar_check_state (EShellSidebar *shell_sidebar) -{ - EBookShellSidebar *book_shell_sidebar; - ESourceSelector *selector; - ESource *source; - gboolean is_system = FALSE; - guint32 state = 0; - - book_shell_sidebar = E_BOOK_SHELL_SIDEBAR (shell_sidebar); - selector = e_book_shell_sidebar_get_selector (book_shell_sidebar); - source = e_source_selector_peek_primary_selection (selector); - - if (source != NULL) { - const gchar *uri; - - uri = e_source_peek_relative_uri (source); - is_system = (uri == NULL || strcmp (uri, "system") == 0); - } - - if (source != NULL) - state |= E_BOOK_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE; - if (is_system) - state |= E_BOOK_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM; - - return state; -} - -static void -book_shell_sidebar_class_init (EBookShellSidebarClass *class) -{ - GObjectClass *object_class; - EShellSidebarClass *shell_sidebar_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (EBookShellSidebarPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->get_property = book_shell_sidebar_get_property; - object_class->dispose = book_shell_sidebar_dispose; - object_class->constructed = book_shell_sidebar_constructed; - - shell_sidebar_class = E_SHELL_SIDEBAR_CLASS (class); - shell_sidebar_class->check_state = book_shell_sidebar_check_state; - - g_object_class_install_property ( - object_class, - PROP_SELECTOR, - g_param_spec_object ( - "selector", - _("Source Selector Widget"), - _("This widget displays groups of address books"), - E_TYPE_SOURCE_SELECTOR, - G_PARAM_READABLE)); -} - -static void -book_shell_sidebar_init (EBookShellSidebar *book_shell_sidebar) -{ - book_shell_sidebar->priv = - E_BOOK_SHELL_SIDEBAR_GET_PRIVATE (book_shell_sidebar); - - /* Postpone widget construction until we have a shell view. */ -} - -GType -e_book_shell_sidebar_get_type (void) -{ - return book_shell_sidebar_type; -} - -void -e_book_shell_sidebar_register_type (GTypeModule *type_module) -{ - static const GTypeInfo type_info = { - sizeof (EBookShellSidebarClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) book_shell_sidebar_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (EBookShellSidebar), - 0, /* n_preallocs */ - (GInstanceInitFunc) book_shell_sidebar_init, - NULL /* value_table */ - }; - - book_shell_sidebar_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_SIDEBAR, - "EBookShellSidebar", &type_info, 0); -} - -GtkWidget * -e_book_shell_sidebar_new (EShellView *shell_view) -{ - g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - - return g_object_new ( - E_TYPE_BOOK_SHELL_SIDEBAR, - "shell-view", shell_view, NULL); -} - -ESourceSelector * -e_book_shell_sidebar_get_selector (EBookShellSidebar *book_shell_sidebar) -{ - g_return_val_if_fail ( - E_IS_BOOK_SHELL_SIDEBAR (book_shell_sidebar), NULL); - - return E_SOURCE_SELECTOR (book_shell_sidebar->priv->selector); -} diff --git a/addressbook/gui/component/e-book-shell-sidebar.h b/addressbook/gui/component/e-book-shell-sidebar.h deleted file mode 100644 index 716523f971..0000000000 --- a/addressbook/gui/component/e-book-shell-sidebar.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * e-book-shell-sidebar.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_BOOK_SHELL_SIDEBAR_H -#define E_BOOK_SHELL_SIDEBAR_H - -#include - -#include -#include - -/* Standard GObject macros */ -#define E_TYPE_BOOK_SHELL_SIDEBAR \ - (e_book_shell_sidebar_get_type ()) -#define E_BOOK_SHELL_SIDEBAR(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_BOOK_SHELL_SIDEBAR, EBookShellSidebar)) -#define E_BOOK_SHELL_SIDEBAR_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_BOOK_SHELL_SIDEBAR, EBookShellSidebarClass)) -#define E_IS_BOOK_SHELL_SIDEBAR(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_BOOK_SHELL_SIDEBAR)) -#define E_IS_BOOK_SHELL_SIDEBAR_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_BOOK_SHELL_SIDEBAR)) -#define E_BOOK_SHELL_SIDEBAR_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_BOOK_SHELL_SIDEBAR, EBookShellSidebarClass)) - -G_BEGIN_DECLS - -typedef struct _EBookShellSidebar EBookShellSidebar; -typedef struct _EBookShellSidebarClass EBookShellSidebarClass; -typedef struct _EBookShellSidebarPrivate EBookShellSidebarPrivate; - -enum { - E_BOOK_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE = 1 << 0, - E_BOOK_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM = 1 << 1 -}; - -struct _EBookShellSidebar { - EShellSidebar parent; - EBookShellSidebarPrivate *priv; -}; - -struct _EBookShellSidebarClass { - EShellSidebarClass parent_class; -}; - -GType e_book_shell_sidebar_get_type (void); -void e_book_shell_sidebar_register_type - (GTypeModule *type_module); -GtkWidget * e_book_shell_sidebar_new(EShellView *shell_view); -ESourceSelector * - e_book_shell_sidebar_get_selector - (EBookShellSidebar *book_shell_sidebar); - -G_END_DECLS - -#endif /* E_BOOK_SHELL_SIDEBAR_H */ diff --git a/addressbook/gui/component/e-book-shell-view-actions.c b/addressbook/gui/component/e-book-shell-view-actions.c deleted file mode 100644 index 773eb3fa7a..0000000000 --- a/addressbook/gui/component/e-book-shell-view-actions.c +++ /dev/null @@ -1,1011 +0,0 @@ -/* - * e-book-shell-view-actions.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-book-shell-view-private.h" - -#include -#include -#include - -#include - -static void -action_address_book_copy_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - e_addressbook_view_copy_to_folder (view, TRUE); -} - -static void -action_address_book_delete_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - EBookShellBackend *book_shell_backend; - EBookShellSidebar *book_shell_sidebar; - ESource *source; - ESourceSelector *selector; - ESourceGroup *source_group; - ESourceList *source_list; - EBook *book; - gint response; - GError *error = NULL; - - shell_view = E_SHELL_VIEW (book_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - book_shell_backend = book_shell_view->priv->book_shell_backend; - source_list = e_book_shell_backend_get_source_list (book_shell_backend); - - book_shell_sidebar = book_shell_view->priv->book_shell_sidebar; - selector = e_book_shell_sidebar_get_selector (book_shell_sidebar); - source = e_source_selector_peek_primary_selection (selector); - g_return_if_fail (source != NULL); - - response = e_error_run ( - GTK_WINDOW (shell_window), - "addressbook:ask-delete-addressbook", - e_source_peek_name (source)); - - if (response != GTK_RESPONSE_YES) - return; - - book = e_book_new (source, &error); - if (error != NULL) { - g_warning ("Error removing addressbook: %s", error->message); - g_error_free (error); - return; - } - - if (!e_book_remove (book, NULL)) { - e_error_run ( - GTK_WINDOW (shell_window), - "addressbook:remove-addressbook", NULL); - g_object_unref (book); - return; - } - - if (e_source_selector_source_is_selected (selector, source)) - e_source_selector_unselect_source (selector, source); - - source_group = e_source_peek_group (source); - e_source_group_remove_source (source_group, source); - - e_source_list_sync (source_list, NULL); - - g_object_unref (book); -} - -static void -action_address_book_move_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - e_addressbook_view_move_to_folder (view, TRUE); -} - -static void -action_address_book_new_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - - shell_view = E_SHELL_VIEW (book_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - addressbook_config_create_new_source (GTK_WIDGET (shell_window)); -} - -static void -action_address_book_properties_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - EBookShellSidebar *book_shell_sidebar; - ESource *source; - ESourceSelector *selector; - EditorUidClosure *closure; - GHashTable *uid_to_editor; - const gchar *uid; - - shell_view = E_SHELL_VIEW (book_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - book_shell_sidebar = book_shell_view->priv->book_shell_sidebar; - selector = e_book_shell_sidebar_get_selector (book_shell_sidebar); - source = e_source_selector_peek_primary_selection (selector); - g_return_if_fail (source != NULL); - - uid = e_source_peek_uid (source); - uid_to_editor = book_shell_view->priv->uid_to_editor; - - closure = g_hash_table_lookup (uid_to_editor, uid); - if (closure == NULL) { - GtkWidget *editor; - - editor = addressbook_config_edit_source ( - GTK_WIDGET (shell_window), source); - - closure = g_new (EditorUidClosure, 1); - closure->editor = editor; - closure->uid = g_strdup (uid); - closure->view = book_shell_view; - - g_hash_table_insert (uid_to_editor, closure->uid, closure); - - g_object_weak_ref ( - G_OBJECT (closure->editor), (GWeakNotify) - e_book_shell_view_editor_weak_notify, closure); - } - - gtk_window_present (GTK_WINDOW (closure->editor)); -} - -static void -action_address_book_rename_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellSidebar *book_shell_sidebar; - ESourceSelector *selector; - - book_shell_sidebar = book_shell_view->priv->book_shell_sidebar; - selector = e_book_shell_sidebar_get_selector (book_shell_sidebar); - - e_source_selector_edit_primary_selection (selector); -} - -static void -action_address_book_save_as_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - e_addressbook_view_save_as (view, TRUE); -} - -static void -action_address_book_stop_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - e_addressbook_view_stop (view); -} - -static void -action_contact_clipboard_copy_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - - book_shell_content = book_shell_view->priv->book_shell_content; - e_book_shell_content_clipboard_copy (book_shell_content); -} - -static void -action_contact_clipboard_cut_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - e_addressbook_view_cut (view); -} - -static void -action_contact_clipboard_paste_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - e_addressbook_view_paste (view); -} - -static void -action_contact_copy_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - e_addressbook_view_copy_to_folder (view, FALSE); -} - -static void -action_contact_delete_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - e_addressbook_view_delete_selection (view, TRUE); -} - -static void -action_contact_forward_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - GList *list, *iter; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - list = e_addressbook_view_get_selected (view); - g_return_if_fail (list != NULL); - - /* Convert the list of contacts to a list of destinations. */ - for (iter = list; iter != NULL; iter = iter->next) { - EContact *contact = iter->data; - EDestination *destination; - - destination = e_destination_new (); - e_destination_set_contact (destination, contact, 0); - g_object_unref (contact); - - iter->data = destination; - } - - eab_send_as_attachment (list); - g_list_foreach (list, (GFunc) g_object_unref, NULL); - g_list_free (list); -} - -static void -action_contact_move_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - e_addressbook_view_move_to_folder (view, FALSE); -} - -static void -action_contact_new_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - EAddressbookModel *model; - EContact *contact; - GtkWidget *editor; - EBook *book; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - model = e_addressbook_view_get_model (view); - book = e_addressbook_model_get_book (model); - g_return_if_fail (book != NULL); - - contact = e_contact_new (); - editor = e_contact_editor_new (book, contact, TRUE, TRUE); - eab_editor_show (EAB_EDITOR (editor)); - g_object_unref (contact); -} - -static void -action_contact_new_list_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - EAddressbookModel *model; - EContact *contact; - GtkWidget *editor; - EBook *book; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - model = e_addressbook_view_get_model (view); - book = e_addressbook_model_get_book (model); - g_return_if_fail (book != NULL); - - contact = e_contact_new (); - editor = e_contact_list_editor_new (book, contact, TRUE, TRUE); - eab_editor_show (EAB_EDITOR (editor)); - g_object_unref (contact); -} - -static void -action_contact_open_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - e_addressbook_view_view (view); -} - -static void -action_contact_preview_cb (GtkToggleAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - gboolean visible; - - book_shell_content = book_shell_view->priv->book_shell_content; - visible = gtk_toggle_action_get_active (action); - e_book_shell_content_set_preview_visible (book_shell_content, visible); -} - -static void -action_contact_print_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - GtkPrintOperationAction print_action; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; - e_addressbook_view_print (view, print_action); -} - -static void -action_contact_print_preview_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - GtkPrintOperationAction print_action; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW; - e_addressbook_view_print (view, print_action); -} - -static void -action_contact_save_as_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - e_addressbook_view_save_as (view, FALSE); -} - -static void -action_contact_search_cb (GtkRadioAction *action, - GtkRadioAction *current, - EBookShellView *book_shell_view) -{ - EShellView *shell_view; - EShellContent *shell_content; - const gchar *search_hint; - - /* XXX Figure out a way to handle this in EShellContent - * instead of every shell view having to handle it. - * The problem is EShellContent does not know what - * the search option actions are for this view. It - * would have to dig up the popup menu and retrieve - * the action for each menu item. Seems messy. */ - - shell_view = E_SHELL_VIEW (book_shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - - search_hint = gtk_action_get_label (GTK_ACTION (current)); - e_shell_content_set_search_hint (shell_content, search_hint); -} - -static void -action_contact_select_all_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - e_addressbook_view_select_all (view); -} - -static void -action_contact_send_message_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - GList *list, *iter; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - list = e_addressbook_view_get_selected (view); - g_return_if_fail (list != NULL); - - /* Convert the list of contacts to a list of destinations. */ - for (iter = list; iter != NULL; iter = iter->next) { - EContact *contact = iter->data; - EDestination *destination; - - destination = e_destination_new (); - e_destination_set_contact (destination, contact, 0); - g_object_unref (contact); - - iter->data = destination; - } - - eab_send_as_to (list); - g_list_foreach (list, (GFunc) g_object_unref, NULL); - g_list_free (list); -} - -static void -action_gal_save_custom_view_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EShellView *shell_view; - EAddressbookView *address_view; - GalViewInstance *view_instance; - - /* All shell views respond to the activation of this action, - * which is defined by EShellWindow. But only the currently - * active shell view proceeds with saving the custom view. */ - shell_view = E_SHELL_VIEW (book_shell_view); - if (!e_shell_view_is_active (shell_view)) - return; - - book_shell_content = book_shell_view->priv->book_shell_content; - address_view = e_book_shell_content_get_current_view (book_shell_content); - view_instance = e_addressbook_view_get_view_instance (address_view); - gal_view_instance_save_as (view_instance); -} - -static void -action_search_execute_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EShellView *shell_view; - - /* All shell views respond to the activation of this action, - * which is defined by EShellWindow. But only the currently - * active shell view proceeds with executing the search. */ - shell_view = E_SHELL_VIEW (book_shell_view); - if (!e_shell_view_is_active (shell_view)) - return; - - e_book_shell_view_execute_search (book_shell_view); -} - -static void -action_search_filter_cb (GtkRadioAction *action, - GtkRadioAction *current, - EBookShellView *book_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - - shell_view = E_SHELL_VIEW (book_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - gtk_action_activate (ACTION (SEARCH_EXECUTE)); -} - -static GtkActionEntry contact_entries[] = { - - { "address-book-copy", - GTK_STOCK_COPY, - N_("Co_py All Contacts To..."), - NULL, - N_("Copy the contacts of the selected address book to another"), - G_CALLBACK (action_address_book_copy_cb) }, - - { "address-book-delete", - GTK_STOCK_DELETE, - N_("Del_ete Address Book"), - NULL, - N_("Delete the selected address book"), - G_CALLBACK (action_address_book_delete_cb) }, - - { "address-book-move", - "folder-move", - N_("Mo_ve All Contacts To..."), - NULL, - N_("Move the contacts of the selected address book to another"), - G_CALLBACK (action_address_book_move_cb) }, - - { "address-book-new", - "address-book-new", - N_("_New Address Book"), - NULL, - N_("Create a new address book"), - G_CALLBACK (action_address_book_new_cb) }, - - { "address-book-properties", - GTK_STOCK_PROPERTIES, - N_("Address _Book Properties"), - NULL, - N_("Show properties of the selected address book"), - G_CALLBACK (action_address_book_properties_cb) }, - - { "address-book-rename", - NULL, - N_("_Rename..."), - "F2", - N_("Rename the selected address book"), - G_CALLBACK (action_address_book_rename_cb) }, - - { "address-book-save-as", - GTK_STOCK_SAVE_AS, - N_("S_ave Address Book as vCard"), - NULL, - N_("Save the contacts of the selected address book as a vCard"), - G_CALLBACK (action_address_book_save_as_cb) }, - - { "address-book-stop", - GTK_STOCK_STOP, - NULL, - NULL, - N_("Stop loading"), - G_CALLBACK (action_address_book_stop_cb) }, - - { "contact-clipboard-copy", - GTK_STOCK_COPY, - NULL, - NULL, - N_("Copy the selection"), - G_CALLBACK (action_contact_clipboard_copy_cb) }, - - { "contact-clipboard-cut", - GTK_STOCK_CUT, - NULL, - NULL, - N_("Cut the selection"), - G_CALLBACK (action_contact_clipboard_cut_cb) }, - - { "contact-clipboard-paste", - GTK_STOCK_PASTE, - NULL, - NULL, - N_("Paste the clipboard"), - G_CALLBACK (action_contact_clipboard_paste_cb) }, - - { "contact-copy", - NULL, - N_("_Copy Contact To..."), - "y", - N_("Copy selected contacts to another address book"), - G_CALLBACK (action_contact_copy_cb) }, - - { "contact-delete", - GTK_STOCK_DELETE, - N_("_Delete Contact"), - "d", - N_("Delete selected contacts"), - G_CALLBACK (action_contact_delete_cb) }, - - { "contact-forward", - "mail-forward", - N_("_Forward Contact..."), - NULL, - N_("Send selected contacts to another person"), - G_CALLBACK (action_contact_forward_cb) }, - - { "contact-move", - NULL, - N_("_Move Contact To..."), - "v", - N_("Move selected contacts to another address book"), - G_CALLBACK (action_contact_move_cb) }, - - { "contact-new", - "contact-new", - N_("_New Contact..."), - NULL, - N_("Create a new contact"), - G_CALLBACK (action_contact_new_cb) }, - - { "contact-new-list", - "stock_contact-list", - N_("New Contact _List..."), - NULL, - N_("Create a new contact list"), - G_CALLBACK (action_contact_new_list_cb) }, - - { "contact-open", - NULL, - N_("_Open"), - "o", - N_("View the current contact"), - G_CALLBACK (action_contact_open_cb) }, - - { "contact-save-as", - GTK_STOCK_SAVE_AS, - N_("Save as vCard..."), - NULL, - N_("Save selected contacts as a vCard"), - G_CALLBACK (action_contact_save_as_cb) }, - - { "contact-select-all", - GTK_STOCK_SELECT_ALL, - NULL, - NULL, - N_("Select all contacts"), - G_CALLBACK (action_contact_select_all_cb) }, - - { "contact-send-message", - "mail-message-new", - N_("_Send Message to Contact..."), - NULL, - N_("Send a message to the selected contacts"), - G_CALLBACK (action_contact_send_message_cb) }, - - /*** Menus ***/ - - { "actions-menu", - NULL, - N_("_Actions"), - NULL, - NULL, - NULL } -}; - -static EPopupActionEntry contact_popup_entries[] = { - - { "address-book-popup-delete", - N_("_Delete"), - "address-book-delete" }, - - { "address-book-popup-properties", - N_("_Properties"), - "address-book-properties" }, - - { "address-book-popup-rename", - NULL, - "address-book-rename" }, - - { "address-book-popup-save-as", - N_("_Save as vCard..."), - "address-book-save-as" }, - - { "contact-popup-clipboard-copy", - NULL, - "contact-clipboard-copy" }, - - { "contact-popup-clipboard-cut", - NULL, - "contact-clipboard-cut" }, - - { "contact-popup-clipboard-paste", - NULL, - "contact-clipboard-paste" }, - - { "contact-popup-copy", - NULL, - "contact-copy" }, - - { "contact-popup-delete", - NULL, - "contact-delete" }, - - { "contact-popup-forward", - NULL, - "contact-forward" }, - - { "contact-popup-move", - NULL, - "contact-move" }, - - { "contact-popup-open", - NULL, - "contact-open" }, - - { "contact-popup-save-as", - NULL, - "contact-save-as" }, - - { "contact-popup-send-message", - NULL, - "contact-send-message" }, -}; - -static GtkToggleActionEntry contact_toggle_entries[] = { - - { "contact-preview", - NULL, - N_("Contact _Preview"), - "m", - N_("Show contact preview window"), - G_CALLBACK (action_contact_preview_cb), - TRUE } -}; - -static GtkRadioActionEntry contact_filter_entries[] = { - - { "contact-filter-any-category", - NULL, - N_("Any Category"), - NULL, - NULL, - CONTACT_FILTER_ANY_CATEGORY }, - - { "contact-filter-unmatched", - NULL, - N_("Unmatched"), - NULL, - NULL, - CONTACT_FILTER_UNMATCHED } -}; - -static GtkRadioActionEntry contact_search_entries[] = { - - { "contact-search-any-field-contains", - NULL, - N_("Any field contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - CONTACT_SEARCH_ANY_FIELD_CONTAINS }, - - { "contact-search-email-begins-with", - NULL, - N_("Email begins with"), - NULL, - NULL, /* XXX Add a tooltip! */ - CONTACT_SEARCH_EMAIL_BEGINS_WITH }, - - { "contact-search-name-contains", - NULL, - N_("Name contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - CONTACT_SEARCH_NAME_CONTAINS } -}; - -static GtkActionEntry lockdown_printing_entries[] = { - - { "contact-print", - GTK_STOCK_PRINT, - NULL, - "p", - N_("Print selected contacts"), - G_CALLBACK (action_contact_print_cb) }, - - { "contact-print-preview", - GTK_STOCK_PRINT_PREVIEW, - NULL, - NULL, - N_("Preview the contacts to be printed"), - G_CALLBACK (action_contact_print_preview_cb) } -}; - -static EPopupActionEntry lockdown_printing_popup_entries[] = { - - { "contact-popup-print", - NULL, - "contact-print" } -}; - -void -e_book_shell_view_actions_init (EBookShellView *book_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - GtkActionGroup *action_group; - GConfBridge *bridge; - GtkAction *action; - GObject *object; - const gchar *key; - - shell_view = E_SHELL_VIEW (book_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - /* Contact Actions */ - action_group = ACTION_GROUP (CONTACTS); - gtk_action_group_add_actions ( - action_group, contact_entries, - G_N_ELEMENTS (contact_entries), book_shell_view); - e_action_group_add_popup_actions ( - action_group, contact_popup_entries, - G_N_ELEMENTS (contact_popup_entries)); - gtk_action_group_add_toggle_actions ( - action_group, contact_toggle_entries, - G_N_ELEMENTS (contact_toggle_entries), book_shell_view); - gtk_action_group_add_radio_actions ( - action_group, contact_search_entries, - G_N_ELEMENTS (contact_search_entries), - CONTACT_SEARCH_NAME_CONTAINS, - G_CALLBACK (action_contact_search_cb), book_shell_view); - - /* Lockdown Printing Actions */ - action_group = ACTION_GROUP (LOCKDOWN_PRINTING); - gtk_action_group_add_actions ( - action_group, lockdown_printing_entries, - G_N_ELEMENTS (lockdown_printing_entries), book_shell_view); - e_action_group_add_popup_actions ( - action_group, lockdown_printing_popup_entries, - G_N_ELEMENTS (lockdown_printing_popup_entries)); - - /* Bind GObject properties to GConf keys. */ - - bridge = gconf_bridge_get (); - - object = G_OBJECT (ACTION (CONTACT_PREVIEW)); - key = "/apps/evolution/addressbook/display/show_preview"; - gconf_bridge_bind_property (bridge, key, object, "active"); - - /* Fine tuning. */ - - action = ACTION (CONTACT_DELETE); - g_object_set (action, "short-label", _("Delete"), NULL); - - g_signal_connect ( - ACTION (GAL_SAVE_CUSTOM_VIEW), "activate", - G_CALLBACK (action_gal_save_custom_view_cb), book_shell_view); - - g_signal_connect ( - ACTION (SEARCH_EXECUTE), "activate", - G_CALLBACK (action_search_execute_cb), book_shell_view); -} - -void -e_book_shell_view_update_search_filter (EBookShellView *book_shell_view) -{ - EShellView *shell_view; - EShellContent *shell_content; - EShellWindow *shell_window; - GtkActionGroup *action_group; - GtkRadioAction *radio_action; - GList *list, *iter; - GSList *group; - gint ii; - - shell_view = E_SHELL_VIEW (book_shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - action_group = ACTION_GROUP (CONTACTS_FILTER); - e_action_group_remove_all_actions (action_group); - - /* Add the standard filter actions. */ - gtk_action_group_add_radio_actions ( - action_group, contact_filter_entries, - G_N_ELEMENTS (contact_filter_entries), - CONTACT_FILTER_ANY_CATEGORY, - G_CALLBACK (action_search_filter_cb), - book_shell_view); - - /* Retrieve the radio group from an action we just added. */ - list = gtk_action_group_list_actions (action_group); - radio_action = GTK_RADIO_ACTION (list->data); - group = gtk_radio_action_get_group (radio_action); - g_list_free (list); - - /* Build the category actions. */ - - list = e_categories_get_list (); - for (iter = list, ii = 0; iter != NULL; iter = iter->next, ii++) { - const gchar *category_name = iter->data; - const gchar *filename; - GtkAction *action; - gchar *action_name; - - action_name = g_strdup_printf ( - "contact-filter-category-%d", ii); - radio_action = gtk_radio_action_new ( - action_name, category_name, NULL, NULL, ii); - g_free (action_name); - - /* Convert the category icon file to a themed icon name. */ - filename = e_categories_get_icon_file_for (category_name); - if (filename != NULL && *filename != '\0') { - gchar *basename; - gchar *cp; - - basename = g_path_get_basename (filename); - - /* Lose the file extension. */ - if ((cp = strrchr (basename, '.')) != NULL) - *cp = '\0'; - - g_object_set ( - radio_action, "icon-name", basename, NULL); - - g_free (basename); - } - - gtk_radio_action_set_group (radio_action, group); - group = gtk_radio_action_get_group (radio_action); - - /* The action group takes ownership of the action. */ - action = GTK_ACTION (radio_action); - gtk_action_group_add_action (action_group, action); - g_object_unref (radio_action); - } - g_list_free (list); - - /* Use any action in the group; doesn't matter which. */ - e_shell_content_set_filter_action (shell_content, radio_action); - - ii = CONTACT_FILTER_UNMATCHED; - e_shell_content_add_filter_separator_after (shell_content, ii); -} diff --git a/addressbook/gui/component/e-book-shell-view-actions.h b/addressbook/gui/component/e-book-shell-view-actions.h deleted file mode 100644 index 8e3d31f7bf..0000000000 --- a/addressbook/gui/component/e-book-shell-view-actions.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * e-book-shell-view-actions.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_BOOK_SHELL_VIEW_ACTIONS_H -#define E_BOOK_SHELL_VIEW_ACTIONS_H - -#include - -/* Address Book Actions */ -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-copy") -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-delete") -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_MOVE(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-move") -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_PROPERTIES(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-properties") -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_RENAME(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-rename") -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_SAVE_AS(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-save-as") -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_STOP(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-stop") - -/* Contact Actions */ -#define E_SHELL_WINDOW_ACTION_CONTACT_CLIPBOARD_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-clipboard-copy") -#define E_SHELL_WINDOW_ACTION_CONTACT_CLIPBOARD_CUT(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-clipboard-cut") -#define E_SHELL_WINDOW_ACTION_CONTACT_CLIPBOARD_PASTE(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-clipboard-paste") -#define E_SHELL_WINDOW_ACTION_CONTACT_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-copy") -#define E_SHELL_WINDOW_ACTION_CONTACT_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-delete") -#define E_SHELL_WINDOW_ACTION_CONTACT_FORWARD(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-forward") -#define E_SHELL_WINDOW_ACTION_CONTACT_MOVE(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-move") -#define E_SHELL_WINDOW_ACTION_CONTACT_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-new") -#define E_SHELL_WINDOW_ACTION_CONTACT_NEW_LIST(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-new-list") -#define E_SHELL_WINDOW_ACTION_CONTACT_OPEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-open") -#define E_SHELL_WINDOW_ACTION_CONTACT_PREVIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-preview") -#define E_SHELL_WINDOW_ACTION_CONTACT_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-print") -#define E_SHELL_WINDOW_ACTION_CONTACT_PRINT_PREVIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-print-preview") -#define E_SHELL_WINDOW_ACTION_CONTACT_SAVE_AS(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-save-as") -#define E_SHELL_WINDOW_ACTION_CONTACT_SELECT_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-select-all") -#define E_SHELL_WINDOW_ACTION_CONTACT_SEND_MESSAGE(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-send-message") - -/* Search Actions */ -#define E_SHELL_WINDOW_ACTION_CONTACT_SEARCH_ANY_FIELD_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-search-any-field-contains") -#define E_SHELL_WINDOW_ACTION_CONTACT_SEARCH_EMAIL_BEGINS_WITH(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-search-email-begins-with") -#define E_SHELL_WINDOW_ACTION_CONTACT_SEARCH_NAME_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-search-name-contains") - -/* Action Groups */ -#define E_SHELL_WINDOW_ACTION_GROUP_CONTACTS(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "contacts") -#define E_SHELL_WINDOW_ACTION_GROUP_CONTACTS_FILTER(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "contacts-filter") - -#endif /* E_BOOK_SHELL_VIEW_ACTIONS_H */ diff --git a/addressbook/gui/component/e-book-shell-view-private.c b/addressbook/gui/component/e-book-shell-view-private.c deleted file mode 100644 index ec3562e87a..0000000000 --- a/addressbook/gui/component/e-book-shell-view-private.c +++ /dev/null @@ -1,621 +0,0 @@ -/* - * e-book-shell-view-private.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-book-shell-view-private.h" - -#include "widgets/menus/gal-view-factory-etable.h" -#include "addressbook/gui/widgets/gal-view-factory-minicard.h" - -#include "addressbook.h" - -static void -open_contact (EBookShellView *book_shell_view, - EContact *contact, - gboolean is_new_contact, - EAddressbookView *view) -{ - EAddressbookModel *model; - GtkWidget *editor; - EBook *book; - gboolean editable; - - model = e_addressbook_view_get_model (view); - book = e_addressbook_model_get_book (model); - editable = e_addressbook_model_get_editable (model); - - if (e_contact_get (contact, E_CONTACT_IS_LIST)) - editor = e_contact_list_editor_new ( - book, contact, is_new_contact, editable); - else - editor = e_contact_editor_new ( - book, contact, is_new_contact, editable); - - eab_editor_show (EAB_EDITOR (editor)); -} - -static void -popup_event (EBookShellView *book_shell_view, - GdkEventButton *event) -{ - EShellView *shell_view; - const gchar *widget_path; - - widget_path = "/contact-popup"; - shell_view = E_SHELL_VIEW (book_shell_view); - - e_shell_view_show_popup_menu (shell_view, widget_path, event); -} - -static void -book_shell_view_selection_change_foreach (gint row, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - EAddressbookModel *model; - EContact *contact; - - /* XXX A "foreach" function is kind of a silly way to retrieve - * the one and only selected contact, but this is the only - * means that ESelectionModel provides. */ - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - model = e_addressbook_view_get_model (view); - contact = e_addressbook_model_get_contact (model, row); - - e_book_shell_content_set_preview_contact (book_shell_content, contact); -} - -static void -selection_change (EBookShellView *book_shell_view, - EAddressbookView *view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *current_view; - ESelectionModel *selection_model; - EShellView *shell_view; - gint n_selected; - - shell_view = E_SHELL_VIEW (book_shell_view); - book_shell_content = book_shell_view->priv->book_shell_content; - current_view = e_book_shell_content_get_current_view (book_shell_content); - - if (view != current_view) - return; - - e_shell_view_update_actions (shell_view); - - selection_model = e_addressbook_view_get_selection_model (view); - - n_selected = (selection_model != NULL) ? - e_selection_model_selected_count (selection_model) : 0; - - if (n_selected == 1) - e_selection_model_foreach ( - selection_model, (EForeachFunc) - book_shell_view_selection_change_foreach, - book_shell_view); - else - e_book_shell_content_set_preview_contact ( - book_shell_content, NULL); -} - -static void -contact_changed (EBookShellView *book_shell_view, - EContact *contact) -{ - EBookShellContent *book_shell_content; - EContact *preview_contact; - - book_shell_content = book_shell_view->priv->book_shell_content; - - preview_contact = - e_book_shell_content_get_preview_contact (book_shell_content); - - if (contact != preview_contact) - return; - - /* Re-render the same contact. */ - e_book_shell_content_set_preview_contact (book_shell_content, contact); -} - -static void -contacts_removed (EBookShellView *book_shell_view, - GArray *removed_indices, - EAddressbookModel *model) -{ - EBookShellContent *book_shell_content; - EContact *preview_contact; - - book_shell_content = book_shell_view->priv->book_shell_content; - - preview_contact = - e_book_shell_content_get_preview_contact (book_shell_content); - - if (preview_contact == NULL) - return; - - /* Is the displayed contact still in the model? */ - if (e_addressbook_model_find (model, preview_contact) < 0) - return; - - /* If not, clear the contact display. */ - e_book_shell_content_set_preview_contact (book_shell_content, NULL); -} - -static void -book_open_cb (EBook *book, - EBookStatus status, - gpointer user_data) -{ - EAddressbookView *view = user_data; - EAddressbookModel *model; - ESource *source; - - source = e_book_get_source (book); - model = e_addressbook_view_get_model (view); - - if (status == E_BOOK_ERROR_OK) { - e_addressbook_model_set_book (model, book); - e_addressbook_model_force_folder_bar_message (model); - } else if (status != E_BOOK_ERROR_CANCELLED) - eab_load_error_dialog (NULL /* XXX */, source, status); -} - -static void -book_shell_view_activate_selected_source (EBookShellView *book_shell_view, - ESourceSelector *selector) -{ - EShellView *shell_view; - EBookShellContent *book_shell_content; - EAddressbookView *view; - EAddressbookModel *model; - ESource *source; - GalViewInstance *view_instance; - GHashTable *hash_table; - GtkWidget *widget; - const gchar *uid; - gchar *view_id; - - shell_view = E_SHELL_VIEW (book_shell_view); - book_shell_content = book_shell_view->priv->book_shell_content; - source = e_source_selector_peek_primary_selection (selector); - - if (source == NULL) - return; - - uid = e_source_peek_uid (source); - hash_table = book_shell_view->priv->uid_to_view; - widget = g_hash_table_lookup (hash_table, uid); - - if (widget != NULL) { - EBook *book; - - /* There is a view for this UID. Make sure the view - * actually contains an EBook. The absence of an EBook - * suggests a previous load failed, so try again. */ - view = E_ADDRESSBOOK_VIEW (widget); - model = e_addressbook_view_get_model (view); - source = e_addressbook_view_get_source (view); - - if (e_addressbook_model_get_book (model) == NULL) { - book = e_book_new (source, NULL); - - if (book != NULL) - addressbook_load (book, book_open_cb, view); - } - - } else { - EBook *book; - - /* Create a view for this UID. */ - widget = e_addressbook_view_new (shell_view, source); - gtk_widget_show (widget); - - e_book_shell_content_insert_view ( - book_shell_content, - E_ADDRESSBOOK_VIEW (widget)); - - g_hash_table_insert ( - hash_table, g_strdup (uid), - g_object_ref (widget)); - - g_signal_connect_swapped ( - widget, "open-contact", - G_CALLBACK (open_contact), book_shell_view); - - g_signal_connect_swapped ( - widget, "popup-event", - G_CALLBACK (popup_event), book_shell_view); - - g_signal_connect_swapped ( - widget, "command-state-change", - G_CALLBACK (e_shell_view_update_actions), - book_shell_view); - - g_signal_connect_swapped ( - widget, "selection-change", - G_CALLBACK (selection_change), book_shell_view); - - book = e_book_new (source, NULL); - view = E_ADDRESSBOOK_VIEW (widget); - - if (book != NULL) - addressbook_load (book, book_open_cb, view); - - model = e_addressbook_view_get_model (view); - - g_signal_connect_swapped ( - model, "contact-changed", - G_CALLBACK (contact_changed), book_shell_view); - - g_signal_connect_swapped ( - model, "contacts-removed", - G_CALLBACK (contacts_removed), book_shell_view); - } - - e_book_shell_content_set_current_view ( - book_shell_content, E_ADDRESSBOOK_VIEW (widget)); - - /* XXX We have to keep the addressbook selector informed of the - * current view so it can move contacts via drag-and-drop. */ - e_addressbook_selector_set_current_view ( - E_ADDRESSBOOK_SELECTOR (selector), - E_ADDRESSBOOK_VIEW (widget)); - - view_instance = e_addressbook_view_get_view_instance (view); - view_id = gal_view_instance_get_current_view_id (view_instance); - e_shell_view_set_view_id (shell_view, view_id); - g_free (view_id); - - e_addressbook_model_force_folder_bar_message (model); - selection_change (book_shell_view, view); -} - -static gboolean -book_shell_view_show_popup_menu (GdkEventButton *event, - EShellView *shell_view) -{ - const gchar *widget_path; - - widget_path = "/address-book-popup"; - e_shell_view_show_popup_menu (shell_view, widget_path, event); - - return TRUE; -} - -static gboolean -book_shell_view_selector_button_press_event_cb (EShellView *shell_view, - GdkEventButton *event) -{ - /* XXX Use ESourceSelector's "popup-event" signal instead. */ - - if (event->button == 3 && event->type == GDK_BUTTON_PRESS) - return book_shell_view_show_popup_menu (event, shell_view); - - return FALSE; -} - -static gboolean -book_shell_view_selector_popup_menu_cb (EShellView *shell_view) -{ - /* XXX Use ESourceSelector's "popup-event" signal instead. */ - - return book_shell_view_show_popup_menu (NULL, shell_view); -} - -static gboolean -book_shell_view_selector_key_press_event_cb (EShellView *shell_view, - GdkEventKey *event) -{ - EShellWindow *shell_window; - - /* Needed for the ACTION() macro. */ - shell_window = e_shell_view_get_shell_window (shell_view); - - if (event->keyval == GDK_Delete) { - gtk_action_activate (ACTION (ADDRESS_BOOK_DELETE)); - return TRUE; - } - - return FALSE; -} - -static void -book_shell_view_load_view_collection (EShellViewClass *shell_view_class) -{ - GalViewCollection *collection; - GalViewFactory *factory; - ETableSpecification *spec; - const gchar *base_dir; - gchar *filename; - - collection = shell_view_class->view_collection; - - base_dir = EVOLUTION_ETSPECDIR; - spec = e_table_specification_new (); - filename = g_build_filename (base_dir, ETSPEC_FILENAME, NULL); - if (!e_table_specification_load_from_file (spec, filename)) - g_critical ("Unable to load ETable specification file " - "for address book"); - g_free (filename); - - factory = gal_view_factory_etable_new (spec); - gal_view_collection_add_factory (collection, factory); - g_object_unref (factory); - g_object_unref (spec); - - factory = gal_view_factory_minicard_new (); - gal_view_collection_add_factory (collection, factory); - g_object_unref (factory); - - gal_view_collection_load (collection); -} - -static void -book_shell_view_notify_view_id_cb (EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *address_view; - GalViewInstance *view_instance; - const gchar *view_id; - - book_shell_content = book_shell_view->priv->book_shell_content; - address_view = e_book_shell_content_get_current_view (book_shell_content); - view_instance = e_addressbook_view_get_view_instance (address_view); - view_id = e_shell_view_get_view_id (E_SHELL_VIEW (book_shell_view)); - - /* A NULL view ID implies we're in a custom view. But you can - * only get to a custom view via the "Define Views" dialog, which - * would have already modified the view instance appropriately. - * Furthermore, there's no way to refer to a custom view by ID - * anyway, since custom views have no IDs. */ - if (view_id == NULL) - return; - - gal_view_instance_set_current_view_id (view_instance, view_id); -} - -void -e_book_shell_view_private_init (EBookShellView *book_shell_view, - EShellViewClass *shell_view_class) -{ - EBookShellViewPrivate *priv = book_shell_view->priv; - GHashTable *uid_to_view; - GHashTable *uid_to_editor; - - uid_to_view = g_hash_table_new_full ( - g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_object_unref); - - uid_to_editor = g_hash_table_new_full ( - g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_free); - - priv->uid_to_view = uid_to_view; - priv->uid_to_editor = uid_to_editor; - - if (!gal_view_collection_loaded (shell_view_class->view_collection)) - book_shell_view_load_view_collection (shell_view_class); - - g_signal_connect ( - book_shell_view, "notify::view-id", - G_CALLBACK (book_shell_view_notify_view_id_cb), NULL); -} - -void -e_book_shell_view_private_constructed (EBookShellView *book_shell_view) -{ - EBookShellViewPrivate *priv = book_shell_view->priv; - EShellContent *shell_content; - EShellSidebar *shell_sidebar; - EShellBackend *shell_backend; - EShellView *shell_view; - EShellWindow *shell_window; - ESourceSelector *selector; - - shell_view = E_SHELL_VIEW (book_shell_view); - shell_backend = e_shell_view_get_shell_backend (shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - e_shell_window_add_action_group (shell_window, "contacts"); - e_shell_window_add_action_group (shell_window, "contacts-filter"); - - /* Cache these to avoid lots of awkward casting. */ - priv->book_shell_backend = g_object_ref (shell_backend); - priv->book_shell_content = g_object_ref (shell_content); - priv->book_shell_sidebar = g_object_ref (shell_sidebar); - - selector = e_book_shell_sidebar_get_selector ( - E_BOOK_SHELL_SIDEBAR (shell_sidebar)); - - g_signal_connect_swapped ( - selector, "button-press-event", - G_CALLBACK (book_shell_view_selector_button_press_event_cb), - book_shell_view); - - g_signal_connect_swapped ( - selector, "key-press-event", - G_CALLBACK (book_shell_view_selector_key_press_event_cb), - book_shell_view); - - g_signal_connect_swapped ( - selector, "popup-menu", - G_CALLBACK (book_shell_view_selector_popup_menu_cb), - book_shell_view); - - g_signal_connect_swapped ( - selector, "primary-selection-changed", - G_CALLBACK (book_shell_view_activate_selected_source), - book_shell_view); - - e_categories_register_change_listener ( - G_CALLBACK (e_book_shell_view_update_search_filter), - book_shell_view); - - e_book_shell_view_actions_init (book_shell_view); - book_shell_view_activate_selected_source (book_shell_view, selector); - e_book_shell_view_update_search_filter (book_shell_view); -} - -void -e_book_shell_view_private_dispose (EBookShellView *book_shell_view) -{ - EBookShellViewPrivate *priv = book_shell_view->priv; - - DISPOSE (priv->book_shell_backend); - DISPOSE (priv->book_shell_content); - DISPOSE (priv->book_shell_sidebar); - - g_hash_table_remove_all (priv->uid_to_view); - g_hash_table_remove_all (priv->uid_to_editor); -} - -void -e_book_shell_view_private_finalize (EBookShellView *book_shell_view) -{ - EBookShellViewPrivate *priv = book_shell_view->priv; - - g_hash_table_destroy (priv->uid_to_view); - g_hash_table_destroy (priv->uid_to_editor); -} - -void -e_book_shell_view_execute_search (EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EShellView *shell_view; - EShellWindow *shell_window; - EShellContent *shell_content; - GtkAction *action; - GString *string; - EAddressbookView *view; - EAddressbookModel *model; - FilterRule *rule; - const gchar *format; - const gchar *text; - gchar *query; - gchar *temp; - gint value; - - shell_view = E_SHELL_VIEW (book_shell_view); - if (!e_shell_view_is_active (shell_view)) - return; - - shell_content = e_shell_view_get_shell_content (shell_view); - text = e_shell_content_get_search_text (shell_content); - - shell_window = e_shell_view_get_shell_window (shell_view); - action = ACTION (CONTACT_SEARCH_ANY_FIELD_CONTAINS); - value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); - - if (text == NULL || *text == '\0') { - text = ""; - value = CONTACT_SEARCH_ANY_FIELD_CONTAINS; - } - - switch (value) { - case CONTACT_SEARCH_NAME_CONTAINS: - format = "(contains \"full_name\" %s)"; - break; - - case CONTACT_SEARCH_EMAIL_BEGINS_WITH: - format = "(beginswith \"email\" %s)"; - break; - - default: - text = ""; - /* fall through */ - - case CONTACT_SEARCH_ANY_FIELD_CONTAINS: - format = "(contains \"x-evolution-any-field\" %s)"; - break; - } - - /* Build the query. */ - string = g_string_new (""); - e_sexp_encode_string (string, text); - query = g_strdup_printf (format, string->str); - g_string_free (string, TRUE); - - /* Apply selected filter. */ - value = e_shell_content_get_filter_value (shell_content); - switch (value) { - case CONTACT_FILTER_ANY_CATEGORY: - break; - - case CONTACT_FILTER_UNMATCHED: - temp = g_strdup_printf ( - "(and (not (and (exists \"CATEGORIES\") " - "(not (is \"CATEGORIES\" \"\")))) %s)", - query); - g_free (query); - query = temp; - break; - - default: - { - GList *categories; - const gchar *category_name; - - categories = e_categories_get_list (); - category_name = g_list_nth_data (categories, value); - g_list_free (categories); - - temp = g_strdup_printf ( - "(and (is \"category_list\" \"%s\") %s)", - category_name, query); - g_free (query); - query = temp; - } - } - - /* XXX This is wrong. We need to programmatically construct a - * FilterRule, tell it to build code, and pass the resulting - * expression string to EAddressbookModel. */ - rule = filter_rule_new (); - e_shell_content_set_search_rule (shell_content, rule); - g_object_unref (rule); - - /* Submit the query. */ - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - model = e_addressbook_view_get_model (view); - e_addressbook_model_set_query (model, query); - g_free (query); - - e_book_shell_content_set_preview_contact (book_shell_content, NULL); -} - -void -e_book_shell_view_editor_weak_notify (EditorUidClosure *closure, - GObject *where_the_object_was) -{ - GHashTable *hash_table; - - hash_table = closure->view->priv->uid_to_editor; - g_hash_table_remove (hash_table, closure->uid); -} diff --git a/addressbook/gui/component/e-book-shell-view-private.h b/addressbook/gui/component/e-book-shell-view-private.h deleted file mode 100644 index b4701aea81..0000000000 --- a/addressbook/gui/component/e-book-shell-view-private.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * e-book-shell-view-private.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_BOOK_SHELL_VIEW_PRIVATE_H -#define E_BOOK_SHELL_VIEW_PRIVATE_H - -#include "e-book-shell-view.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "e-util/gconf-bridge.h" -#include "shell/e-shell-content.h" -#include "shell/e-shell-sidebar.h" -#include "misc/e-popup-action.h" - -#include "addressbook/gui/contact-editor/e-contact-editor.h" -#include "addressbook/gui/contact-list-editor/e-contact-list-editor.h" -#include "addressbook/gui/widgets/eab-gui-util.h" -#include "addressbook/gui/widgets/e-addressbook-view.h" -#include "addressbook/gui/widgets/e-addressbook-selector.h" - -#include "e-book-shell-backend.h" -#include "e-book-shell-content.h" -#include "e-book-shell-sidebar.h" -#include "e-book-shell-view-actions.h" - -#define E_BOOK_SHELL_VIEW_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_BOOK_SHELL_VIEW, EBookShellViewPrivate)) - -/* Shorthand, requires a variable named "shell_window". */ -#define ACTION(name) \ - (E_SHELL_WINDOW_ACTION_##name (shell_window)) -#define ACTION_GROUP(name) \ - (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) - -/* For use in dispose() methods. */ -#define DISPOSE(obj) \ - G_STMT_START { \ - if ((obj) != NULL) { g_object_unref (obj); (obj) = NULL; } \ - } G_STMT_END - -/* ETable Specifications */ -#define ETSPEC_FILENAME "e-addressbook-view.etspec" - -G_BEGIN_DECLS - -typedef struct _EditorUidClosure EditorUidClosure; - -struct _EditorUidClosure { - GtkWidget *editor; - gchar *uid; - EBookShellView *view; -}; - -/* List these in the order to be displayed. - * Positive values are reserved for categories. */ -enum { - CONTACT_FILTER_ANY_CATEGORY = -2, - CONTACT_FILTER_UNMATCHED = -1 -}; - -/* List these in the order to be displayed. */ -enum { - CONTACT_SEARCH_NAME_CONTAINS, - CONTACT_SEARCH_EMAIL_BEGINS_WITH, - CONTACT_SEARCH_ANY_FIELD_CONTAINS -}; - -struct _EBookShellViewPrivate { - - /* These are just for convenience. */ - EBookShellBackend *book_shell_backend; - EBookShellContent *book_shell_content; - EBookShellSidebar *book_shell_sidebar; - - GHashTable *uid_to_view; - GHashTable *uid_to_editor; -}; - -void e_book_shell_view_private_init - (EBookShellView *book_shell_view, - EShellViewClass *shell_view_class); -void e_book_shell_view_private_constructed - (EBookShellView *book_shell_view); -void e_book_shell_view_private_dispose - (EBookShellView *book_shell_view); -void e_book_shell_view_private_finalize - (EBookShellView *book_shell_view); - -/* Private Utilities */ - -void e_book_shell_view_actions_init - (EBookShellView *book_shell_view); -void e_book_shell_view_execute_search - (EBookShellView *book_shell_view); -void e_book_shell_view_editor_weak_notify - (EditorUidClosure *closure, - GObject *where_the_object_was); -void e_book_shell_view_update_search_filter - (EBookShellView *book_shell_view); - -G_END_DECLS - -#endif /* E_BOOK_SHELL_VIEW_PRIVATE_H */ diff --git a/addressbook/gui/component/e-book-shell-view.c b/addressbook/gui/component/e-book-shell-view.c deleted file mode 100644 index ea48bb534c..0000000000 --- a/addressbook/gui/component/e-book-shell-view.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * e-book-shell-view.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-book-shell-view-private.h" - -static gpointer parent_class; -static GType book_shell_view_type; - -static void -book_shell_view_source_list_changed_cb (EBookShellView *book_shell_view, - ESourceList *source_list) -{ - EBookShellViewPrivate *priv = book_shell_view->priv; - EBookShellContent *book_shell_content; - EShellView *shell_view; - GList *keys, *iter; - - shell_view = E_SHELL_VIEW (book_shell_view); - book_shell_content = book_shell_view->priv->book_shell_content; - - keys = g_hash_table_get_keys (priv->uid_to_view); - for (iter = keys; iter != NULL; iter = iter->next) { - gchar *uid = iter->data; - EAddressbookView *view; - - /* If the source still exists, move on. */ - if (e_source_list_peek_source_by_uid (source_list, uid)) - continue; - - /* Remove the view for the deleted source. */ - view = g_hash_table_lookup (priv->uid_to_view, uid); - e_book_shell_content_remove_view (book_shell_content, view); - g_hash_table_remove (priv->uid_to_view, uid); - } - g_list_free (keys); - - keys = g_hash_table_get_keys (priv->uid_to_editor); - for (iter = keys; iter != NULL; iter = iter->next) { - gchar *uid = iter->data; - EditorUidClosure *closure; - - /* If the source still exists, move on. */ - if (e_source_list_peek_source_by_uid (source_list, uid)) - continue; - - /* Remove the editor for the deleted source. */ - closure = g_hash_table_lookup (priv->uid_to_editor, uid); - g_object_weak_unref ( - G_OBJECT (closure->editor), (GWeakNotify) - e_book_shell_view_editor_weak_notify, closure); - gtk_widget_destroy (closure->editor); - g_hash_table_remove (priv->uid_to_editor, uid); - } - g_list_free (keys); - - e_shell_view_update_actions (shell_view); -} - -static void -book_shell_view_dispose (GObject *object) -{ - EBookShellView *book_shell_view; - - book_shell_view = E_BOOK_SHELL_VIEW (object); - e_book_shell_view_private_dispose (book_shell_view); - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -book_shell_view_finalize (GObject *object) -{ - EBookShellView *book_shell_view; - - book_shell_view = E_BOOK_SHELL_VIEW (object); - e_book_shell_view_private_finalize (book_shell_view); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -book_shell_view_constructed (GObject *object) -{ - EBookShellView *book_shell_view; - EBookShellBackend *book_shell_backend; - ESourceList *source_list; - - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (parent_class)->constructed (object); - - book_shell_view = E_BOOK_SHELL_VIEW (object); - e_book_shell_view_private_constructed (book_shell_view); - - book_shell_backend = book_shell_view->priv->book_shell_backend; - source_list = e_book_shell_backend_get_source_list (book_shell_backend); - - g_signal_connect_swapped ( - source_list, "changed", - G_CALLBACK (book_shell_view_source_list_changed_cb), - book_shell_view); -} - -static void -book_shell_view_update_actions (EShellView *shell_view) -{ - EBookShellViewPrivate *priv; - EShellContent *shell_content; - EShellSidebar *shell_sidebar; - EShellWindow *shell_window; - GtkAction *action; - const gchar *label; - gboolean sensitive; - guint32 state; - - /* Be descriptive. */ - gboolean any_contacts_selected; - gboolean has_primary_source; - gboolean multiple_contacts_selected; - gboolean primary_source_is_system; - gboolean single_contact_selected; - gboolean selection_is_contact_list; - gboolean selection_has_email; - gboolean source_is_busy; - gboolean source_is_editable; - gboolean source_is_empty; - - priv = E_BOOK_SHELL_VIEW_GET_PRIVATE (shell_view); - - shell_window = e_shell_view_get_shell_window (shell_view); - - shell_content = e_shell_view_get_shell_content (shell_view); - state = e_shell_content_check_state (shell_content); - - single_contact_selected = - (state & E_BOOK_SHELL_CONTENT_SELECTION_SINGLE); - multiple_contacts_selected = - (state & E_BOOK_SHELL_CONTENT_SELECTION_MULTIPLE); - selection_has_email = - (state & E_BOOK_SHELL_CONTENT_SELECTION_HAS_EMAIL); - selection_is_contact_list = - (state & E_BOOK_SHELL_CONTENT_SELECTION_IS_CONTACT_LIST); - source_is_busy = - (state & E_BOOK_SHELL_CONTENT_SOURCE_IS_BUSY); - source_is_editable = - (state & E_BOOK_SHELL_CONTENT_SOURCE_IS_EDITABLE); - source_is_empty = - (state & E_BOOK_SHELL_CONTENT_SOURCE_IS_EMPTY); - - shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - state = e_shell_sidebar_check_state (shell_sidebar); - - has_primary_source = - (state & E_BOOK_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE); - primary_source_is_system = - (state & E_BOOK_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM); - - any_contacts_selected = - (single_contact_selected || multiple_contacts_selected); - - action = ACTION (ADDRESS_BOOK_DELETE); - sensitive = has_primary_source && !primary_source_is_system; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (ADDRESS_BOOK_RENAME); - sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (ADDRESS_BOOK_STOP); - sensitive = source_is_busy; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_CLIPBOARD_COPY); - sensitive = any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_CLIPBOARD_CUT); - sensitive = source_is_editable && any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_CLIPBOARD_PASTE); - sensitive = source_is_editable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_COPY); - sensitive = any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_DELETE); - sensitive = source_is_editable && any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_FORWARD); - sensitive = any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); - if (multiple_contacts_selected) - label = _("_Forward Contacts"); - else - label = _("_Forward Contact"); - g_object_set (action, "label", label, NULL); - - action = ACTION (CONTACT_MOVE); - sensitive = source_is_editable && any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_OPEN); - sensitive = any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_PRINT); - sensitive = any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_PRINT_PREVIEW); - sensitive = any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_SAVE_AS); - sensitive = any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_SELECT_ALL); - sensitive = !(source_is_empty); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_SEND_MESSAGE); - sensitive = any_contacts_selected && selection_has_email; - gtk_action_set_sensitive (action, sensitive); - if (multiple_contacts_selected) - label = _("_Send Message to Contacts"); - else if (selection_is_contact_list) - label = _("_Send Message to List"); - else - label = _("_Send Message to Contact"); - g_object_set (action, "label", label, NULL); -} - -static void -book_shell_view_class_init (EBookShellViewClass *class) -{ - GObjectClass *object_class; - EShellViewClass *shell_view_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (EBookShellViewPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->dispose = book_shell_view_dispose; - object_class->finalize = book_shell_view_finalize; - object_class->constructed = book_shell_view_constructed; - - shell_view_class = E_SHELL_VIEW_CLASS (class); - shell_view_class->label = _("Contacts"); - shell_view_class->icon_name = "x-office-address-book"; - shell_view_class->ui_definition = "evolution-contacts.ui"; - shell_view_class->ui_manager_id = "org.gnome.evolution.contacts"; - shell_view_class->search_options = "/contact-search-options"; - shell_view_class->search_rules = "addresstypes.xml"; - shell_view_class->new_shell_content = e_book_shell_content_new; - shell_view_class->new_shell_sidebar = e_book_shell_sidebar_new; - shell_view_class->update_actions = book_shell_view_update_actions; -} - -static void -book_shell_view_init (EBookShellView *book_shell_view, - EShellViewClass *shell_view_class) -{ - book_shell_view->priv = - E_BOOK_SHELL_VIEW_GET_PRIVATE (book_shell_view); - - e_book_shell_view_private_init (book_shell_view, shell_view_class); -} - -GType -e_book_shell_view_get_type (void) -{ - return book_shell_view_type; -} - -void -e_book_shell_view_register_type (GTypeModule *type_module) -{ - const GTypeInfo type_info = { - sizeof (EBookShellViewClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) book_shell_view_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (EBookShellView), - 0, /* n_preallocs */ - (GInstanceInitFunc) book_shell_view_init, - NULL /* value_table */ - }; - - book_shell_view_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_VIEW, - "EBookShellView", &type_info, 0); -} diff --git a/addressbook/gui/component/e-book-shell-view.h b/addressbook/gui/component/e-book-shell-view.h deleted file mode 100644 index 33a0c8a75d..0000000000 --- a/addressbook/gui/component/e-book-shell-view.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * e-book-shell-view.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_BOOK_SHELL_VIEW_H -#define E_BOOK_SHELL_VIEW_H - -#include - -/* Standard GObject macros */ -#define E_TYPE_BOOK_SHELL_VIEW \ - (e_book_shell_view_get_type ()) -#define E_BOOK_SHELL_VIEW(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_BOOK_SHELL_VIEW, EBookShellView)) -#define E_BOOK_SHELL_VIEW_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_BOOK_SHELL_VIEW, EBookShellViewClass)) -#define E_IS_BOOK_SHELL_VIEW(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_BOOK_SHELL_VIEW)) -#define E_IS_BOOK_SHELL_VIEW_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_BOOK_SHELL_VIEW)) -#define E_BOOK_SHELL_VIEW_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_BOOK_SHELL_VIEW, EBookShellViewClass)) - -G_BEGIN_DECLS - -typedef struct _EBookShellView EBookShellView; -typedef struct _EBookShellViewClass EBookShellViewClass; -typedef struct _EBookShellViewPrivate EBookShellViewPrivate; - -struct _EBookShellView { - EShellView parent; - EBookShellViewPrivate *priv; -}; - -struct _EBookShellViewClass { - EShellViewClass parent_class; -}; - -GType e_book_shell_view_get_type (void); -void e_book_shell_view_register_type (GTypeModule *type_module); - -G_END_DECLS - -#endif /* E_BOOK_SHELL_VIEW_H */ diff --git a/addressbook/gui/component/eab-composer-util.c b/addressbook/gui/component/eab-composer-util.c deleted file mode 100644 index 6d45f13a94..0000000000 --- a/addressbook/gui/component/eab-composer-util.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "eab-composer-util.h" - -#include -#include -#include -#include - -#include "composer/e-msg-composer.h" -#include "addressbook/util/eab-book-util.h" -#include "addressbook/gui/widgets/eab-gui-util.h" - -void -eab_send_as_to (GList *destinations) -{ - EMsgComposer *composer; - EComposerHeaderTable *table; - GPtrArray *to_array; - GPtrArray *bcc_array; - - union { - gpointer *pdata; - EDestination **destinations; - } convert; - - if (destinations == NULL) - return; - - composer = e_msg_composer_new (); - table = e_msg_composer_get_header_table (composer); - - to_array = g_ptr_array_new (); - bcc_array = g_ptr_array_new (); - - /* Sort contacts into "To" and "Bcc" destinations. */ - while (destinations != NULL) { - EDestination *destination = destinations->data; - - if (e_destination_is_evolution_list (destination)) { - if (e_destination_list_show_addresses (destination)) - g_ptr_array_add (to_array, destination); - else - g_ptr_array_add (bcc_array, destination); - } else - g_ptr_array_add (to_array, destination); - - destinations = g_list_next (destinations); - } - - /* Add sentinels to each array. */ - g_ptr_array_add (to_array, NULL); - g_ptr_array_add (bcc_array, NULL); - - /* XXX Acrobatics like this make me question whether NULL-terminated - * arrays are really the best argument type for passing a list of - * destinations to the header table. */ - - /* Add "To" destinations. */ - convert.pdata = to_array->pdata; - e_composer_header_table_set_destinations_to ( - table, convert.destinations); - g_ptr_array_free (to_array, FALSE); - e_destination_freev (convert.destinations); - - /* Add "Bcc" destinations. */ - convert.pdata = bcc_array->pdata; - e_composer_header_table_set_destinations_bcc ( - table, convert.destinations); - g_ptr_array_free (bcc_array, FALSE); - e_destination_freev (convert.destinations); - - gtk_widget_show (GTK_WIDGET (composer)); -} - -static const gchar * -get_email (EContact *contact, EContactField field_id, gchar **to_free) -{ - gchar *name = NULL, *mail = NULL; - const gchar *value = e_contact_get_const (contact, field_id); - - *to_free = NULL; - - if (eab_parse_qp_email (value, &name, &mail)) { - *to_free = g_strdup_printf ("%s <%s>", name, mail); - value = *to_free; - } - - g_free (name); - g_free (mail); - - return value; -} - -void -eab_send_as_attachment (GList *destinations) -{ - EMsgComposer *composer; - EComposerHeaderTable *table; - CamelMimePart *attachment; - GList *contacts, *iter; - gchar *data; - - if (destinations == NULL) - return; - - composer = e_msg_composer_new (); - table = e_msg_composer_get_header_table (composer); - - attachment = camel_mime_part_new (); - - contacts = g_list_copy (destinations); - for (iter = contacts; iter != NULL; iter = iter->next) - iter->data = e_destination_get_contact (iter->data); - data = eab_contact_list_to_string (contacts); - g_list_free (contacts); - - camel_mime_part_set_content ( - attachment, data, strlen (data), "text/x-vcard"); - - if (destinations->next != NULL) - camel_mime_part_set_description ( - attachment, _("Multiple vCards")); - else { - EContact *contact; - const gchar *file_as; - gchar *description; - - contact = e_destination_get_contact (destinations->data); - file_as = e_contact_get_const (contact, E_CONTACT_FILE_AS); - description = g_strdup_printf (_("vCard for %s"), file_as); - camel_mime_part_set_description (attachment, description); - g_free (description); - } - - camel_mime_part_set_disposition (attachment, "attachment"); - - e_msg_composer_attach (composer, attachment); - camel_object_unref (attachment); - - if (destinations->next != NULL) - e_composer_header_table_set_subject ( - table, _("Contact information")); - else { - EContact *contact; - gchar *tempstr; - const gchar *tempstr2; - gchar *tempfree = NULL; - - contact = e_destination_get_contact (destinations->data); - tempstr2 = e_contact_get_const (contact, E_CONTACT_FILE_AS); - if (!tempstr2 || !*tempstr2) - tempstr2 = e_contact_get_const (contact, E_CONTACT_FULL_NAME); - if (!tempstr2 || !*tempstr2) - tempstr2 = e_contact_get_const (contact, E_CONTACT_ORG); - if (!tempstr2 || !*tempstr2) { - g_free (tempfree); - tempstr2 = get_email (contact, E_CONTACT_EMAIL_1, &tempfree); - } - if (!tempstr2 || !*tempstr2) { - g_free (tempfree); - tempstr2 = get_email (contact, E_CONTACT_EMAIL_2, &tempfree); - } - if (!tempstr2 || !*tempstr2) { - g_free (tempfree); - tempstr2 = get_email (contact, E_CONTACT_EMAIL_3, &tempfree); - } - - if (!tempstr2 || !*tempstr2) - tempstr = g_strdup_printf (_("Contact information")); - else - tempstr = g_strdup_printf (_("Contact information for %s"), tempstr2); - - e_composer_header_table_set_subject (table, tempstr); - - g_free (tempstr); - g_free (tempfree); - } - - gtk_widget_show (GTK_WIDGET (composer)); -} diff --git a/addressbook/gui/component/eab-composer-util.h b/addressbook/gui/component/eab-composer-util.h deleted file mode 100644 index 4aec23074d..0000000000 --- a/addressbook/gui/component/eab-composer-util.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef EAB_COMPOSER_UTIL_H -#define EAB_COMPOSER_UTIL_H - -#include - -G_BEGIN_DECLS - -void eab_send_as_to (GList *destinations); -void eab_send_as_attachment (GList *destinations); - -G_END_DECLS - -#endif /* EAB_COMPOSER_UTIL_H */ diff --git a/addressbook/gui/component/evolution-module-addressbook.c b/addressbook/gui/component/evolution-module-addressbook.c deleted file mode 100644 index 3089133e43..0000000000 --- a/addressbook/gui/component/evolution-module-addressbook.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * evolution-module-addressbook.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-book-shell-backend.h" -#include "e-book-shell-content.h" -#include "e-book-shell-sidebar.h" -#include "e-book-shell-view.h" - -/* Module Entry Points */ -void e_module_load (GTypeModule *type_module); -void e_module_unload (GTypeModule *type_module); - -G_MODULE_EXPORT void -e_module_load (GTypeModule *type_module) -{ - /* Register dynamically loaded types. */ - - e_book_shell_backend_register_type (type_module); - e_book_shell_content_register_type (type_module); - e_book_shell_sidebar_register_type (type_module); - e_book_shell_view_register_type (type_module); -} - -G_MODULE_EXPORT void -e_module_unload (GTypeModule *type_module) -{ -} diff --git a/addressbook/gui/component/ldap-config.glade b/addressbook/gui/component/ldap-config.glade deleted file mode 100644 index f87cf84b14..0000000000 --- a/addressbook/gui/component/ldap-config.glade +++ /dev/null @@ -1,1454 +0,0 @@ - - - - - - - True - Address Book Properties - GTK_WINDOW_TOPLEVEL - GTK_WIN_POS_NONE - False - True - False - True - False - False - GDK_WINDOW_TYPE_HINT_DIALOG - GDK_GRAVITY_NORTH_WEST - True - False - False - - - - True - False - 0 - - - - True - GTK_BUTTONBOX_END - - - - True - True - True - gtk-cancel - True - GTK_RELIEF_NORMAL - True - -6 - - - - - - True - True - True - gtk-ok - True - GTK_RELIEF_NORMAL - True - -5 - - - - - 0 - False - True - GTK_PACK_END - - - - - - 12 - True - True - True - True - GTK_POS_TOP - False - False - - - - 12 - True - False - 12 - - - - True - Display - False - True - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - False - 6 - - - - True - - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - _Name: - True - False - GTK_JUSTIFY_CENTER - False - False - 0 - 0.5 - 0 - 0 - account-editor-display-name-entry - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - This is the name for this server that will appear in your Evolution folder list. It is for display purposes only. - True - True - True - 0 - - True - * - False - - - 0 - True - True - - - - - 0 - False - False - - - - - - False - 12 - - - - True - Server Information - False - True - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - False - 12 - - - - True - - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - 3 - 2 - False - 6 - 6 - - - - True - _Port: - True - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - 1 - 1 - 2 - fill - - - - - - - True - _Server: - True - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - server-name-entry - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - 1 - 0 - 1 - fill - - - - - - - True - False - 6 - - - - True - _Use secure connection: - True - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - ssl-combobox - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - SSL encryption -TLS encryption -No encryption - False - True - - - 0 - True - True - - - - - 0 - 2 - 2 - 3 - expand|shrink|fill - shrink|fill - - - - - - True - This is the full name of your LDAP server. For example, "ldap.mycompany.com". - True - True - True - True - 0 - - True - * - False - - - 1 - 2 - 0 - 1 - - - - - - - True - 389 -636 -3268 - False - True - True - - - 1 - 2 - 1 - 2 - fill - fill - - - - - 0 - True - True - - - - - 0 - True - True - - - - - - True - <b>Authentication</b> - False - True - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - False - 12 - - - - True - - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - 2 - 2 - False - 6 - 6 - - - - True - _Login method: - True - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - 1 - 0 - 1 - fill - - - - - - - True - Lo_gin: - True - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - auth-entry - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - 1 - 1 - 2 - fill - - - - - - - True - Evolution will use this email address to authenticate you with the server. - True - True - True - 0 - - True - * - False - - - 1 - 2 - 1 - 2 - - - - - - - True - Anonymously -Using email address -Using distinguished name (DN) - False - True - - - 1 - 2 - 0 - 1 - shrink|fill - shrink|fill - - - - - 0 - True - True - - - - - 0 - True - True - - - - - 0 - False - False - - - - - False - False - - - - - - True - General - False - False - GTK_JUSTIFY_CENTER - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - tab - - - - - - 12 - False - 12 - - - - True - <b>Searching</b> - False - True - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - False - 12 - - - - True - - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - 4 - 3 - False - 6 - 6 - - - - True - - False - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - 1 - 1 - 2 - fill - - - - - - - True - Search _base: - True - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - rootdn-entry - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - 1 - 0 - 1 - expand|shrink|fill - shrink|fill - - - - - - True - _Search scope: - True - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - 1 - 2 - 3 - expand|shrink|fill - shrink|fill - - - - - - True - The search base is the distinguished name (DN) of the entry where your searches will begin. If you leave this blank, the search will begin at the root of the directory tree. - True - True - True - True - 0 - - True - * - False - - - 1 - 3 - 0 - 1 - expand|shrink|fill - shrink|fill - - - - - - True - True - GTK_RELIEF_NORMAL - True - - - - True - 0.5 - 0.5 - 0 - 0 - 0 - 0 - 0 - 0 - - - - True - False - 2 - - - - True - gtk-find - 4 - 0.5 - 0.5 - 0 - 0 - - - 0 - False - False - - - - - - True - _Find Possible Search Bases - True - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - - - - 1 - 2 - 1 - 2 - expand|shrink|fill - shrink|fill - - - - - - True - Search _filter: - True - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - search-filter-entry - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - 1 - 3 - 4 - expand|shrink|fill - shrink|fill - - - - - - True - True - True - True - 0 - - True - * - False - - Search Filter - Search filter is the type of object to be searched for. If this is not modified, the default search will be performed on the type "person". - - - - 1 - 3 - 3 - 4 - expand|shrink|fill - shrink|fill - - - - - - True - One -Sub - False - True - - - 1 - 3 - 2 - 3 - shrink|fill - shrink|fill - - - - - 0 - True - True - - - - - 0 - False - False - - - - - - True - <b>Downloading</b> - False - True - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - False - 12 - - - - True - - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - 3 - 3 - False - 6 - 6 - - - - True - False - 6 - - - - True - 1 - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - True - False - GTK_POS_TOP - 1 - GTK_UPDATE_CONTINUOUS - False - 3 1 5 0.5 1 0 - - - 0 - True - True - - - - - - True - 5 - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - 1 - 2 - 0 - 1 - expand|shrink|fill - shrink|fill - - - - - - True - minutes - False - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 2 - 3 - 0 - 1 - shrink|fill - shrink|fill - - - - - - True - cards - False - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 2 - 3 - 1 - 2 - shrink|fill - shrink|fill - - - - - - True - _Timeout: - True - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - timeout-scale - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - 1 - 0 - 1 - shrink|fill - shrink|fill - - - - - - True - _Download limit: - True - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - download-limit-spinbutton - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - 1 - 1 - 2 - shrink|fill - shrink|fill - - - - - - True - This is the maximum number of entries to download. Setting this number to be too large will slow down your address book. - True - 1 - 0 - False - GTK_UPDATE_ALWAYS - False - False - 0 0 1000 1 10 0 - - - 1 - 2 - 1 - 2 - expand|shrink|fill - shrink|fill - - - - - - True - True - B_rowse this book until limit reached - True - GTK_RELIEF_NORMAL - True - False - False - True - - - 0 - 3 - 2 - 3 - fill - - - - - - 0 - True - True - - - - - 0 - False - False - - - - - False - False - - - - - - True - Details - False - False - GTK_JUSTIFY_CENTER - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - tab - - - - - 0 - True - True - - - - - - - - Supported Search Bases - GTK_WINDOW_TOPLEVEL - GTK_WIN_POS_CENTER - False - 320 - 200 - True - False - True - False - False - GDK_WINDOW_TYPE_HINT_DIALOG - GDK_GRAVITY_NORTH_WEST - True - False - False - - - - True - False - 0 - - - - True - GTK_BUTTONBOX_END - - - - True - True - True - gtk-cancel - True - GTK_RELIEF_NORMAL - True - -6 - - - - - - True - True - True - gtk-ok - True - GTK_RELIEF_NORMAL - True - -5 - - - - - 0 - False - True - GTK_PACK_END - - - - - - 12 - True - False - 0 - - - - True - supported_bases_create_table - 0 - 0 - Fri, 12 Apr 2002 20:06:45 GMT - - - 0 - True - True - - - - - 0 - True - True - - - - - - - diff --git a/addressbook/gui/component/openldap-extract.h b/addressbook/gui/component/openldap-extract.h deleted file mode 100644 index 996bf370a8..0000000000 --- a/addressbook/gui/component/openldap-extract.h +++ /dev/null @@ -1,1427 +0,0 @@ -/* This is extracted from the OpenLDAP sources. - * - * Stuff that isn't used in e-book-backend-ldap.c was dropped, like - * the LDAPSchemaExtensionItem stuff. - * - * This file basically has three parts: - * - * - some general macros from OpenLDAP that work as such on all - * implementations. - * - * - ldap_str2objectclass() - * - * - ldap_url_parse() - */ - -/* This work is part of OpenLDAP Software . - * - * Copyright 1998-2005 The OpenLDAP Foundation. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in file COPYING.OPENLDAP in - * the top-level directory of the distribution or, alternatively, at - * . - */ - -#include -#include - -/* from various header files */ - -#define LDAP_CONST const - -#define LDAP_PORT 389 /* ldap:/// default LDAP port */ -#define LDAPS_PORT 636 /* ldaps:/// default LDAP over TLS port */ - -#define LDAP_ROOT_DSE "" - -#define LDAP_SPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') -#define LDAP_DIGIT(c) ((c) >= '0' && (c) <= '9') - -#define LDAP_EXOP_START_TLS "1.3.6.1.4.1.1466.20037" /* RFC 2830 */ - -#define LDAP_MALLOC(n) malloc((n)) -#define LDAP_CALLOC(n,s) calloc((n),(s)) -#define LDAP_REALLOC(p,s) realloc((p),(s)) -#define LDAP_FREE(p) free((p)) -#define LDAP_VFREE(p) vfree((gpointer *)(p)) -#define LDAP_STRDUP(s) strdup((s)) - -#define LDAP_RANGE(n,x,y) (((x) <= (n)) && ((n) <= (y))) -#define LDAP_NAME_ERROR(n) LDAP_RANGE((n),0x20,0x24) /* 32-34,36 */ - -#define ldap_msgtype(lm) (lm)->lm_msgtype -#define ldap_msgid(lm) (lm)->lm_msgid - -#define LDAP_SCHERR_OUTOFMEM 1 -#define LDAP_SCHERR_UNEXPTOKEN 2 -#define LDAP_SCHERR_NOLEFTPAREN 3 -#define LDAP_SCHERR_NORIGHTPAREN 4 -#define LDAP_SCHERR_NODIGIT 5 -#define LDAP_SCHERR_BADNAME 6 -#define LDAP_SCHERR_BADDESC 7 -#define LDAP_SCHERR_BADSUP 8 -#define LDAP_SCHERR_DUPOPT 9 -#define LDAP_SCHERR_EMPTY 10 -#define LDAP_SCHERR_MISSING 11 -#define LDAP_SCHERR_OUT_OF_ORDER 12 - -#define LDAP_SCHEMA_YES 1 - -#define LDAP_SCHEMA_ABSTRACT 0 -#define LDAP_SCHEMA_STRUCTURAL 1 -#define LDAP_SCHEMA_AUXILIARY 2 - -#define LDAP_SCHEMA_ALLOW_NONE 0x00U /* Strict parsing */ -#define LDAP_SCHEMA_ALLOW_NO_OID 0x01U /* Allow missing oid */ -#define LDAP_SCHEMA_ALLOW_QUOTED 0x02U /* Allow bogus extra quotes */ -#define LDAP_SCHEMA_ALLOW_DESCR 0x04U /* Allow descr instead of OID */ -#define LDAP_SCHEMA_ALLOW_DESCR_PREFIX 0x08U /* Allow descr as OID prefix */ -#define LDAP_SCHEMA_ALLOW_OID_MACRO 0x10U /* Allow OID macros in slapd */ -#define LDAP_SCHEMA_ALLOW_OUT_OF_ORDER_FIELDS 0x20U /* Allow fields in most any order */ -#define LDAP_SCHEMA_ALLOW_ALL 0x3fU /* Be very liberal in parsing */ -#define LDAP_SCHEMA_SKIP 0x80U /* Don't malloc any result */ - -typedef struct ldap_objectclass { - gchar *oc_oid; /* REQUIRED */ - gchar **oc_names; /* OPTIONAL */ - gchar *oc_desc; /* OPTIONAL */ - gint oc_obsolete; /* 0=no, 1=yes */ - gchar **oc_sup_oids; /* OPTIONAL */ - gint oc_kind; /* 0=ABSTRACT, 1=STRUCTURAL, 2=AUXILIARY */ - gchar **oc_at_oids_must; /* OPTIONAL */ - gchar **oc_at_oids_may; /* OPTIONAL */ -} LDAPObjectClass; - - -static void -vfree(gpointer *vec) -{ - gint i; - - for (i = 0; vec[i] != NULL; i++) - free(vec[i]); -} - -/* from schema.c */ - -/* - * Now come the parsers. There is one parser for each entity type: - * objectclasses, attributetypes, etc. - * - * Each of them is written as a recursive-descent parser, except that - * none of them is really recursive. But the idea is kept: there - * is one routine per non-terminal that eithers gobbles lexical tokens - * or calls lower-level routines, etc. - * - * The scanner is implemented in the routine get_token. Actually, - * get_token is more than a scanner and will return tokens that are - * in fact non-terminals in the grammar. So you can see the whole - * approach as the combination of a low-level bottom-up recognizer - * combined with a scanner and a number of top-down parsers. Or just - * consider that the real grammars recognized by the parsers are not - * those of the standards. As a matter of fact, our parsers are more - * liberal than the spec when there is no ambiguity. - * - * The difference is pretty academic (modulo bugs or incorrect - * interpretation of the specs). - */ - -#define TK_NOENDQUOTE -2 -#define TK_OUTOFMEM -1 -#define TK_EOS 0 -#define TK_UNEXPCHAR 1 -#define TK_BAREWORD 2 -#define TK_QDSTRING 3 -#define TK_LEFTPAREN 4 -#define TK_RIGHTPAREN 5 -#define TK_DOLLAR 6 -#define TK_QDESCR TK_QDSTRING - -struct token { - gint type; - gchar *sval; -}; - -static gint -get_token( const gchar ** sp, gchar ** token_val ) -{ - gint kind; - const gchar * p; - const gchar * q; - gchar * res; - - *token_val = NULL; - switch (**sp) { - case '\0': - kind = TK_EOS; - (*sp)++; - break; - case '(': - kind = TK_LEFTPAREN; - (*sp)++; - break; - case ')': - kind = TK_RIGHTPAREN; - (*sp)++; - break; - case '$': - kind = TK_DOLLAR; - (*sp)++; - break; - case '\'': - kind = TK_QDSTRING; - (*sp)++; - p = *sp; - while ( **sp != '\'' && **sp != '\0' ) - (*sp)++; - if ( **sp == '\'' ) { - q = *sp; - res = LDAP_MALLOC(q-p+1); - if ( !res ) { - kind = TK_OUTOFMEM; - } else { - strncpy(res,p,q-p); - res[q-p] = '\0'; - *token_val = res; - } - (*sp)++; - } else { - kind = TK_NOENDQUOTE; - } - break; - default: - kind = TK_BAREWORD; - p = *sp; - while ( !LDAP_SPACE(**sp) && - **sp != '(' && - **sp != ')' && - **sp != '$' && - **sp != '\'' && - **sp != '\0' ) - (*sp)++; - q = *sp; - res = LDAP_MALLOC(q-p+1); - if ( !res ) { - kind = TK_OUTOFMEM; - } else { - strncpy(res,p,q-p); - res[q-p] = '\0'; - *token_val = res; - } - break; -/* kind = TK_UNEXPCHAR; */ -/* break; */ - } - - return kind; -} - -/* Gobble optional whitespace */ -static void -parse_whsp(const gchar **sp) -{ - while (LDAP_SPACE(**sp)) - (*sp)++; -} - -/* Parse a sequence of dot-separated decimal strings */ -static gchar * -ldap_int_parse_numericoid(const gchar **sp, gint *code, const gint flags) -{ - gchar * res = NULL; - const gchar * start = *sp; - gint len; - gint quoted = 0; - - /* Netscape puts the SYNTAX value in quotes (incorrectly) */ - if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && **sp == '\'' ) { - quoted = 1; - (*sp)++; - start++; - } - /* Each iteration of this loop gets one decimal string */ - while (**sp) { - if ( !LDAP_DIGIT(**sp) ) { - /* - * Initial gchar is not a digit or gchar after dot is - * not a digit - */ - *code = LDAP_SCHERR_NODIGIT; - return NULL; - } - (*sp)++; - while ( LDAP_DIGIT(**sp) ) - (*sp)++; - if ( **sp != '.' ) - break; - /* Otherwise, gobble the dot and loop again */ - (*sp)++; - } - /* Now *sp points at the gchar past the numericoid. Perfect. */ - len = *sp - start; - if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && quoted ) { - if ( **sp == '\'' ) { - (*sp)++; - } else { - *code = LDAP_SCHERR_UNEXPTOKEN; - return NULL; - } - } - if (flags & LDAP_SCHEMA_SKIP) { - res = (gchar *)start; - } else { - res = LDAP_MALLOC(len+1); - if (!res) { - *code = LDAP_SCHERR_OUTOFMEM; - return(NULL); - } - strncpy(res,start,len); - res[len] = '\0'; - } - return(res); -} - -/* Parse a qdescr or a list of them enclosed in () */ -static gchar ** -parse_qdescrs(const gchar **sp, gint *code) -{ - gchar ** res; - gchar ** res1; - gint kind; - gchar * sval; - gint size; - gint pos; - - parse_whsp(sp); - kind = get_token(sp,&sval); - if ( kind == TK_LEFTPAREN ) { - /* Let's presume there will be at least 2 entries */ - size = 3; - res = LDAP_CALLOC(3,sizeof(gchar *)); - if ( !res ) { - *code = LDAP_SCHERR_OUTOFMEM; - return NULL; - } - pos = 0; - while (1) { - parse_whsp(sp); - kind = get_token(sp,&sval); - if ( kind == TK_RIGHTPAREN ) - break; - if ( kind == TK_QDESCR ) { - if ( pos == size-2 ) { - size++; - res1 = LDAP_REALLOC(res,size*sizeof(gchar *)); - if ( !res1 ) { - LDAP_VFREE(res); - LDAP_FREE(sval); - *code = LDAP_SCHERR_OUTOFMEM; - return(NULL); - } - res = res1; - } - res[pos++] = sval; - res[pos] = NULL; - parse_whsp(sp); - } else { - LDAP_VFREE(res); - LDAP_FREE(sval); - *code = LDAP_SCHERR_UNEXPTOKEN; - return(NULL); - } - } - parse_whsp(sp); - return(res); - } else if ( kind == TK_QDESCR ) { - res = LDAP_CALLOC(2,sizeof(gchar *)); - if ( !res ) { - *code = LDAP_SCHERR_OUTOFMEM; - return NULL; - } - res[0] = sval; - res[1] = NULL; - parse_whsp(sp); - return res; - } else { - LDAP_FREE(sval); - *code = LDAP_SCHERR_BADNAME; - return NULL; - } -} - -/* Parse a woid or a $-separated list of them enclosed in () */ -static gchar ** -parse_oids(const gchar **sp, gint *code, const gint allow_quoted) -{ - gchar ** res; - gchar ** res1; - gint kind; - gchar * sval; - gint size; - gint pos; - - /* - * Strictly speaking, doing this here accepts whsp before the - * ( at the begining of an oidlist, but this is harmless. Also, - * we are very liberal in what we accept as an OID. Maybe - * refine later. - */ - parse_whsp(sp); - kind = get_token(sp,&sval); - if ( kind == TK_LEFTPAREN ) { - /* Let's presume there will be at least 2 entries */ - size = 3; - res = LDAP_CALLOC(3,sizeof(gchar *)); - if ( !res ) { - *code = LDAP_SCHERR_OUTOFMEM; - return NULL; - } - pos = 0; - parse_whsp(sp); - kind = get_token(sp,&sval); - if ( kind == TK_BAREWORD || - ( allow_quoted && kind == TK_QDSTRING ) ) { - res[pos++] = sval; - res[pos] = NULL; - } else { - *code = LDAP_SCHERR_UNEXPTOKEN; - LDAP_FREE(sval); - LDAP_VFREE(res); - return NULL; - } - parse_whsp(sp); - while (1) { - kind = get_token(sp,&sval); - if ( kind == TK_RIGHTPAREN ) - break; - if ( kind == TK_DOLLAR ) { - parse_whsp(sp); - kind = get_token(sp,&sval); - if ( kind == TK_BAREWORD || - ( allow_quoted && - kind == TK_QDSTRING ) ) { - if ( pos == size-2 ) { - size++; - res1 = LDAP_REALLOC(res,size*sizeof(gchar *)); - if ( !res1 ) { - LDAP_FREE(sval); - LDAP_VFREE(res); - *code = LDAP_SCHERR_OUTOFMEM; - return(NULL); - } - res = res1; - } - res[pos++] = sval; - res[pos] = NULL; - } else { - *code = LDAP_SCHERR_UNEXPTOKEN; - LDAP_FREE(sval); - LDAP_VFREE(res); - return NULL; - } - parse_whsp(sp); - } else { - *code = LDAP_SCHERR_UNEXPTOKEN; - LDAP_FREE(sval); - LDAP_VFREE(res); - return NULL; - } - } - parse_whsp(sp); - return(res); - } else if ( kind == TK_BAREWORD || - ( allow_quoted && kind == TK_QDSTRING ) ) { - res = LDAP_CALLOC(2,sizeof(gchar *)); - if ( !res ) { - LDAP_FREE(sval); - *code = LDAP_SCHERR_OUTOFMEM; - return NULL; - } - res[0] = sval; - res[1] = NULL; - parse_whsp(sp); - return res; - } else { - LDAP_FREE(sval); - *code = LDAP_SCHERR_BADNAME; - return NULL; - } -} - -static void -ldap_objectclass_free(LDAPObjectClass * oc) -{ - LDAP_FREE(oc->oc_oid); - if (oc->oc_names) LDAP_VFREE(oc->oc_names); - if (oc->oc_desc) LDAP_FREE(oc->oc_desc); - if (oc->oc_sup_oids) LDAP_VFREE(oc->oc_sup_oids); - if (oc->oc_at_oids_must) LDAP_VFREE(oc->oc_at_oids_must); - if (oc->oc_at_oids_may) LDAP_VFREE(oc->oc_at_oids_may); - LDAP_FREE(oc); -} - -static LDAPObjectClass * -ldap_str2objectclass( LDAP_CONST gchar * s, - gint * code, - LDAP_CONST gchar ** errp, - LDAP_CONST unsigned flags ) -{ - gint kind; - const gchar * ss = s; - gchar * sval; - gint seen_name = 0; - gint seen_desc = 0; - gint seen_obsolete = 0; - gint seen_sup = 0; - gint seen_kind = 0; - gint seen_must = 0; - gint seen_may = 0; - LDAPObjectClass * oc; - gchar ** ext_vals; - const gchar * savepos; - - if ( !s ) { - *code = LDAP_SCHERR_EMPTY; - *errp = ""; - return NULL; - } - - *errp = s; - oc = LDAP_CALLOC(1,sizeof(LDAPObjectClass)); - - if ( !oc ) { - *code = LDAP_SCHERR_OUTOFMEM; - return NULL; - } - oc->oc_kind = LDAP_SCHEMA_STRUCTURAL; - - kind = get_token(&ss,&sval); - if ( kind != TK_LEFTPAREN ) { - *code = LDAP_SCHERR_NOLEFTPAREN; - LDAP_FREE(sval); - ldap_objectclass_free(oc); - return NULL; - } - - /* - * Definitions MUST begin with an OID in the numericoid format. - * However, this routine is used by clients to parse the response - * from servers and very well known servers will provide an OID - * in the wrong format or even no OID at all. We do our best to - * extract info from those servers. - */ - parse_whsp(&ss); - savepos = ss; - oc->oc_oid = ldap_int_parse_numericoid(&ss,code,0); - if ( !oc->oc_oid ) { - if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) { - /* Backtracking */ - ss = savepos; - kind = get_token(&ss,&sval); - if ( kind == TK_BAREWORD ) { - if ( !strcasecmp(sval, "NAME") || - !strcasecmp(sval, "DESC") || - !strcasecmp(sval, "OBSOLETE") || - !strcasecmp(sval, "SUP") || - !strcasecmp(sval, "ABSTRACT") || - !strcasecmp(sval, "STRUCTURAL") || - !strcasecmp(sval, "AUXILIARY") || - !strcasecmp(sval, "MUST") || - !strcasecmp(sval, "MAY") || - !strncasecmp(sval, "X-", 2) ) { - /* Missing OID, backtrack */ - ss = savepos; - } else if ( flags & - LDAP_SCHEMA_ALLOW_OID_MACRO ) { - /* Non-numerical OID, ignore */ - gint len = ss-savepos; - oc->oc_oid = LDAP_MALLOC(len+1); - strncpy(oc->oc_oid, savepos, len); - oc->oc_oid[len] = 0; - } - } - LDAP_FREE(sval); - } else { - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - } - } - parse_whsp(&ss); - - /* - * Beyond this point we will be liberal an accept the items - * in any order. - */ - while (1) { - kind = get_token(&ss,&sval); - switch (kind) { - case TK_EOS: - *code = LDAP_SCHERR_NORIGHTPAREN; - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - case TK_RIGHTPAREN: - return oc; - case TK_BAREWORD: - if ( !strcasecmp(sval,"NAME") ) { - LDAP_FREE(sval); - if ( seen_name ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_name = 1; - oc->oc_names = parse_qdescrs(&ss,code); - if ( !oc->oc_names ) { - if ( *code != LDAP_SCHERR_OUTOFMEM ) - *code = LDAP_SCHERR_BADNAME; - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - } - } else if ( !strcasecmp(sval,"DESC") ) { - LDAP_FREE(sval); - if ( seen_desc ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_desc = 1; - parse_whsp(&ss); - kind = get_token(&ss,&sval); - if ( kind != TK_QDSTRING ) { - *code = LDAP_SCHERR_UNEXPTOKEN; - *errp = ss; - LDAP_FREE(sval); - ldap_objectclass_free(oc); - return NULL; - } - oc->oc_desc = sval; - parse_whsp(&ss); - } else if ( !strcasecmp(sval,"OBSOLETE") ) { - LDAP_FREE(sval); - if ( seen_obsolete ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_obsolete = 1; - oc->oc_obsolete = LDAP_SCHEMA_YES; - parse_whsp(&ss); - } else if ( !strcasecmp(sval,"SUP") ) { - LDAP_FREE(sval); - if ( seen_sup ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_sup = 1; - oc->oc_sup_oids = parse_oids(&ss, - code, - flags); - if ( !oc->oc_sup_oids ) { - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - } - } else if ( !strcasecmp(sval,"ABSTRACT") ) { - LDAP_FREE(sval); - if ( seen_kind ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_kind = 1; - oc->oc_kind = LDAP_SCHEMA_ABSTRACT; - parse_whsp(&ss); - } else if ( !strcasecmp(sval,"STRUCTURAL") ) { - LDAP_FREE(sval); - if ( seen_kind ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_kind = 1; - oc->oc_kind = LDAP_SCHEMA_STRUCTURAL; - parse_whsp(&ss); - } else if ( !strcasecmp(sval,"AUXILIARY") ) { - LDAP_FREE(sval); - if ( seen_kind ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_kind = 1; - oc->oc_kind = LDAP_SCHEMA_AUXILIARY; - parse_whsp(&ss); - } else if ( !strcasecmp(sval,"MUST") ) { - LDAP_FREE(sval); - if ( seen_must ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_must = 1; - oc->oc_at_oids_must = parse_oids(&ss,code,0); - if ( !oc->oc_at_oids_must ) { - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - } - parse_whsp(&ss); - } else if ( !strcasecmp(sval,"MAY") ) { - LDAP_FREE(sval); - if ( seen_may ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_may = 1; - oc->oc_at_oids_may = parse_oids(&ss,code,0); - if ( !oc->oc_at_oids_may ) { - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - } - parse_whsp(&ss); - } else if ( sval[0] == 'X' && sval[1] == '-' ) { - /* Should be parse_qdstrings */ - ext_vals = parse_qdescrs(&ss, code); - if ( !ext_vals ) { - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - } -#if 0 - if ( add_extension(&oc->oc_extensions, - sval, ext_vals) ) { - *code = LDAP_SCHERR_OUTOFMEM; - *errp = ss; - LDAP_FREE(sval); - ldap_objectclass_free(oc); - return NULL; - } -#endif - } else { - *code = LDAP_SCHERR_UNEXPTOKEN; - *errp = ss; - LDAP_FREE(sval); - ldap_objectclass_free(oc); - return NULL; - } - break; - default: - *code = LDAP_SCHERR_UNEXPTOKEN; - *errp = ss; - LDAP_FREE(sval); - ldap_objectclass_free(oc); - return NULL; - } - } -} - -/* from utf-8.c */ - -#define LDAP_UTF8_NEXT(p) g_utf8_next_char((p)) -#define LDAP_UTF8_INCR(p) ((p)=LDAP_UTF8_NEXT((p))) -#define ldap_x_utf8_to_ucs4(str) g_utf8_get_char(str) - -static gchar *ldap_utf8_strchr( const gchar *str, const gchar *chr ) -{ - for(; *str != '\0'; LDAP_UTF8_INCR(str) ) { - if( ldap_x_utf8_to_ucs4( str ) == ldap_x_utf8_to_ucs4( chr ) ) { - return (gchar *) str; - } - } - - return NULL; -} - -static gsize ldap_utf8_strcspn( const gchar *str, const gchar *set ) -{ - const gchar *cstr; - const gchar *cset; - - for( cstr = str; *cstr != '\0'; LDAP_UTF8_INCR(cstr) ) { - for( cset = set; *cset != '\0'; LDAP_UTF8_INCR(cset) ) { - if( ldap_x_utf8_to_ucs4( cstr ) == ldap_x_utf8_to_ucs4( cset ) ) { - return cstr - str; - } - } - } - - return cstr - str; -} - -static gsize ldap_utf8_strspn( const gchar *str, const gchar *set ) -{ - const gchar *cstr; - const gchar *cset; - - for( cstr = str; *cstr != '\0'; LDAP_UTF8_INCR(cstr) ) { - for( cset = set; ; LDAP_UTF8_INCR(cset) ) { - if( *cset == '\0' ) { - return cstr - str; - } - - if( ldap_x_utf8_to_ucs4( cstr ) == ldap_x_utf8_to_ucs4( cset ) ) { - break; - } - } - } - - return cstr - str; -} - -static gchar *ldap_utf8_strtok(gchar *str, const gchar *sep, gchar **last) -{ - gchar *begin; - gchar *end; - - if( last == NULL ) return NULL; - - begin = str ? str : *last; - - begin += ldap_utf8_strspn( begin, sep ); - - if( *begin == '\0' ) { - *last = NULL; - return NULL; - } - - end = &begin[ ldap_utf8_strcspn( begin, sep ) ]; - - if( *end != '\0' ) { - gchar *next = LDAP_UTF8_NEXT( end ); - *end = '\0'; - end = next; - } - - *last = end; - return begin; -} - -/* from ldap.h */ - -#define LDAP_URL_SUCCESS 0x00 /* Success */ -#define LDAP_URL_ERR_MEM 0x01 /* can't allocate memory space */ -#define LDAP_URL_ERR_PARAM 0x02 /* parameter is bad */ - -#define LDAP_URL_ERR_BADSCHEME 0x03 /* URL doesn't begin with "ldap[si]://" */ -#define LDAP_URL_ERR_BADENCLOSURE 0x04 /* URL is missing trailing ">" */ -#define LDAP_URL_ERR_BADURL 0x05 /* URL is bad */ -#define LDAP_URL_ERR_BADHOST 0x06 /* host port is bad */ -#define LDAP_URL_ERR_BADATTRS 0x07 /* bad (or missing) attributes */ -#define LDAP_URL_ERR_BADSCOPE 0x08 /* scope string is invalid (or missing) */ -#define LDAP_URL_ERR_BADFILTER 0x09 /* bad or missing filter */ -#define LDAP_URL_ERR_BADEXTS 0x0a /* bad or missing extensions */ - -#define LDAP_URL_PREFIX "ldap://" -#define LDAP_URL_PREFIX_LEN (sizeof(LDAP_URL_PREFIX)-1) -#define LDAPS_URL_PREFIX "ldaps://" -#define LDAPS_URL_PREFIX_LEN (sizeof(LDAPS_URL_PREFIX)-1) -#define LDAPI_URL_PREFIX "ldapi://" -#define LDAPI_URL_PREFIX_LEN (sizeof(LDAPI_URL_PREFIX)-1) - -#define LDAP_URL_URLCOLON "URL:" -#define LDAP_URL_URLCOLON_LEN (sizeof(LDAP_URL_URLCOLON)-1) - -typedef struct ldap_url_desc { - struct ldap_url_desc *lud_next; - gchar *lud_scheme; - gchar *lud_host; - gint lud_port; - gchar *lud_dn; - gchar **lud_attrs; - gint lud_scope; - gchar *lud_filter; - gchar **lud_exts; - gint lud_crit_exts; -} LDAPURLDesc; - -/* from url.c */ - -static const gchar * -skip_url_prefix( - const gchar *url, - gint *enclosedp, - const gchar **scheme ) -{ - /* - * return non-zero if this looks like a LDAP URL; zero if not - * if non-zero returned, *urlp will be moved past "ldap://" part of URL - */ - const gchar *p; - - if ( url == NULL ) { - return( NULL ); - } - - p = url; - - /* skip leading '<' (if any) */ - if ( *p == '<' ) { - *enclosedp = 1; - ++p; - } else { - *enclosedp = 0; - } - - /* skip leading "URL:" (if any) */ - if ( strncasecmp( p, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) { - p += LDAP_URL_URLCOLON_LEN; - } - - /* check for "ldap://" prefix */ - if ( strncasecmp( p, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) == 0 ) { - /* skip over "ldap://" prefix and return success */ - p += LDAP_URL_PREFIX_LEN; - *scheme = "ldap"; - return( p ); - } - - /* check for "ldaps://" prefix */ - if ( strncasecmp( p, LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) { - /* skip over "ldaps://" prefix and return success */ - p += LDAPS_URL_PREFIX_LEN; - *scheme = "ldaps"; - return( p ); - } - - /* check for "ldapi://" prefix */ - if ( strncasecmp( p, LDAPI_URL_PREFIX, LDAPI_URL_PREFIX_LEN ) == 0 ) { - /* skip over "ldapi://" prefix and return success */ - p += LDAPI_URL_PREFIX_LEN; - *scheme = "ldapi"; - return( p ); - } - -#ifdef LDAP_CONNECTIONLESS - /* check for "cldap://" prefix */ - if ( strncasecmp( p, LDAPC_URL_PREFIX, LDAPC_URL_PREFIX_LEN ) == 0 ) { - /* skip over "cldap://" prefix and return success */ - p += LDAPC_URL_PREFIX_LEN; - *scheme = "cldap"; - return( p ); - } -#endif - - return( NULL ); -} - -static gint str2scope( const gchar *p ) -{ - if ( strcasecmp( p, "one" ) == 0 ) { - return LDAP_SCOPE_ONELEVEL; - - } else if ( strcasecmp( p, "onelevel" ) == 0 ) { - return LDAP_SCOPE_ONELEVEL; - - } else if ( strcasecmp( p, "base" ) == 0 ) { - return LDAP_SCOPE_BASE; - - } else if ( strcasecmp( p, "sub" ) == 0 ) { - return LDAP_SCOPE_SUBTREE; - - } else if ( strcasecmp( p, "subtree" ) == 0 ) { - return LDAP_SCOPE_SUBTREE; - } - - return( -1 ); -} - -static void -ldap_free_urldesc( LDAPURLDesc *ludp ) -{ - if ( ludp == NULL ) { - return; - } - - if ( ludp->lud_scheme != NULL ) { - LDAP_FREE( ludp->lud_scheme ); - } - - if ( ludp->lud_host != NULL ) { - LDAP_FREE( ludp->lud_host ); - } - - if ( ludp->lud_dn != NULL ) { - LDAP_FREE( ludp->lud_dn ); - } - - if ( ludp->lud_filter != NULL ) { - LDAP_FREE( ludp->lud_filter); - } - - if ( ludp->lud_attrs != NULL ) { - LDAP_VFREE( ludp->lud_attrs ); - } - - if ( ludp->lud_exts != NULL ) { - LDAP_VFREE( ludp->lud_exts ); - } - - LDAP_FREE( ludp ); -} - -static gint -ldap_int_unhex( gint c ) -{ - return( c >= '0' && c <= '9' ? c - '0' - : c >= 'A' && c <= 'F' ? c - 'A' + 10 - : c - 'a' + 10 ); -} - -static void -ldap_pvt_hex_unescape( gchar *s ) -{ - /* - * Remove URL hex escapes from s... done in place. The basic concept for - * this routine is borrowed from the WWW library HTUnEscape() routine. - */ - gchar *p; - - for ( p = s; *s != '\0'; ++s ) { - if ( *s == '%' ) { - if ( *++s == '\0' ) { - break; - } - *p = ldap_int_unhex( *s ) << 4; - if ( *++s == '\0' ) { - break; - } - *p++ += ldap_int_unhex( *s ); - } else { - *p++ = *s; - } - } - - *p = '\0'; -} - -static gchar ** -ldap_str2charray( const gchar *str_in, const gchar *brkstr ) -{ - gchar **res; - gchar *str, *s; - gchar *lasts; - gint i; - - /* protect the input string from strtok */ - str = LDAP_STRDUP( str_in ); - if( str == NULL ) { - return NULL; - } - - i = 1; - for ( s = str; *s; s++ ) { - if ( ldap_utf8_strchr( brkstr, s ) != NULL ) { - i++; - } - } - - res = (gchar **) LDAP_MALLOC( (i + 1) * sizeof(gchar *) ); - - if( res == NULL ) { - LDAP_FREE( str ); - return NULL; - } - - i = 0; - - for ( s = ldap_utf8_strtok( str, brkstr, &lasts ); - s != NULL; - s = ldap_utf8_strtok( NULL, brkstr, &lasts ) ) - { - res[i] = LDAP_STRDUP( s ); - - if(res[i] == NULL) { - for( --i; i >= 0; i-- ) { - LDAP_FREE( res[i] ); - } - LDAP_FREE( res ); - LDAP_FREE( str ); - return NULL; - } - - i++; - } - - res[i] = NULL; - - LDAP_FREE( str ); - return( res ); -} - -static gint -ldap_url_parse_ext( LDAP_CONST gchar *url_in, LDAPURLDesc **ludpp ) -{ -/* - * Pick apart the pieces of an LDAP URL. - */ - - LDAPURLDesc *ludp; - gchar *p, *q, *r; - gint i, enclosed; - const gchar *scheme = NULL; - const gchar *url_tmp; - gchar *url; - - if( url_in == NULL || ludpp == NULL ) { - return LDAP_URL_ERR_PARAM; - } - - *ludpp = NULL; /* pessimistic */ - - url_tmp = skip_url_prefix( url_in, &enclosed, &scheme ); - - if ( url_tmp == NULL ) { - return LDAP_URL_ERR_BADSCHEME; - } - - assert( scheme ); - - /* make working copy of the remainder of the URL */ - url = LDAP_STRDUP( url_tmp ); - if ( url == NULL ) { - return LDAP_URL_ERR_MEM; - } - - if ( enclosed ) { - p = &url[strlen(url)-1]; - - if( *p != '>' ) { - LDAP_FREE( url ); - return LDAP_URL_ERR_BADENCLOSURE; - } - - *p = '\0'; - } - - /* allocate return struct */ - ludp = (LDAPURLDesc *)LDAP_CALLOC( 1, sizeof( LDAPURLDesc )); - - if ( ludp == NULL ) { - LDAP_FREE( url ); - return LDAP_URL_ERR_MEM; - } - - ludp->lud_next = NULL; - ludp->lud_host = NULL; - ludp->lud_port = 0; - ludp->lud_dn = NULL; - ludp->lud_attrs = NULL; - ludp->lud_filter = NULL; - ludp->lud_scope = LDAP_SCOPE_DEFAULT; - ludp->lud_filter = NULL; - ludp->lud_exts = NULL; - - ludp->lud_scheme = LDAP_STRDUP( scheme ); - - if ( ludp->lud_scheme == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_MEM; - } - - /* scan forward for '/' that marks end of hostport and begin. of dn */ - p = strchr( url, '/' ); - - if( p != NULL ) { - /* terminate hostport; point to start of dn */ - *p++ = '\0'; - } - - /* IPv6 syntax with [ip address]:port */ - if ( *url == '[' ) { - r = strchr( url, ']' ); - if ( r == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADURL; - } - *r++ = '\0'; - q = strchr( r, ':' ); - } else { - q = strchr( url, ':' ); - } - - if ( q != NULL ) { - gchar *next; - - *q++ = '\0'; - ldap_pvt_hex_unescape( q ); - - if( *q == '\0' ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADURL; - } - - ludp->lud_port = strtol( q, &next, 10 ); - if ( next == NULL || next[0] != '\0' ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADURL; - } - } - - ldap_pvt_hex_unescape( url ); - - /* If [ip address]:port syntax, url is [ip and we skip the [ */ - ludp->lud_host = LDAP_STRDUP( url + ( *url == '[' ) ); - - if( ludp->lud_host == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_MEM; - } - - /* - * Kludge. ldap://111.222.333.444:389??cn=abc,o=company - * - * On early Novell releases, search references/referrals were returned - * in this format, i.e., the dn was kind of in the scope position, - * but the required slash is missing. The whole thing is illegal syntax, - * but we need to account for it. Fortunately it can't be confused with - * anything real. - */ - if( (p == NULL) && (q != NULL) && ((q = strchr( q, '?')) != NULL)) { - q++; - /* ? immediately followed by question */ - if( *q == '?') { - q++; - if( *q != '\0' ) { - /* parse dn part */ - ldap_pvt_hex_unescape( q ); - ludp->lud_dn = LDAP_STRDUP( q ); - } else { - ludp->lud_dn = LDAP_STRDUP( "" ); - } - - if( ludp->lud_dn == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_MEM; - } - } - } - - if( p == NULL ) { - LDAP_FREE( url ); - *ludpp = ludp; - return LDAP_URL_SUCCESS; - } - - /* scan forward for '?' that may marks end of dn */ - q = strchr( p, '?' ); - - if( q != NULL ) { - /* terminate dn part */ - *q++ = '\0'; - } - - if( *p != '\0' ) { - /* parse dn part */ - ldap_pvt_hex_unescape( p ); - ludp->lud_dn = LDAP_STRDUP( p ); - } else { - ludp->lud_dn = LDAP_STRDUP( "" ); - } - - if( ludp->lud_dn == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_MEM; - } - - if( q == NULL ) { - /* no more */ - LDAP_FREE( url ); - *ludpp = ludp; - return LDAP_URL_SUCCESS; - } - - /* scan forward for '?' that may marks end of attributes */ - p = q; - q = strchr( p, '?' ); - - if( q != NULL ) { - /* terminate attributes part */ - *q++ = '\0'; - } - - if( *p != '\0' ) { - /* parse attributes */ - ldap_pvt_hex_unescape( p ); - ludp->lud_attrs = ldap_str2charray( p, "," ); - - if( ludp->lud_attrs == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADATTRS; - } - } - - if ( q == NULL ) { - /* no more */ - LDAP_FREE( url ); - *ludpp = ludp; - return LDAP_URL_SUCCESS; - } - - /* scan forward for '?' that may marks end of scope */ - p = q; - q = strchr( p, '?' ); - - if( q != NULL ) { - /* terminate the scope part */ - *q++ = '\0'; - } - - if( *p != '\0' ) { - /* parse the scope */ - ldap_pvt_hex_unescape( p ); - ludp->lud_scope = str2scope( p ); - - if( ludp->lud_scope == -1 ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADSCOPE; - } - } - - if ( q == NULL ) { - /* no more */ - LDAP_FREE( url ); - *ludpp = ludp; - return LDAP_URL_SUCCESS; - } - - /* scan forward for '?' that may marks end of filter */ - p = q; - q = strchr( p, '?' ); - - if( q != NULL ) { - /* terminate the filter part */ - *q++ = '\0'; - } - - if( *p != '\0' ) { - /* parse the filter */ - ldap_pvt_hex_unescape( p ); - - if( ! *p ) { - /* missing filter */ - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADFILTER; - } - - LDAP_FREE( ludp->lud_filter ); - ludp->lud_filter = LDAP_STRDUP( p ); - - if( ludp->lud_filter == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_MEM; - } - } - - if ( q == NULL ) { - /* no more */ - LDAP_FREE( url ); - *ludpp = ludp; - return LDAP_URL_SUCCESS; - } - - /* scan forward for '?' that may marks end of extensions */ - p = q; - q = strchr( p, '?' ); - - if( q != NULL ) { - /* extra '?' */ - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADURL; - } - - /* parse the extensions */ - ludp->lud_exts = ldap_str2charray( p, "," ); - - if( ludp->lud_exts == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADEXTS; - } - - for( i=0; ludp->lud_exts[i] != NULL; i++ ) { - ldap_pvt_hex_unescape( ludp->lud_exts[i] ); - - if( *ludp->lud_exts[i] == '!' ) { - /* count the number of critical extensions */ - ludp->lud_crit_exts++; - } - } - - if( i == 0 ) { - /* must have 1 or more */ - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADEXTS; - } - - /* no more */ - *ludpp = ludp; - LDAP_FREE( url ); - return LDAP_URL_SUCCESS; -} - -static gint -ldap_url_parse( LDAP_CONST gchar *url_in, LDAPURLDesc **ludpp ) -{ - gint rc = ldap_url_parse_ext( url_in, ludpp ); - - if( rc != LDAP_URL_SUCCESS ) { - return rc; - } - - if ((*ludpp)->lud_scope == LDAP_SCOPE_DEFAULT) { - (*ludpp)->lud_scope = LDAP_SCOPE_BASE; - } - - if ((*ludpp)->lud_host != NULL && *(*ludpp)->lud_host == '\0') { - LDAP_FREE( (*ludpp)->lud_host ); - (*ludpp)->lud_host = NULL; - } - - if ((*ludpp)->lud_port == 0) { - if( strcmp((*ludpp)->lud_scheme, "ldap") == 0 ) { - (*ludpp)->lud_port = LDAP_PORT; -#ifdef LDAP_CONNECTIONLESS - } else if( strcmp((*ludpp)->lud_scheme, "cldap") == 0 ) { - (*ludpp)->lud_port = LDAP_PORT; -#endif - } else if( strcmp((*ludpp)->lud_scheme, "ldaps") == 0 ) { - (*ludpp)->lud_port = LDAPS_PORT; - } - } - - return rc; -} - diff --git a/addressbook/gui/widgets/Makefile.am b/addressbook/gui/widgets/Makefile.am index 45c0b0cba3..e940065833 100644 --- a/addressbook/gui/widgets/Makefile.am +++ b/addressbook/gui/widgets/Makefile.am @@ -52,14 +52,14 @@ libeabwidgets_la_SOURCES = \ gal-view-minicard.h \ gal-view-factory-minicard.c \ gal-view-factory-minicard.h \ - a11y/ea-minicard.c \ - a11y/ea-minicard.h \ - a11y/ea-minicard-view.c \ - a11y/ea-minicard-view.h \ - a11y/ea-addressbook-view.c \ - a11y/ea-addressbook-view.h \ - a11y/ea-addressbook.c \ - a11y/ea-addressbook.h + ea-minicard.c \ + ea-minicard.h \ + ea-minicard-view.c \ + ea-minicard-view.h \ + ea-addressbook-view.c \ + ea-addressbook-view.h \ + ea-addressbook.c \ + ea-addressbook.h libeabwidgets_la_LIBADD = \ $(top_builddir)/widgets/misc/libemiscwidgets.la \ diff --git a/addressbook/gui/widgets/a11y/ea-addressbook-view.c b/addressbook/gui/widgets/a11y/ea-addressbook-view.c deleted file mode 100644 index b2d7ebb171..0000000000 --- a/addressbook/gui/widgets/a11y/ea-addressbook-view.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Leon Zhang - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include - -#include -#include "ea-addressbook-view.h" - -static G_CONST_RETURN gchar * ea_ab_view_get_name (AtkObject *accessible); -static G_CONST_RETURN gchar * ea_ab_view_get_description (AtkObject *accessible); - -static void ea_ab_view_class_init (EAddressbookViewClass *class); - -static gpointer parent_class = NULL; - -GType -ea_ab_view_get_type (void) -{ - static GType type = 0; - AtkObjectFactory *factory; - GTypeQuery query; - GType derived_atk_type; - - if (!type) { - static GTypeInfo tinfo = { - sizeof (EAddressbookViewClass), - (GBaseInitFunc) NULL, /* base_init */ - (GBaseFinalizeFunc) NULL, /* base_finalize */ - (GClassInitFunc) ea_ab_view_class_init, - (GClassFinalizeFunc) NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EAddressbookView), - 0, /* n_preallocs */ - (GInstanceInitFunc) NULL, /* instance init */ - NULL /* value table */ - }; - - /* - * Figure out the size of the class and instance - * we are run-time deriving from (GailWidget, in this case) */ - - factory = atk_registry_get_factory (atk_get_default_registry (), - GTK_TYPE_EVENT_BOX); - derived_atk_type = atk_object_factory_get_accessible_type (factory); - g_type_query (derived_atk_type, &query); - - tinfo.class_size = query.class_size; - tinfo.instance_size = query.instance_size; - - type = g_type_register_static (derived_atk_type, - "EaABView", &tinfo, 0); - } - - return type; -} - -static void -ea_ab_view_class_init (EAddressbookViewClass *class) -{ - AtkObjectClass *atk_object_class; - - parent_class = g_type_class_peek_parent (class); - - atk_object_class = ATK_OBJECT_CLASS (class); - atk_object_class->get_name = ea_ab_view_get_name; - atk_object_class->get_description = ea_ab_view_get_description; -} - -static G_CONST_RETURN gchar * -ea_ab_view_get_name (AtkObject *accessible) -{ - g_return_val_if_fail (EA_IS_AB_VIEW(accessible), NULL); - if (accessible->name) - return accessible->name; - - return _("evolution address book"); -} - -static G_CONST_RETURN gchar * -ea_ab_view_get_description (AtkObject *accessible) -{ - if (accessible->description) - return accessible->description; - - return _("evolution address book"); -} - -AtkObject* -ea_ab_view_new (GObject *obj) -{ - GObject *object; - AtkObject *accessible; - - g_return_val_if_fail(obj != NULL, NULL); - g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW(obj), NULL); - - object = g_object_new (EA_TYPE_AB_VIEW, NULL); - - accessible = ATK_OBJECT (object); - atk_object_initialize (accessible, obj); - accessible->role = ATK_ROLE_CANVAS; - - return accessible; -} diff --git a/addressbook/gui/widgets/a11y/ea-addressbook-view.h b/addressbook/gui/widgets/a11y/ea-addressbook-view.h deleted file mode 100644 index 4607746337..0000000000 --- a/addressbook/gui/widgets/a11y/ea-addressbook-view.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Leon Zhang - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EA_ADDRESSBOOK_VIEW_H__ -#define __EA_ADDRESSBOOK_VIEW_H__ - -#include -#include "e-addressbook-view.h" - -G_BEGIN_DECLS - -#define EA_TYPE_AB_VIEW (ea_ab_view_get_type ()) -#define EA_AB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_AB_VIEW, EaABView)) -#define EA_AB_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_AB_VIEW, EaABViewClass)) -#define EA_IS_AB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_AB_VIEW)) -#define EA_IS_AB_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EA_TYPE_AB_VIEW)) - -typedef struct _EaABView EaABView; -typedef struct _EaABViewClass EaABViewClass; - -struct _EaABView -{ - GtkAccessible parent; -}; - - -struct _EaABViewClass -{ - GtkAccessibleClass parent_class; -}; - -GType ea_ab_view_get_type (void); -AtkObject* ea_ab_view_new(GObject *obj); - -G_END_DECLS - - -#endif /* __EA_ADDRESSBOOK_VIEW_H__ */ diff --git a/addressbook/gui/widgets/a11y/ea-addressbook.c b/addressbook/gui/widgets/a11y/ea-addressbook.c deleted file mode 100644 index 14fc4c1ca3..0000000000 --- a/addressbook/gui/widgets/a11y/ea-addressbook.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Leon Zhang - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include -#include "a11y/ea-factory.h" -#include "ea-addressbook.h" -#include "ea-minicard.h" -#include "ea-minicard-view.h" -#include "ea-addressbook-view.h" - -EA_FACTORY_GOBJECT (EA_TYPE_MINICARD, ea_minicard, ea_minicard_new) -EA_FACTORY_GOBJECT (EA_TYPE_MINICARD_VIEW, ea_minicard_view, ea_minicard_view_new) -EA_FACTORY_GOBJECT (EA_TYPE_AB_VIEW, ea_ab_view, ea_ab_view_new) - -static gboolean ea_addressbook_focus_watcher (GSignalInvocationHint *ihint, - guint n_param_values, - const GValue *param_values, - gpointer data); - -void e_minicard_a11y_init (void) -{ - EA_SET_FACTORY (e_minicard_get_type (), ea_minicard); -} - -void e_minicard_view_a11y_init (void) -{ - EA_SET_FACTORY (e_minicard_view_get_type (), ea_minicard_view); - - if (atk_get_root ()) { - g_signal_add_emission_hook (g_signal_lookup ("event", - e_minicard_get_type()), - 0, ea_addressbook_focus_watcher, - NULL, (GDestroyNotify) NULL); - } -} - -void eab_view_a11y_init (void) -{ - EA_SET_FACTORY (E_TYPE_ADDRESSBOOK_VIEW, ea_ab_view); -} - -static gboolean -ea_addressbook_focus_watcher (GSignalInvocationHint *ihint, - guint n_param_values, - const GValue *param_values, - gpointer data) -{ - GObject *object; - GdkEvent *event; - AtkObject *ea_event = NULL; - - object = g_value_get_object (param_values + 0); - event = g_value_get_boxed (param_values + 1); - - if (E_IS_MINICARD (object)) { - GnomeCanvasItem *item = GNOME_CANVAS_ITEM (object); - ea_event = atk_gobject_accessible_for_object (object); - if (event->type == GDK_FOCUS_CHANGE) { - if ((event->focus_change.in) && (E_IS_MINICARD (item->canvas->focused_item))) - atk_focus_tracker_notify (ea_event); - } - } - - return TRUE; -} diff --git a/addressbook/gui/widgets/a11y/ea-addressbook.h b/addressbook/gui/widgets/a11y/ea-addressbook.h deleted file mode 100644 index 97b691dc18..0000000000 --- a/addressbook/gui/widgets/a11y/ea-addressbook.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Leon Zhang - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -/* Evolution Accessibility -*/ - -#ifndef _EA_ADDRESSBOOK_H__ -#define _EA_ADDRESSBOOK_H__ - -void eab_view_a11y_init (void); -void e_minicard_view_a11y_init (void); -void e_minicard_a11y_init (void); - -#endif /* _EA_ADDRESSBOOK_H__ */ diff --git a/addressbook/gui/widgets/a11y/ea-minicard-view.c b/addressbook/gui/widgets/a11y/ea-minicard-view.c deleted file mode 100644 index b35f64ae5e..0000000000 --- a/addressbook/gui/widgets/a11y/ea-minicard-view.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Leon Zhang < leon.zhang@sun.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include -#include -#include -#include -#include "ea-minicard.h" -#include "ea-minicard-view.h" -#include "eab-gui-util.h" -#include "e-addressbook-view.h" - -static const gchar * action_name[] = { - N_("New Contact"), - N_("New Contact List") -}; - - -static G_CONST_RETURN gchar * ea_minicard_view_get_name (AtkObject *accessible); -static G_CONST_RETURN gchar * ea_minicard_view_get_description (AtkObject *accessible); - -static void ea_minicard_view_class_init (EaMinicardViewClass *klass); - -static gint ea_minicard_view_get_n_children (AtkObject *obj); -static AtkObject *ea_minicard_view_ref_child (AtkObject *obj, gint i); - -static AtkStateSet *ea_minicard_view_ref_state_set(AtkObject *obj); - -static void atk_selection_interface_init (AtkSelectionIface *iface); -static gboolean selection_interface_add_selection (AtkSelection *selection, - gint i); -static gboolean selection_interface_clear_selection (AtkSelection *selection); -static AtkObject* selection_interface_ref_selection (AtkSelection *selection, - gint i); -static gint selection_interface_get_selection_count (AtkSelection *selection); -static gboolean selection_interface_is_child_selected (AtkSelection *selection, - gint i); - -static void atk_action_interface_init (AtkActionIface *iface); -static gboolean atk_action_interface_do_action (AtkAction *iface, gint i); -static gint atk_action_interface_get_n_action (AtkAction *iface); -static G_CONST_RETURN gchar * atk_action_interface_get_description (AtkAction *iface, gint i); -static G_CONST_RETURN gchar * atk_action_interface_get_name (AtkAction *iface, gint i); - -static gpointer parent_class = NULL; - -GType -ea_minicard_view_get_type (void) -{ - static GType type = 0; - AtkObjectFactory *factory; - GTypeQuery query; - GType derived_atk_type; - - if (!type) { - static GTypeInfo tinfo = { - sizeof (EaMinicardViewClass), - (GBaseInitFunc) NULL, /* base_init */ - (GBaseFinalizeFunc) NULL, /* base_finalize */ - (GClassInitFunc) ea_minicard_view_class_init, - (GClassFinalizeFunc) NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EaMinicardView), - 0, /* n_preallocs */ - (GInstanceInitFunc) NULL, /* instance init */ - NULL /* value table */ - }; - - static const GInterfaceInfo atk_selection_info = { - (GInterfaceInitFunc) atk_selection_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - static const GInterfaceInfo atk_action_info = { - (GInterfaceInitFunc) atk_action_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - /* - * Figure out the size of the class and instance - * we are run-time deriving from (GailWidget, in this case) */ - - factory = atk_registry_get_factory (atk_get_default_registry (), - GNOME_TYPE_CANVAS_GROUP); - derived_atk_type = atk_object_factory_get_accessible_type (factory); - g_type_query (derived_atk_type, &query); - - tinfo.class_size = query.class_size; - tinfo.instance_size = query.instance_size; - - type = g_type_register_static (derived_atk_type, - "EaMinicardView", &tinfo, 0); - g_type_add_interface_static (type, ATK_TYPE_SELECTION, - &atk_selection_info); - g_type_add_interface_static (type, ATK_TYPE_ACTION, - &atk_action_info); - - } - - return type; -} - -static void -ea_minicard_view_class_init (EaMinicardViewClass *klass) -{ - AtkObjectClass *class = ATK_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - class->get_name = ea_minicard_view_get_name; - class->get_description = ea_minicard_view_get_description; - class->ref_state_set = ea_minicard_view_ref_state_set; - class->get_n_children = ea_minicard_view_get_n_children; - class->ref_child = ea_minicard_view_ref_child; -} - -static G_CONST_RETURN gchar * -ea_minicard_view_get_name (AtkObject *accessible) -{ - EReflow *reflow; - gchar *string; - EMinicardView *card_view; - EBook *book = NULL; - const gchar *source_name; - - g_return_val_if_fail (EA_IS_MINICARD_VIEW (accessible), NULL); - - reflow = E_REFLOW(atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible))); - - if (!reflow) - return NULL; - - /* Get the current name of minicard view*/ - card_view = E_MINICARD_VIEW (reflow); - g_object_get (card_view->adapter, "book", &book, NULL); - g_return_val_if_fail (E_IS_BOOK (book), NULL); - source_name = e_source_peek_name (e_book_get_source (book)); - if (!source_name) - source_name=""; - - string = g_strdup_printf (ngettext ("current address book folder %s has %d card", - "current address book folder %s has %d cards", - reflow->count), source_name, reflow->count); - - ATK_OBJECT_CLASS (parent_class)->set_name (accessible, string); - g_free (string); - g_object_unref(book); - return accessible->name; -} - -static G_CONST_RETURN gchar * -ea_minicard_view_get_description (AtkObject *accessible) -{ - g_return_val_if_fail (EA_IS_MINICARD_VIEW(accessible), NULL); - if (accessible->description) - return accessible->description; - - return _("evolution address book"); -} - -AtkObject* -ea_minicard_view_new (GObject *obj) -{ - GObject *object; - AtkObject *accessible; - - g_return_val_if_fail (E_IS_MINICARD_VIEW(obj), NULL); - object = g_object_new (EA_TYPE_MINICARD_VIEW, NULL); - accessible = ATK_OBJECT (object); - atk_object_initialize (accessible, obj); - accessible->role = ATK_ROLE_PANEL; - return accessible; -} - -static gint -ea_minicard_view_get_n_children (AtkObject *accessible) -{ - EReflow *reflow; - - gint child_num = 0; - - g_return_val_if_fail (EA_IS_MINICARD_VIEW (accessible), -1); - - reflow = E_REFLOW (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible))); - - if (!reflow) - return -1; - - child_num = reflow->count; - - return child_num; -} - -static AtkStateSet *ea_minicard_view_ref_state_set (AtkObject *obj) -{ - AtkStateSet *state_set = NULL; - GObject *gobj = NULL; - - state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (obj); - if( !state_set ) - state_set = atk_state_set_new (); - - gobj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (obj)); - if( !gobj ) - return state_set; - - atk_state_set_add_state (state_set, ATK_STATE_ENABLED); - atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE); - atk_state_set_add_state (state_set, ATK_STATE_SHOWING); - - return state_set; -} - -static AtkObject * -ea_minicard_view_ref_child (AtkObject *accessible, gint index) -{ - EReflow *reflow; - gint child_num; - AtkObject *atk_object = NULL; - EMinicard *card = NULL; - - g_return_val_if_fail (EA_IS_MINICARD_VIEW (accessible), NULL); - - child_num = atk_object_get_n_accessible_children (accessible); - if (child_num <= 0 || index < 0 || index >= child_num) - return NULL; - - reflow = E_REFLOW (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible))); - if (!reflow) - return NULL; - if (!reflow->items ) - return NULL; - /* a minicard */ - if (index < child_num) { - card = E_MINICARD (reflow->items[index]); - atk_object = atk_gobject_accessible_for_object (G_OBJECT (card)); - } else { - return NULL; - } - - g_object_ref (atk_object); - return atk_object; -} - -/* atkselection interface */ - -static void -atk_selection_interface_init (AtkSelectionIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->add_selection = selection_interface_add_selection; - iface->clear_selection = selection_interface_clear_selection; - iface->ref_selection = selection_interface_ref_selection; - iface->get_selection_count = selection_interface_get_selection_count; - iface->is_child_selected = selection_interface_is_child_selected; -} - -static gboolean -selection_interface_add_selection (AtkSelection *selection, gint i) -{ - AtkGObjectAccessible *atk_gobj= NULL; - EReflow *reflow = NULL; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (selection); - reflow = E_REFLOW (atk_gobject_accessible_get_object (atk_gobj)); - - if (!reflow) - return FALSE; - - selection_interface_clear_selection (selection); - e_selection_model_select_single_row (reflow->selection, i); - - return TRUE; -} - -static gboolean -selection_interface_clear_selection (AtkSelection *selection) -{ - AtkGObjectAccessible *atk_gobj = NULL; - EReflow *reflow = NULL; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (selection); - reflow = E_REFLOW(atk_gobject_accessible_get_object (atk_gobj)); - - if( !reflow ) - return FALSE; - - e_selection_model_clear (reflow->selection); - - return TRUE; -} - -static AtkObject* -selection_interface_ref_selection (AtkSelection *selection, gint i) -{ - return ea_minicard_view_ref_child (ATK_OBJECT (selection), i); -} - -static gint -selection_interface_get_selection_count (AtkSelection *selection) -{ - AtkGObjectAccessible *atk_gobj = NULL; - EReflow *reflow = NULL; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (selection); - reflow = E_REFLOW (atk_gobject_accessible_get_object (atk_gobj)); - - if (!reflow ) - return FALSE; - - return e_selection_model_selected_count (reflow->selection); -} - -static gboolean -selection_interface_is_child_selected (AtkSelection *selection, gint i) -{ - AtkGObjectAccessible *atk_gobj = NULL; - EReflow *reflow = NULL; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (selection); - reflow = E_REFLOW(atk_gobject_accessible_get_object (atk_gobj)); - - if( !reflow ) - return FALSE; - - return e_selection_model_is_row_selected (reflow->selection, i); -} - -static void atk_action_interface_init (AtkActionIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->do_action = atk_action_interface_do_action; - iface->get_n_actions = atk_action_interface_get_n_action; - iface->get_description = atk_action_interface_get_description; - iface->get_name = atk_action_interface_get_name; -} - -static gboolean atk_action_interface_do_action (AtkAction *action, gint i) -{ - gboolean return_value = TRUE; - EMinicardView *card_view; - - AtkGObjectAccessible *atk_gobj= NULL; - EReflow *reflow = NULL; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (action); - reflow = E_REFLOW (atk_gobject_accessible_get_object (atk_gobj)); - - if (reflow == NULL) - return FALSE; - - card_view = E_MINICARD_VIEW (reflow); - - switch (i) { - case 0: - /* New Contact */ - e_minicard_view_create_contact (card_view); - break; - case 1: - /* New Contact List */ - e_minicard_view_create_contact_list (card_view); - break; - default: - return_value = FALSE; - break; - } - - return return_value; -} - -static gint atk_action_interface_get_n_action (AtkAction *iface) -{ - return G_N_ELEMENTS (action_name); -} - -static G_CONST_RETURN gchar * -atk_action_interface_get_description (AtkAction *iface, gint i) -{ - return atk_action_interface_get_name (iface, i); -} - -static G_CONST_RETURN gchar * -atk_action_interface_get_name (AtkAction *iface, gint i) -{ - if( i >= G_N_ELEMENTS (action_name) || i < 0) - return NULL; - - return action_name[i]; -} - diff --git a/addressbook/gui/widgets/a11y/ea-minicard-view.h b/addressbook/gui/widgets/a11y/ea-minicard-view.h deleted file mode 100644 index c564dac8c8..0000000000 --- a/addressbook/gui/widgets/a11y/ea-minicard-view.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Leon Zhang - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EA_MINICARD_VIEW_H__ -#define __EA_MINICARD_VIEW_H__ - -#include -#include "e-minicard-view.h" - -G_BEGIN_DECLS - -#define EA_TYPE_MINICARD_VIEW (ea_minicard_view_get_type ()) -#define EA_MINICARD_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_MINICARD_VIEW, EaMinicardView)) -#define EA_MINICARD_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_MINICARD_VIEW, EaMiniCardViewClass)) -#define EA_IS_MINICARD_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_MINICARD_VIEW)) -#define EA_IS_MINICARD_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EA_TYPE_MINICARD_VIEW)) - - -typedef struct _EaMinicardView EaMinicardView; -typedef struct _EaMinicardViewClass EaMinicardViewClass; - -struct _EaMinicardView -{ - AtkGObjectAccessible parent; -}; - - -struct _EaMinicardViewClass -{ - AtkGObjectAccessibleClass parent_class; -}; - -GType ea_minicard_view_get_type (void); - -AtkObject* ea_minicard_view_new(GObject *obj); - -G_END_DECLS - - -#endif /* __EA_MINICARD_VIEW_H__ */ diff --git a/addressbook/gui/widgets/a11y/ea-minicard.c b/addressbook/gui/widgets/a11y/ea-minicard.c deleted file mode 100644 index b1b1ebbe33..0000000000 --- a/addressbook/gui/widgets/a11y/ea-minicard.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Leon Zhang - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include -#include -#include -#include "ea-minicard.h" -#include "ea-minicard-view.h" -#include "e-minicard.h" - -static const gchar * action_name[] = { - N_("Open") -}; - -static G_CONST_RETURN gchar * ea_minicard_get_name (AtkObject *accessible); -static G_CONST_RETURN gchar * ea_minicard_get_description (AtkObject *accessible); - -static void ea_minicard_class_init (EaMinicardClass *klass); - -static gint ea_minicard_get_n_children (AtkObject *obj); -static AtkObject* ea_minicard_ref_child(AtkObject *obj, gint i); - -static AtkStateSet *ea_minicard_ref_state_set (AtkObject *obj); - -static void atk_action_interface_init (AtkActionIface *iface); -static gboolean atk_action_interface_do_action (AtkAction *iface, gint i); -static gint atk_action_interface_get_n_action (AtkAction *iface); -static G_CONST_RETURN gchar * atk_action_interface_get_description (AtkAction *iface, gint i); -static G_CONST_RETURN gchar * atk_action_interface_get_name (AtkAction *iface, gint i); - -static gpointer parent_class = NULL; - -GType -ea_minicard_get_type (void) -{ - static GType type = 0; - AtkObjectFactory *factory; - GTypeQuery query; - GType derived_atk_type; - - if (!type) { - static GTypeInfo tinfo = { - sizeof (EaMinicardClass), - (GBaseInitFunc) NULL, /* base_init */ - (GBaseFinalizeFunc) NULL, /* base_finalize */ - (GClassInitFunc) ea_minicard_class_init, - (GClassFinalizeFunc) NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EaMinicard), - 0, /* n_preallocs */ - (GInstanceInitFunc) NULL, /* instance init */ - NULL /* value table */ - }; - - static const GInterfaceInfo atk_action_info = { - (GInterfaceInitFunc) atk_action_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - /* - * Figure out the size of the class and instance - * we are run-time deriving from (GailWidget, in this case) - */ - - factory = atk_registry_get_factory (atk_get_default_registry (), - GNOME_TYPE_CANVAS_GROUP); - derived_atk_type = atk_object_factory_get_accessible_type (factory); - g_type_query (derived_atk_type, &query); - - tinfo.class_size = query.class_size; - tinfo.instance_size = query.instance_size; - - type = g_type_register_static ( derived_atk_type, - "EaMinicard", &tinfo, 0); - g_type_add_interface_static (type, ATK_TYPE_ACTION, - &atk_action_info); - } - - return type; -} - -static void -ea_minicard_class_init (EaMinicardClass *klass) -{ - AtkObjectClass *class = ATK_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - class->get_name = ea_minicard_get_name; - class->get_description = ea_minicard_get_description; - class->ref_state_set = ea_minicard_ref_state_set; - class->get_n_children = ea_minicard_get_n_children; - class->ref_child = ea_minicard_ref_child; -} - -/* - * we access the main content of current minicard, including - * header text, label(field, field name) - */ -static G_CONST_RETURN gchar * -ea_minicard_get_name (AtkObject *accessible) -{ -#define BUFFERSIZE 500 - - static gchar name[BUFFERSIZE]; - GString *new_str = g_string_new (NULL); - gchar *string; - EMinicard *card; - - g_return_val_if_fail (EA_IS_MINICARD(accessible), NULL); - memset (name, '\0', BUFFERSIZE); - - card = E_MINICARD(atk_gobject_accessible_get_object - (ATK_GOBJECT_ACCESSIBLE(accessible))); - if (!card) - return NULL; - - g_object_get (card->header_text, "text", &string, NULL); - - if (e_contact_get (card->contact, E_CONTACT_IS_LIST)) - g_string_append (new_str, _("Contact List: ")); - else g_string_append (new_str, _("Contact: ")); - - /* get header of current card */ - g_string_append (new_str, string); - g_free (string); - - /* if there exist no enough space for remain info, return */ - if (new_str->len >= BUFFERSIZE) { - strncpy (name, new_str->str, BUFFERSIZE); - return name; - } - - strcpy (name, new_str->str); - g_string_free (new_str, TRUE); - - ATK_OBJECT_CLASS (parent_class)->set_name (accessible, name); - - return accessible->name; -} - -static G_CONST_RETURN gchar * -ea_minicard_get_description (AtkObject *accessible) -{ - if (accessible->description) - return accessible->description; - - return _("evolution minicard"); -} - -AtkObject* -ea_minicard_new (GObject *obj) -{ - GObject *object; - AtkObject *accessible; - - g_return_val_if_fail(obj != NULL, NULL); - g_return_val_if_fail (E_IS_MINICARD(obj), NULL); - - object = g_object_new (EA_TYPE_MINICARD, NULL); - accessible = ATK_OBJECT (object); - atk_object_initialize (accessible, obj); - - accessible->role = ATK_ROLE_PANEL; - return accessible; -} - -static AtkStateSet *ea_minicard_ref_state_set (AtkObject *obj) -{ - AtkStateSet *state_set = NULL; - GObject *gobj = NULL; - - state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (obj); - if( !state_set ) - state_set = atk_state_set_new (); - - gobj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (obj)); - if( !gobj ) - return state_set; - - atk_state_set_add_state (state_set, ATK_STATE_SELECTABLE); - atk_state_set_add_state (state_set, ATK_STATE_ENABLED); - atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE); - atk_state_set_add_state (state_set, ATK_STATE_SHOWING); - - return state_set; -} - -static gint -ea_minicard_get_n_children (AtkObject *accessible) -{ - return 0; -} - -static AtkObject * -ea_minicard_ref_child (AtkObject *accessible, gint index) -{ - return NULL; -} - -static void atk_action_interface_init (AtkActionIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->do_action = atk_action_interface_do_action; - iface->get_n_actions = atk_action_interface_get_n_action; - iface->get_description = atk_action_interface_get_description; - iface->get_name = atk_action_interface_get_name; -} - -static gboolean atk_action_interface_do_action (AtkAction *iface, gint i) -{ - EMinicard *minicard = NULL; - - minicard = E_MINICARD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (iface))); - if( minicard == NULL ) - return FALSE; - - if( i >= G_N_ELEMENTS (action_name) || i < 0 ) - return FALSE; - - switch (i) { - /* open card */ - case 0: - e_minicard_activate_editor (minicard); - break; - default: - return FALSE; - } - - return TRUE; -} - -static gint atk_action_interface_get_n_action (AtkAction *iface) -{ - return G_N_ELEMENTS (action_name); -} - -static G_CONST_RETURN gchar * -atk_action_interface_get_description (AtkAction *iface, gint i) -{ - return atk_action_interface_get_name (iface, i); -} - -static G_CONST_RETURN gchar * -atk_action_interface_get_name (AtkAction *iface, gint i) -{ - if( i >= G_N_ELEMENTS (action_name) || i < 0) - return NULL; - - return action_name[i]; -} - diff --git a/addressbook/gui/widgets/a11y/ea-minicard.h b/addressbook/gui/widgets/a11y/ea-minicard.h deleted file mode 100644 index 879463b629..0000000000 --- a/addressbook/gui/widgets/a11y/ea-minicard.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Leon Zhang - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EA_MINICARD_H__ -#define __EA_MINICARD_H__ - -#include -#include "e-minicard.h" -#include "e-minicard-label.h" - -G_BEGIN_DECLS - -#define EA_TYPE_MINICARD (ea_minicard_get_type ()) -#define EA_MINICARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_MINICARD, EaMinicard)) -#define EA_MINICARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_MINICARD, EaMiniCardClass)) -#define EA_IS_MINICARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_MINICARD)) -#define EA_IS_MINICARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EA_TYPE_MINICARD)) - -typedef struct _EaMinicard EaMinicard; -typedef struct _EaMinicardClass EaMinicardClass; - -struct _EaMinicard -{ - AtkGObjectAccessible parent; -}; - - -struct _EaMinicardClass -{ - AtkGObjectAccessibleClass parent_class; -}; - -GType ea_minicard_get_type (void); -AtkObject* ea_minicard_new(GObject *obj); - -G_END_DECLS - - -#endif /* __EA_MINICARD_H__ */ diff --git a/addressbook/gui/widgets/e-addressbook-view.c b/addressbook/gui/widgets/e-addressbook-view.c index 5df049dbe6..ae79ead397 100644 --- a/addressbook/gui/widgets/e-addressbook-view.c +++ b/addressbook/gui/widgets/e-addressbook-view.c @@ -33,7 +33,7 @@ #include #include "addressbook/printing/e-contact-print.h" -#include "a11y/ea-addressbook.h" +#include "ea-addressbook.h" #include "e-util/e-print.h" #include "e-util/e-util.h" diff --git a/addressbook/gui/widgets/e-minicard-view.c b/addressbook/gui/widgets/e-minicard-view.c index ece8d84654..6ee55f8b9f 100644 --- a/addressbook/gui/widgets/e-minicard-view.c +++ b/addressbook/gui/widgets/e-minicard-view.c @@ -34,7 +34,7 @@ #include #include #include "e-util/e-util.h" -#include "a11y/ea-addressbook.h" +#include "ea-addressbook.h" static void e_minicard_view_drag_data_get(GtkWidget *widget, GdkDragContext *context, diff --git a/addressbook/gui/widgets/e-minicard.c b/addressbook/gui/widgets/e-minicard.c index 2d9deeecbc..a8b6554888 100644 --- a/addressbook/gui/widgets/e-minicard.c +++ b/addressbook/gui/widgets/e-minicard.c @@ -38,7 +38,7 @@ #include #include #include -#include "a11y/ea-addressbook.h" +#include "ea-addressbook.h" static void e_minicard_init (EMinicard *card); static void e_minicard_class_init (EMinicardClass *class); diff --git a/addressbook/gui/widgets/ea-addressbook-view.c b/addressbook/gui/widgets/ea-addressbook-view.c new file mode 100644 index 0000000000..b2d7ebb171 --- /dev/null +++ b/addressbook/gui/widgets/ea-addressbook-view.c @@ -0,0 +1,123 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Leon Zhang + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include + +#include +#include "ea-addressbook-view.h" + +static G_CONST_RETURN gchar * ea_ab_view_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar * ea_ab_view_get_description (AtkObject *accessible); + +static void ea_ab_view_class_init (EAddressbookViewClass *class); + +static gpointer parent_class = NULL; + +GType +ea_ab_view_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EAddressbookViewClass), + (GBaseInitFunc) NULL, /* base_init */ + (GBaseFinalizeFunc) NULL, /* base_finalize */ + (GClassInitFunc) ea_ab_view_class_init, + (GClassFinalizeFunc) NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (EAddressbookView), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (GailWidget, in this case) */ + + factory = atk_registry_get_factory (atk_get_default_registry (), + GTK_TYPE_EVENT_BOX); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + type = g_type_register_static (derived_atk_type, + "EaABView", &tinfo, 0); + } + + return type; +} + +static void +ea_ab_view_class_init (EAddressbookViewClass *class) +{ + AtkObjectClass *atk_object_class; + + parent_class = g_type_class_peek_parent (class); + + atk_object_class = ATK_OBJECT_CLASS (class); + atk_object_class->get_name = ea_ab_view_get_name; + atk_object_class->get_description = ea_ab_view_get_description; +} + +static G_CONST_RETURN gchar * +ea_ab_view_get_name (AtkObject *accessible) +{ + g_return_val_if_fail (EA_IS_AB_VIEW(accessible), NULL); + if (accessible->name) + return accessible->name; + + return _("evolution address book"); +} + +static G_CONST_RETURN gchar * +ea_ab_view_get_description (AtkObject *accessible) +{ + if (accessible->description) + return accessible->description; + + return _("evolution address book"); +} + +AtkObject* +ea_ab_view_new (GObject *obj) +{ + GObject *object; + AtkObject *accessible; + + g_return_val_if_fail(obj != NULL, NULL); + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW(obj), NULL); + + object = g_object_new (EA_TYPE_AB_VIEW, NULL); + + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, obj); + accessible->role = ATK_ROLE_CANVAS; + + return accessible; +} diff --git a/addressbook/gui/widgets/ea-addressbook-view.h b/addressbook/gui/widgets/ea-addressbook-view.h new file mode 100644 index 0000000000..4607746337 --- /dev/null +++ b/addressbook/gui/widgets/ea-addressbook-view.h @@ -0,0 +1,57 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Leon Zhang + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_ADDRESSBOOK_VIEW_H__ +#define __EA_ADDRESSBOOK_VIEW_H__ + +#include +#include "e-addressbook-view.h" + +G_BEGIN_DECLS + +#define EA_TYPE_AB_VIEW (ea_ab_view_get_type ()) +#define EA_AB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_AB_VIEW, EaABView)) +#define EA_AB_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_AB_VIEW, EaABViewClass)) +#define EA_IS_AB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_AB_VIEW)) +#define EA_IS_AB_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EA_TYPE_AB_VIEW)) + +typedef struct _EaABView EaABView; +typedef struct _EaABViewClass EaABViewClass; + +struct _EaABView +{ + GtkAccessible parent; +}; + + +struct _EaABViewClass +{ + GtkAccessibleClass parent_class; +}; + +GType ea_ab_view_get_type (void); +AtkObject* ea_ab_view_new(GObject *obj); + +G_END_DECLS + + +#endif /* __EA_ADDRESSBOOK_VIEW_H__ */ diff --git a/addressbook/gui/widgets/ea-addressbook.c b/addressbook/gui/widgets/ea-addressbook.c new file mode 100644 index 0000000000..14fc4c1ca3 --- /dev/null +++ b/addressbook/gui/widgets/ea-addressbook.c @@ -0,0 +1,84 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Leon Zhang + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include +#include "a11y/ea-factory.h" +#include "ea-addressbook.h" +#include "ea-minicard.h" +#include "ea-minicard-view.h" +#include "ea-addressbook-view.h" + +EA_FACTORY_GOBJECT (EA_TYPE_MINICARD, ea_minicard, ea_minicard_new) +EA_FACTORY_GOBJECT (EA_TYPE_MINICARD_VIEW, ea_minicard_view, ea_minicard_view_new) +EA_FACTORY_GOBJECT (EA_TYPE_AB_VIEW, ea_ab_view, ea_ab_view_new) + +static gboolean ea_addressbook_focus_watcher (GSignalInvocationHint *ihint, + guint n_param_values, + const GValue *param_values, + gpointer data); + +void e_minicard_a11y_init (void) +{ + EA_SET_FACTORY (e_minicard_get_type (), ea_minicard); +} + +void e_minicard_view_a11y_init (void) +{ + EA_SET_FACTORY (e_minicard_view_get_type (), ea_minicard_view); + + if (atk_get_root ()) { + g_signal_add_emission_hook (g_signal_lookup ("event", + e_minicard_get_type()), + 0, ea_addressbook_focus_watcher, + NULL, (GDestroyNotify) NULL); + } +} + +void eab_view_a11y_init (void) +{ + EA_SET_FACTORY (E_TYPE_ADDRESSBOOK_VIEW, ea_ab_view); +} + +static gboolean +ea_addressbook_focus_watcher (GSignalInvocationHint *ihint, + guint n_param_values, + const GValue *param_values, + gpointer data) +{ + GObject *object; + GdkEvent *event; + AtkObject *ea_event = NULL; + + object = g_value_get_object (param_values + 0); + event = g_value_get_boxed (param_values + 1); + + if (E_IS_MINICARD (object)) { + GnomeCanvasItem *item = GNOME_CANVAS_ITEM (object); + ea_event = atk_gobject_accessible_for_object (object); + if (event->type == GDK_FOCUS_CHANGE) { + if ((event->focus_change.in) && (E_IS_MINICARD (item->canvas->focused_item))) + atk_focus_tracker_notify (ea_event); + } + } + + return TRUE; +} diff --git a/addressbook/gui/widgets/ea-addressbook.h b/addressbook/gui/widgets/ea-addressbook.h new file mode 100644 index 0000000000..97b691dc18 --- /dev/null +++ b/addressbook/gui/widgets/ea-addressbook.h @@ -0,0 +1,33 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Leon Zhang + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/* Evolution Accessibility +*/ + +#ifndef _EA_ADDRESSBOOK_H__ +#define _EA_ADDRESSBOOK_H__ + +void eab_view_a11y_init (void); +void e_minicard_view_a11y_init (void); +void e_minicard_a11y_init (void); + +#endif /* _EA_ADDRESSBOOK_H__ */ diff --git a/addressbook/gui/widgets/ea-minicard-view.c b/addressbook/gui/widgets/ea-minicard-view.c new file mode 100644 index 0000000000..b35f64ae5e --- /dev/null +++ b/addressbook/gui/widgets/ea-minicard-view.c @@ -0,0 +1,413 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Leon Zhang < leon.zhang@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include +#include +#include +#include +#include "ea-minicard.h" +#include "ea-minicard-view.h" +#include "eab-gui-util.h" +#include "e-addressbook-view.h" + +static const gchar * action_name[] = { + N_("New Contact"), + N_("New Contact List") +}; + + +static G_CONST_RETURN gchar * ea_minicard_view_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar * ea_minicard_view_get_description (AtkObject *accessible); + +static void ea_minicard_view_class_init (EaMinicardViewClass *klass); + +static gint ea_minicard_view_get_n_children (AtkObject *obj); +static AtkObject *ea_minicard_view_ref_child (AtkObject *obj, gint i); + +static AtkStateSet *ea_minicard_view_ref_state_set(AtkObject *obj); + +static void atk_selection_interface_init (AtkSelectionIface *iface); +static gboolean selection_interface_add_selection (AtkSelection *selection, + gint i); +static gboolean selection_interface_clear_selection (AtkSelection *selection); +static AtkObject* selection_interface_ref_selection (AtkSelection *selection, + gint i); +static gint selection_interface_get_selection_count (AtkSelection *selection); +static gboolean selection_interface_is_child_selected (AtkSelection *selection, + gint i); + +static void atk_action_interface_init (AtkActionIface *iface); +static gboolean atk_action_interface_do_action (AtkAction *iface, gint i); +static gint atk_action_interface_get_n_action (AtkAction *iface); +static G_CONST_RETURN gchar * atk_action_interface_get_description (AtkAction *iface, gint i); +static G_CONST_RETURN gchar * atk_action_interface_get_name (AtkAction *iface, gint i); + +static gpointer parent_class = NULL; + +GType +ea_minicard_view_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaMinicardViewClass), + (GBaseInitFunc) NULL, /* base_init */ + (GBaseFinalizeFunc) NULL, /* base_finalize */ + (GClassInitFunc) ea_minicard_view_class_init, + (GClassFinalizeFunc) NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (EaMinicardView), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + static const GInterfaceInfo atk_selection_info = { + (GInterfaceInitFunc) atk_selection_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + static const GInterfaceInfo atk_action_info = { + (GInterfaceInitFunc) atk_action_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (GailWidget, in this case) */ + + factory = atk_registry_get_factory (atk_get_default_registry (), + GNOME_TYPE_CANVAS_GROUP); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + type = g_type_register_static (derived_atk_type, + "EaMinicardView", &tinfo, 0); + g_type_add_interface_static (type, ATK_TYPE_SELECTION, + &atk_selection_info); + g_type_add_interface_static (type, ATK_TYPE_ACTION, + &atk_action_info); + + } + + return type; +} + +static void +ea_minicard_view_class_init (EaMinicardViewClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + class->get_name = ea_minicard_view_get_name; + class->get_description = ea_minicard_view_get_description; + class->ref_state_set = ea_minicard_view_ref_state_set; + class->get_n_children = ea_minicard_view_get_n_children; + class->ref_child = ea_minicard_view_ref_child; +} + +static G_CONST_RETURN gchar * +ea_minicard_view_get_name (AtkObject *accessible) +{ + EReflow *reflow; + gchar *string; + EMinicardView *card_view; + EBook *book = NULL; + const gchar *source_name; + + g_return_val_if_fail (EA_IS_MINICARD_VIEW (accessible), NULL); + + reflow = E_REFLOW(atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible))); + + if (!reflow) + return NULL; + + /* Get the current name of minicard view*/ + card_view = E_MINICARD_VIEW (reflow); + g_object_get (card_view->adapter, "book", &book, NULL); + g_return_val_if_fail (E_IS_BOOK (book), NULL); + source_name = e_source_peek_name (e_book_get_source (book)); + if (!source_name) + source_name=""; + + string = g_strdup_printf (ngettext ("current address book folder %s has %d card", + "current address book folder %s has %d cards", + reflow->count), source_name, reflow->count); + + ATK_OBJECT_CLASS (parent_class)->set_name (accessible, string); + g_free (string); + g_object_unref(book); + return accessible->name; +} + +static G_CONST_RETURN gchar * +ea_minicard_view_get_description (AtkObject *accessible) +{ + g_return_val_if_fail (EA_IS_MINICARD_VIEW(accessible), NULL); + if (accessible->description) + return accessible->description; + + return _("evolution address book"); +} + +AtkObject* +ea_minicard_view_new (GObject *obj) +{ + GObject *object; + AtkObject *accessible; + + g_return_val_if_fail (E_IS_MINICARD_VIEW(obj), NULL); + object = g_object_new (EA_TYPE_MINICARD_VIEW, NULL); + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, obj); + accessible->role = ATK_ROLE_PANEL; + return accessible; +} + +static gint +ea_minicard_view_get_n_children (AtkObject *accessible) +{ + EReflow *reflow; + + gint child_num = 0; + + g_return_val_if_fail (EA_IS_MINICARD_VIEW (accessible), -1); + + reflow = E_REFLOW (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible))); + + if (!reflow) + return -1; + + child_num = reflow->count; + + return child_num; +} + +static AtkStateSet *ea_minicard_view_ref_state_set (AtkObject *obj) +{ + AtkStateSet *state_set = NULL; + GObject *gobj = NULL; + + state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (obj); + if( !state_set ) + state_set = atk_state_set_new (); + + gobj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (obj)); + if( !gobj ) + return state_set; + + atk_state_set_add_state (state_set, ATK_STATE_ENABLED); + atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE); + atk_state_set_add_state (state_set, ATK_STATE_SHOWING); + + return state_set; +} + +static AtkObject * +ea_minicard_view_ref_child (AtkObject *accessible, gint index) +{ + EReflow *reflow; + gint child_num; + AtkObject *atk_object = NULL; + EMinicard *card = NULL; + + g_return_val_if_fail (EA_IS_MINICARD_VIEW (accessible), NULL); + + child_num = atk_object_get_n_accessible_children (accessible); + if (child_num <= 0 || index < 0 || index >= child_num) + return NULL; + + reflow = E_REFLOW (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible))); + if (!reflow) + return NULL; + if (!reflow->items ) + return NULL; + /* a minicard */ + if (index < child_num) { + card = E_MINICARD (reflow->items[index]); + atk_object = atk_gobject_accessible_for_object (G_OBJECT (card)); + } else { + return NULL; + } + + g_object_ref (atk_object); + return atk_object; +} + +/* atkselection interface */ + +static void +atk_selection_interface_init (AtkSelectionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->add_selection = selection_interface_add_selection; + iface->clear_selection = selection_interface_clear_selection; + iface->ref_selection = selection_interface_ref_selection; + iface->get_selection_count = selection_interface_get_selection_count; + iface->is_child_selected = selection_interface_is_child_selected; +} + +static gboolean +selection_interface_add_selection (AtkSelection *selection, gint i) +{ + AtkGObjectAccessible *atk_gobj= NULL; + EReflow *reflow = NULL; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (selection); + reflow = E_REFLOW (atk_gobject_accessible_get_object (atk_gobj)); + + if (!reflow) + return FALSE; + + selection_interface_clear_selection (selection); + e_selection_model_select_single_row (reflow->selection, i); + + return TRUE; +} + +static gboolean +selection_interface_clear_selection (AtkSelection *selection) +{ + AtkGObjectAccessible *atk_gobj = NULL; + EReflow *reflow = NULL; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (selection); + reflow = E_REFLOW(atk_gobject_accessible_get_object (atk_gobj)); + + if( !reflow ) + return FALSE; + + e_selection_model_clear (reflow->selection); + + return TRUE; +} + +static AtkObject* +selection_interface_ref_selection (AtkSelection *selection, gint i) +{ + return ea_minicard_view_ref_child (ATK_OBJECT (selection), i); +} + +static gint +selection_interface_get_selection_count (AtkSelection *selection) +{ + AtkGObjectAccessible *atk_gobj = NULL; + EReflow *reflow = NULL; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (selection); + reflow = E_REFLOW (atk_gobject_accessible_get_object (atk_gobj)); + + if (!reflow ) + return FALSE; + + return e_selection_model_selected_count (reflow->selection); +} + +static gboolean +selection_interface_is_child_selected (AtkSelection *selection, gint i) +{ + AtkGObjectAccessible *atk_gobj = NULL; + EReflow *reflow = NULL; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (selection); + reflow = E_REFLOW(atk_gobject_accessible_get_object (atk_gobj)); + + if( !reflow ) + return FALSE; + + return e_selection_model_is_row_selected (reflow->selection, i); +} + +static void atk_action_interface_init (AtkActionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->do_action = atk_action_interface_do_action; + iface->get_n_actions = atk_action_interface_get_n_action; + iface->get_description = atk_action_interface_get_description; + iface->get_name = atk_action_interface_get_name; +} + +static gboolean atk_action_interface_do_action (AtkAction *action, gint i) +{ + gboolean return_value = TRUE; + EMinicardView *card_view; + + AtkGObjectAccessible *atk_gobj= NULL; + EReflow *reflow = NULL; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (action); + reflow = E_REFLOW (atk_gobject_accessible_get_object (atk_gobj)); + + if (reflow == NULL) + return FALSE; + + card_view = E_MINICARD_VIEW (reflow); + + switch (i) { + case 0: + /* New Contact */ + e_minicard_view_create_contact (card_view); + break; + case 1: + /* New Contact List */ + e_minicard_view_create_contact_list (card_view); + break; + default: + return_value = FALSE; + break; + } + + return return_value; +} + +static gint atk_action_interface_get_n_action (AtkAction *iface) +{ + return G_N_ELEMENTS (action_name); +} + +static G_CONST_RETURN gchar * +atk_action_interface_get_description (AtkAction *iface, gint i) +{ + return atk_action_interface_get_name (iface, i); +} + +static G_CONST_RETURN gchar * +atk_action_interface_get_name (AtkAction *iface, gint i) +{ + if( i >= G_N_ELEMENTS (action_name) || i < 0) + return NULL; + + return action_name[i]; +} + diff --git a/addressbook/gui/widgets/ea-minicard-view.h b/addressbook/gui/widgets/ea-minicard-view.h new file mode 100644 index 0000000000..c564dac8c8 --- /dev/null +++ b/addressbook/gui/widgets/ea-minicard-view.h @@ -0,0 +1,59 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Leon Zhang + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_MINICARD_VIEW_H__ +#define __EA_MINICARD_VIEW_H__ + +#include +#include "e-minicard-view.h" + +G_BEGIN_DECLS + +#define EA_TYPE_MINICARD_VIEW (ea_minicard_view_get_type ()) +#define EA_MINICARD_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_MINICARD_VIEW, EaMinicardView)) +#define EA_MINICARD_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_MINICARD_VIEW, EaMiniCardViewClass)) +#define EA_IS_MINICARD_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_MINICARD_VIEW)) +#define EA_IS_MINICARD_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EA_TYPE_MINICARD_VIEW)) + + +typedef struct _EaMinicardView EaMinicardView; +typedef struct _EaMinicardViewClass EaMinicardViewClass; + +struct _EaMinicardView +{ + AtkGObjectAccessible parent; +}; + + +struct _EaMinicardViewClass +{ + AtkGObjectAccessibleClass parent_class; +}; + +GType ea_minicard_view_get_type (void); + +AtkObject* ea_minicard_view_new(GObject *obj); + +G_END_DECLS + + +#endif /* __EA_MINICARD_VIEW_H__ */ diff --git a/addressbook/gui/widgets/ea-minicard.c b/addressbook/gui/widgets/ea-minicard.c new file mode 100644 index 0000000000..b1b1ebbe33 --- /dev/null +++ b/addressbook/gui/widgets/ea-minicard.c @@ -0,0 +1,273 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Leon Zhang + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include +#include +#include +#include "ea-minicard.h" +#include "ea-minicard-view.h" +#include "e-minicard.h" + +static const gchar * action_name[] = { + N_("Open") +}; + +static G_CONST_RETURN gchar * ea_minicard_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar * ea_minicard_get_description (AtkObject *accessible); + +static void ea_minicard_class_init (EaMinicardClass *klass); + +static gint ea_minicard_get_n_children (AtkObject *obj); +static AtkObject* ea_minicard_ref_child(AtkObject *obj, gint i); + +static AtkStateSet *ea_minicard_ref_state_set (AtkObject *obj); + +static void atk_action_interface_init (AtkActionIface *iface); +static gboolean atk_action_interface_do_action (AtkAction *iface, gint i); +static gint atk_action_interface_get_n_action (AtkAction *iface); +static G_CONST_RETURN gchar * atk_action_interface_get_description (AtkAction *iface, gint i); +static G_CONST_RETURN gchar * atk_action_interface_get_name (AtkAction *iface, gint i); + +static gpointer parent_class = NULL; + +GType +ea_minicard_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaMinicardClass), + (GBaseInitFunc) NULL, /* base_init */ + (GBaseFinalizeFunc) NULL, /* base_finalize */ + (GClassInitFunc) ea_minicard_class_init, + (GClassFinalizeFunc) NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (EaMinicard), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + static const GInterfaceInfo atk_action_info = { + (GInterfaceInitFunc) atk_action_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (GailWidget, in this case) + */ + + factory = atk_registry_get_factory (atk_get_default_registry (), + GNOME_TYPE_CANVAS_GROUP); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + type = g_type_register_static ( derived_atk_type, + "EaMinicard", &tinfo, 0); + g_type_add_interface_static (type, ATK_TYPE_ACTION, + &atk_action_info); + } + + return type; +} + +static void +ea_minicard_class_init (EaMinicardClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + class->get_name = ea_minicard_get_name; + class->get_description = ea_minicard_get_description; + class->ref_state_set = ea_minicard_ref_state_set; + class->get_n_children = ea_minicard_get_n_children; + class->ref_child = ea_minicard_ref_child; +} + +/* + * we access the main content of current minicard, including + * header text, label(field, field name) + */ +static G_CONST_RETURN gchar * +ea_minicard_get_name (AtkObject *accessible) +{ +#define BUFFERSIZE 500 + + static gchar name[BUFFERSIZE]; + GString *new_str = g_string_new (NULL); + gchar *string; + EMinicard *card; + + g_return_val_if_fail (EA_IS_MINICARD(accessible), NULL); + memset (name, '\0', BUFFERSIZE); + + card = E_MINICARD(atk_gobject_accessible_get_object + (ATK_GOBJECT_ACCESSIBLE(accessible))); + if (!card) + return NULL; + + g_object_get (card->header_text, "text", &string, NULL); + + if (e_contact_get (card->contact, E_CONTACT_IS_LIST)) + g_string_append (new_str, _("Contact List: ")); + else g_string_append (new_str, _("Contact: ")); + + /* get header of current card */ + g_string_append (new_str, string); + g_free (string); + + /* if there exist no enough space for remain info, return */ + if (new_str->len >= BUFFERSIZE) { + strncpy (name, new_str->str, BUFFERSIZE); + return name; + } + + strcpy (name, new_str->str); + g_string_free (new_str, TRUE); + + ATK_OBJECT_CLASS (parent_class)->set_name (accessible, name); + + return accessible->name; +} + +static G_CONST_RETURN gchar * +ea_minicard_get_description (AtkObject *accessible) +{ + if (accessible->description) + return accessible->description; + + return _("evolution minicard"); +} + +AtkObject* +ea_minicard_new (GObject *obj) +{ + GObject *object; + AtkObject *accessible; + + g_return_val_if_fail(obj != NULL, NULL); + g_return_val_if_fail (E_IS_MINICARD(obj), NULL); + + object = g_object_new (EA_TYPE_MINICARD, NULL); + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, obj); + + accessible->role = ATK_ROLE_PANEL; + return accessible; +} + +static AtkStateSet *ea_minicard_ref_state_set (AtkObject *obj) +{ + AtkStateSet *state_set = NULL; + GObject *gobj = NULL; + + state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (obj); + if( !state_set ) + state_set = atk_state_set_new (); + + gobj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (obj)); + if( !gobj ) + return state_set; + + atk_state_set_add_state (state_set, ATK_STATE_SELECTABLE); + atk_state_set_add_state (state_set, ATK_STATE_ENABLED); + atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE); + atk_state_set_add_state (state_set, ATK_STATE_SHOWING); + + return state_set; +} + +static gint +ea_minicard_get_n_children (AtkObject *accessible) +{ + return 0; +} + +static AtkObject * +ea_minicard_ref_child (AtkObject *accessible, gint index) +{ + return NULL; +} + +static void atk_action_interface_init (AtkActionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->do_action = atk_action_interface_do_action; + iface->get_n_actions = atk_action_interface_get_n_action; + iface->get_description = atk_action_interface_get_description; + iface->get_name = atk_action_interface_get_name; +} + +static gboolean atk_action_interface_do_action (AtkAction *iface, gint i) +{ + EMinicard *minicard = NULL; + + minicard = E_MINICARD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (iface))); + if( minicard == NULL ) + return FALSE; + + if( i >= G_N_ELEMENTS (action_name) || i < 0 ) + return FALSE; + + switch (i) { + /* open card */ + case 0: + e_minicard_activate_editor (minicard); + break; + default: + return FALSE; + } + + return TRUE; +} + +static gint atk_action_interface_get_n_action (AtkAction *iface) +{ + return G_N_ELEMENTS (action_name); +} + +static G_CONST_RETURN gchar * +atk_action_interface_get_description (AtkAction *iface, gint i) +{ + return atk_action_interface_get_name (iface, i); +} + +static G_CONST_RETURN gchar * +atk_action_interface_get_name (AtkAction *iface, gint i) +{ + if( i >= G_N_ELEMENTS (action_name) || i < 0) + return NULL; + + return action_name[i]; +} + diff --git a/addressbook/gui/widgets/ea-minicard.h b/addressbook/gui/widgets/ea-minicard.h new file mode 100644 index 0000000000..879463b629 --- /dev/null +++ b/addressbook/gui/widgets/ea-minicard.h @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Leon Zhang + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_MINICARD_H__ +#define __EA_MINICARD_H__ + +#include +#include "e-minicard.h" +#include "e-minicard-label.h" + +G_BEGIN_DECLS + +#define EA_TYPE_MINICARD (ea_minicard_get_type ()) +#define EA_MINICARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_MINICARD, EaMinicard)) +#define EA_MINICARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_MINICARD, EaMiniCardClass)) +#define EA_IS_MINICARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_MINICARD)) +#define EA_IS_MINICARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EA_TYPE_MINICARD)) + +typedef struct _EaMinicard EaMinicard; +typedef struct _EaMinicardClass EaMinicardClass; + +struct _EaMinicard +{ + AtkGObjectAccessible parent; +}; + + +struct _EaMinicardClass +{ + AtkGObjectAccessibleClass parent_class; +}; + +GType ea_minicard_get_type (void); +AtkObject* ea_minicard_new(GObject *obj); + +G_END_DECLS + + +#endif /* __EA_MINICARD_H__ */ diff --git a/calendar/Makefile.am b/calendar/Makefile.am index 5da53380b8..87057a4d3a 100644 --- a/calendar/Makefile.am +++ b/calendar/Makefile.am @@ -4,7 +4,7 @@ else CONDUIT_DIR = endif -SUBDIRS = idl common importers gui $(CONDUIT_DIR) module +SUBDIRS = idl common importers gui $(CONDUIT_DIR) error_DATA = calendar.error errordir = $(privdatadir)/errors diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am index 0f669eee4f..b919da8cf3 100644 --- a/calendar/gui/Makefile.am +++ b/calendar/gui/Makefile.am @@ -1,5 +1,5 @@ if OS_WIN32 -WIN32_BOOTSTRAP_LIBS = $(top_builddir)/win32/libevolution-mail-shared.la +WIN32_BOOTSTRAP_LIBS = $(top_builddir)/win32/libevolution-mail.la endif SUBDIRS = alarm-notify dialogs @@ -24,7 +24,6 @@ INCLUDES = \ -I$(top_srcdir)/calendar \ -I$(top_srcdir)/widgets \ -I$(top_srcdir)/widgets/misc \ - -I$(top_srcdir)/a11y/calendar \ -DSEARCH_RULE_DIR=\"$(ruledir)\" \ -DEVOLUTION_GLADEDIR=\""$(gladedir)"\" \ -DEVOLUTION_ETSPECDIR=\""$(etspecdir)"\" \ @@ -177,30 +176,30 @@ libcal_gui_la_SOURCES = \ weekday-picker.h # no gnome-cal no a11y. FIXME: KILL-BONOBO -# a11y/ea-calendar.c \ -# a11y/ea-calendar.h \ -# a11y/ea-calendar-helpers.c \ -# a11y/ea-calendar-helpers.h \ -# a11y/ea-cal-view.c \ -# a11y/ea-cal-view.h \ -# a11y/ea-cal-view-event.c \ -# a11y/ea-cal-view-event.h \ -# a11y/ea-day-view.c \ -# a11y/ea-day-view.h \ -# a11y/ea-day-view-main-item.c \ -# a11y/ea-day-view-main-item.h \ -# a11y/ea-day-view-cell.c \ -# a11y/ea-day-view-cell.h \ -# a11y/ea-week-view.c \ -# a11y/ea-week-view.h \ -# a11y/ea-week-view-main-item.c \ -# a11y/ea-week-view-main-item.h \ -# a11y/ea-week-view-cell.c \ -# a11y/ea-week-view-cell.h \ -# a11y/ea-jump-button.c \ -# a11y/ea-jump-button.h \ -# a11y/ea-gnome-calendar.c \ -# a11y/ea-gnome-calendar.h +# ea-calendar.c \ +# ea-calendar.h \ +# ea-calendar-helpers.c \ +# ea-calendar-helpers.h \ +# ea-cal-view.c \ +# ea-cal-view.h \ +# ea-cal-view-event.c \ +# ea-cal-view-event.h \ +# ea-day-view.c \ +# ea-day-view.h \ +# ea-day-view-main-item.c \ +# ea-day-view-main-item.h \ +# ea-day-view-cell.c \ +# ea-day-view-cell.h \ +# ea-week-view.c \ +# ea-week-view.h \ +# ea-week-view-main-item.c \ +# ea-week-view-main-item.h \ +# ea-week-view-cell.c \ +# ea-week-view-cell.h \ +# ea-jump-button.c \ +# ea-jump-button.h \ +# ea-gnome-calendar.c \ +# ea-gnome-calendar.h libcal_gui_la_LIBADD = \ $(top_builddir)/composer/libcomposer.la \ diff --git a/calendar/gui/a11y/ea-cal-view-event.c b/calendar/gui/a11y/ea-cal-view-event.c deleted file mode 100644 index 5da164323f..0000000000 --- a/calendar/gui/a11y/ea-cal-view-event.c +++ /dev/null @@ -1,573 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "ea-cal-view-event.h" -#include "ea-calendar-helpers.h" -#include "ea-day-view.h" -#include "ea-week-view.h" -#include -#include - -static void ea_cal_view_event_class_init (EaCalViewEventClass *klass); -static void ea_cal_view_event_init (EaCalViewEvent *a11y); - -static void ea_cal_view_event_dispose (GObject *object); -static G_CONST_RETURN gchar * ea_cal_view_event_get_name (AtkObject *accessible); -static G_CONST_RETURN gchar * ea_cal_view_event_get_description (AtkObject *accessible); -static AtkObject* ea_cal_view_event_get_parent (AtkObject *accessible); -static gint ea_cal_view_event_get_index_in_parent (AtkObject *accessible); -static AtkStateSet *ea_cal_view_event_ref_state_set (AtkObject *accessible); - -/* component interface */ -static void atk_component_interface_init (AtkComponentIface *iface); -static void ea_cal_view_get_extents (AtkComponent *component, - gint *x, gint *y, gint *width, gint *height, - AtkCoordType coord_type); -/* action interface */ -static void atk_action_interface_init (AtkActionIface *iface); -static gboolean ea_cal_view_event_do_action (AtkAction *action, gint i); -static gint ea_cal_view_event_get_n_actions (AtkAction *action); -static G_CONST_RETURN gchar * ea_cal_view_event_action_get_name (AtkAction *action, gint i); - - -#ifdef ACC_DEBUG -static gint n_ea_cal_view_event_created = 0, n_ea_cal_view_event_destroyed = 0; -static void ea_cal_view_finalize (GObject *object); -#endif - -static gpointer parent_class = NULL; - -GType -ea_cal_view_event_get_type (void) -{ - static GType type = 0; - AtkObjectFactory *factory; - GTypeQuery query; - GType derived_atk_type; - - - if (!type) { - static GTypeInfo tinfo = { - sizeof (EaCalViewEventClass), - (GBaseInitFunc) NULL, /* base init */ - (GBaseFinalizeFunc) NULL, /* base finalize */ - (GClassInitFunc) ea_cal_view_event_class_init, /* class init */ - (GClassFinalizeFunc) NULL, /* class finalize */ - NULL, /* class data */ - sizeof (EaCalViewEvent), /* instance size */ - 0, /* nb preallocs */ - (GInstanceInitFunc) ea_cal_view_event_init, /* instance init */ - NULL /* value table */ - }; - - static const GInterfaceInfo atk_component_info = { - (GInterfaceInitFunc) atk_component_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - static const GInterfaceInfo atk_action_info = { - (GInterfaceInitFunc) atk_action_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - - /* - * Figure out the size of the class and instance - * we are run-time deriving from (atk object for E_TEXT, in this case) - */ - - factory = atk_registry_get_factory (atk_get_default_registry (), - E_TYPE_TEXT); - derived_atk_type = atk_object_factory_get_accessible_type (factory); - g_type_query (derived_atk_type, &query); - - tinfo.class_size = query.class_size; - tinfo.instance_size = query.instance_size; - - /* we inherit the component, text and other interfaces from E_TEXT */ - type = g_type_register_static (derived_atk_type, - "EaCalViewEvent", &tinfo, 0); - g_type_add_interface_static (type, ATK_TYPE_COMPONENT, - &atk_component_info); - g_type_add_interface_static (type, ATK_TYPE_ACTION, - &atk_action_info); - - - } - - return type; -} - -static void -ea_cal_view_event_class_init (EaCalViewEventClass *klass) -{ - AtkObjectClass *class = ATK_OBJECT_CLASS (klass); - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); -#ifdef ACC_DEBUG - gobject_class->finalize = ea_cal_view_finalize; -#endif - - parent_class = g_type_class_peek_parent (klass); - - gobject_class->dispose = ea_cal_view_event_dispose; - - class->get_name = ea_cal_view_event_get_name; - class->get_description = ea_cal_view_event_get_description; - class->get_parent = ea_cal_view_event_get_parent; - class->get_index_in_parent = ea_cal_view_event_get_index_in_parent; - class->ref_state_set = ea_cal_view_event_ref_state_set; - -} - -static void -ea_cal_view_event_init (EaCalViewEvent *a11y) -{ - a11y->state_set = atk_state_set_new (); - atk_state_set_add_state (a11y->state_set, ATK_STATE_TRANSIENT); - atk_state_set_add_state (a11y->state_set, ATK_STATE_ENABLED); - atk_state_set_add_state (a11y->state_set, ATK_STATE_SENSITIVE); - atk_state_set_add_state (a11y->state_set, ATK_STATE_SELECTABLE); - atk_state_set_add_state (a11y->state_set, ATK_STATE_SHOWING); - atk_state_set_add_state (a11y->state_set, ATK_STATE_FOCUSABLE); -} - -#ifdef ACC_DEBUG -static void ea_cal_view_finalize (GObject *object) -{ - G_OBJECT_CLASS (parent_class)->finalize (object); - - ++n_ea_cal_view_event_destroyed; - printf ("ACC_DEBUG: n_ea_cal_view_event_destroyed = %d\n", - n_ea_cal_view_event_destroyed); -} -#endif - -AtkObject* -ea_cal_view_event_new (GObject *obj) -{ - AtkObject *atk_obj = NULL; - GObject *target_obj; - ECalendarView *cal_view; - - g_return_val_if_fail (E_IS_TEXT (obj), NULL); - cal_view = ea_calendar_helpers_get_cal_view_from (GNOME_CANVAS_ITEM (obj)); - if (!cal_view) - return NULL; - - if (E_IS_WEEK_VIEW (cal_view)) { - gint event_num, span_num; - EWeekViewEvent *week_view_event; - EWeekViewEventSpan *event_span; - EWeekView *week_view = E_WEEK_VIEW (cal_view); - - /* for week view, we need to check if a atkobject exists for - * the first span of the same event - */ - if (!e_week_view_find_event_from_item (week_view, - GNOME_CANVAS_ITEM (obj), - &event_num, - &span_num)) - return NULL; - week_view_event = &g_array_index (week_view->events, - EWeekViewEvent, - event_num); - /* get the first span */ - event_span = &g_array_index (week_view->spans, - EWeekViewEventSpan, - week_view_event->spans_index); - target_obj = G_OBJECT (event_span->text_item); - atk_obj = g_object_get_data (target_obj, "accessible-object"); - - } - else - target_obj = obj; - - if (!atk_obj) { - static AtkRole event_role = ATK_ROLE_INVALID; - atk_obj = ATK_OBJECT (g_object_new (EA_TYPE_CAL_VIEW_EVENT, - NULL)); - atk_object_initialize (atk_obj, target_obj); - if (event_role == ATK_ROLE_INVALID) - event_role = atk_role_register ("Calendar Event"); - atk_obj->role = event_role; -#ifdef ACC_DEBUG - ++n_ea_cal_view_event_created; - printf ("ACC_DEBUG: n_ea_cal_view_event_created = %d\n", - n_ea_cal_view_event_created); -#endif - } - - /* the registered factory for E_TEXT is cannot create a EaCalViewEvent, - * we should save the EaCalViewEvent object in it. - */ - g_object_set_data (obj, "accessible-object", atk_obj); - - return atk_obj; -} - -static void -ea_cal_view_event_dispose (GObject *object) -{ - EaCalViewEvent *a11y = EA_CAL_VIEW_EVENT (object); - - if (a11y->state_set) { - g_object_unref (a11y->state_set); - a11y->state_set = NULL; - } - - if (G_OBJECT_CLASS(parent_class)->dispose) - G_OBJECT_CLASS(parent_class)->dispose (object); -} - -static G_CONST_RETURN gchar * -ea_cal_view_event_get_name (AtkObject *accessible) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - ECalendarViewEvent *event; - gchar *name_string; - const gchar *alarm_string; - const gchar *recur_string; - const gchar *meeting_string; - gchar *summary_string; - const gchar *summary; - - - g_return_val_if_fail (EA_IS_CAL_VIEW_EVENT (accessible), NULL); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj || !E_IS_TEXT (g_obj)) - return NULL; - event = ea_calendar_helpers_get_cal_view_event_from (GNOME_CANVAS_ITEM(g_obj)); - - alarm_string = recur_string = meeting_string = ""; - if (event && event->comp_data) { - if (e_cal_util_component_has_alarms (event->comp_data->icalcomp)) - alarm_string = _("It has alarms."); - - if (e_cal_util_component_has_recurrences (event->comp_data->icalcomp)) - recur_string = _("It has recurrences."); - - if (e_cal_util_component_has_organizer (event->comp_data->icalcomp)) - meeting_string = _("It is a meeting."); - - } - - summary = icalcomponent_get_summary (event->comp_data->icalcomp); - if (summary) - summary_string = g_strdup_printf (_("Calendar Event: Summary is %s."), summary); - else - summary_string = g_strdup (_("Calendar Event: It has no summary.")); - - name_string = g_strdup_printf ("%s %s %s %s", summary_string, alarm_string, recur_string, meeting_string); - g_free (summary_string); - - ATK_OBJECT_CLASS (parent_class)->set_name (accessible, name_string); -#ifdef ACC_DEBUG - printf("EvoAcc: name for event accobj=%p, is %s\n", - (gpointer)accessible, new_name); -#endif - g_free (name_string); - return accessible->name; -} - -static G_CONST_RETURN gchar * -ea_cal_view_event_get_description (AtkObject *accessible) -{ - if (accessible->description) - return accessible->description; - - return _("calendar view event"); -} - -static AtkObject * -ea_cal_view_event_get_parent (AtkObject *accessible) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - GnomeCanvasItem *canvas_item; - ECalendarView *cal_view; - - g_return_val_if_fail (EA_IS_CAL_VIEW_EVENT (accessible), NULL); - atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); - - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (g_obj == NULL) - /* Object is defunct */ - return NULL; - canvas_item = GNOME_CANVAS_ITEM (g_obj); - - cal_view = ea_calendar_helpers_get_cal_view_from (canvas_item); - - if (!cal_view) - return NULL; - - return gtk_widget_get_accessible (GTK_WIDGET (cal_view)); -} - -static gint -ea_cal_view_event_get_index_in_parent (AtkObject *accessible) -{ - GObject *g_obj; - GnomeCanvasItem *canvas_item; - ECalendarView *cal_view; - ECalendarViewEvent *cal_view_event; - - g_return_val_if_fail (EA_IS_CAL_VIEW_EVENT (accessible), -1); - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible)); - if (!g_obj) - /* defunct object*/ - return -1; - - canvas_item = GNOME_CANVAS_ITEM (g_obj); - cal_view = ea_calendar_helpers_get_cal_view_from (canvas_item); - if (!cal_view) - return -1; - - cal_view_event = ea_calendar_helpers_get_cal_view_event_from (canvas_item); - if (!cal_view_event) - return -1; - - if (E_IS_DAY_VIEW (cal_view)) { - gint day, event_num, num_before; - EDayViewEvent *day_view_event; - EDayView *day_view = E_DAY_VIEW (cal_view); - - /* the long event comes first in the order */ - for (event_num = day_view->long_events->len - 1; event_num >= 0; - --event_num) { - day_view_event = &g_array_index (day_view->long_events, - EDayViewEvent, event_num); - if (cal_view_event == (ECalendarViewEvent*)day_view_event) - return event_num; - - } - num_before = day_view->long_events->len; - - for (day = 0; day < day_view->days_shown; ++day) { - for (event_num = day_view->events[day]->len - 1; event_num >= 0; - --event_num) { - day_view_event = &g_array_index (day_view->events[day], - EDayViewEvent, event_num); - if (cal_view_event == (ECalendarViewEvent*)day_view_event) - return num_before + event_num; - } - num_before += day_view->events[day]->len; - } - } - else if (E_IS_WEEK_VIEW (cal_view)) { - AtkObject *atk_parent, *atk_child; - gint index = 0; - - atk_parent = atk_object_get_parent (accessible); - while ((atk_child = atk_object_ref_accessible_child (atk_parent, - index)) != NULL) { - if (atk_child == accessible) { - g_object_unref (atk_child); - return index; - } - g_object_unref (atk_child); - ++index; - } - } - else { - g_return_val_if_reached (-1); - } - return -1; -} - -static AtkStateSet * -ea_cal_view_event_ref_state_set (AtkObject *accessible) -{ - EaCalViewEvent *atk_event = EA_CAL_VIEW_EVENT (accessible); - - g_return_val_if_fail (atk_event->state_set, NULL); - - g_object_ref (atk_event->state_set); - - return atk_event->state_set; -} - -/* Atk Component Interface */ - -static void -atk_component_interface_init (AtkComponentIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->get_extents = ea_cal_view_get_extents; -} - -static void -ea_cal_view_get_extents (AtkComponent *component, - gint *x, - gint *y, - gint *width, - gint *height, - AtkCoordType coord_type) -{ - GObject *g_obj; - GnomeCanvasItem *canvas_item; - gint x_window, y_window; - gint scroll_x, scroll_y; - ECalendarView *cal_view; - gint item_x, item_y, item_w, item_h; - GtkWidget *canvas = NULL; - - g_return_if_fail (EA_IS_CAL_VIEW_EVENT (component)); - - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(component)); - if (!g_obj) - /* defunct object*/ - return; - g_return_if_fail (E_IS_TEXT (g_obj)); - - canvas_item = GNOME_CANVAS_ITEM (g_obj); - cal_view = ea_calendar_helpers_get_cal_view_from (canvas_item); - if (!cal_view) - return; - - if (E_IS_DAY_VIEW (cal_view)) { - gint day, event_num; - - if (!e_day_view_find_event_from_item (E_DAY_VIEW (cal_view), - canvas_item, - &day, &event_num)) - return; - if (day == E_DAY_VIEW_LONG_EVENT) { - gint start_day, end_day; - if (!e_day_view_get_long_event_position (E_DAY_VIEW (cal_view), - event_num, - &start_day, - &end_day, - &item_x, - &item_y, - &item_w, - &item_h)) - return; - canvas = E_DAY_VIEW (cal_view)->top_canvas; - } - else { - if (!e_day_view_get_event_position (E_DAY_VIEW (cal_view), day, - event_num, - &item_x, &item_y, - &item_w, &item_h)) - - return; - canvas = E_DAY_VIEW (cal_view)->main_canvas; - } - } - else if (E_IS_WEEK_VIEW (cal_view)) { - gint event_num, span_num; - if (!e_week_view_find_event_from_item (E_WEEK_VIEW (cal_view), - canvas_item, &event_num, - &span_num)) - return; - - if (!e_week_view_get_span_position (E_WEEK_VIEW (cal_view), - event_num, span_num, - &item_x, &item_y, &item_w)) - return; - item_h = E_WEEK_VIEW_ICON_HEIGHT; - canvas = E_WEEK_VIEW (cal_view)->main_canvas; - } - else - return; - - if (!canvas) - return; - - gdk_window_get_origin (canvas->window, - &x_window, &y_window); - gnome_canvas_get_scroll_offsets (GNOME_CANVAS (canvas), &scroll_x, &scroll_y); - - *x = item_x + x_window - scroll_x; - *y = item_y + y_window - scroll_y; - *width = item_w; - *height = item_h; - - if (coord_type == ATK_XY_WINDOW) { - GdkWindow *window; - gint x_toplevel, y_toplevel; - - window = gdk_window_get_toplevel (GTK_WIDGET (cal_view)->window); - gdk_window_get_origin (window, &x_toplevel, &y_toplevel); - - *x -= x_toplevel; - *y -= y_toplevel; - } - -#ifdef ACC_DEBUG - printf ("Event Bounds (%d, %d, %d, %d)\n", *x, *y, *width, *height); -#endif -} - -#define CAL_VIEW_EVENT_ACTION_NUM 1 - -static const gchar * action_name [CAL_VIEW_EVENT_ACTION_NUM] = { - N_("Grab Focus") -}; - -static void -atk_action_interface_init (AtkActionIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->do_action = ea_cal_view_event_do_action; - iface->get_n_actions = ea_cal_view_event_get_n_actions; - iface->get_name = ea_cal_view_event_action_get_name; -} - -static gboolean -ea_cal_view_event_do_action (AtkAction *action, gint i) -{ - AtkGObjectAccessible *atk_gobj; - AtkComponent *atk_comp; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (action); - - if (i == 0) { - atk_comp = (AtkComponent *)atk_gobj; - return atk_component_grab_focus (atk_comp); - } - - return FALSE; - -} - -static gint -ea_cal_view_event_get_n_actions (AtkAction *action) -{ - return CAL_VIEW_EVENT_ACTION_NUM; -} - -static G_CONST_RETURN gchar * -ea_cal_view_event_action_get_name (AtkAction *action, gint i) -{ - if (i >= 0 && i < CAL_VIEW_EVENT_ACTION_NUM) - return action_name [i]; - return NULL; -} - diff --git a/calendar/gui/a11y/ea-cal-view-event.h b/calendar/gui/a11y/ea-cal-view-event.h deleted file mode 100644 index 548e42b4a7..0000000000 --- a/calendar/gui/a11y/ea-cal-view-event.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EA_CAL_VIEW_EVENT_H__ -#define __EA_CAL_VIEW_EVENT_H__ - -#include - -G_BEGIN_DECLS - -#define EA_TYPE_CAL_VIEW_EVENT (ea_cal_view_event_get_type ()) -#define EA_CAL_VIEW_EVENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_CAL_VIEW_EVENT, EaCalViewEvent)) -#define EA_CAL_VIEW_EVENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_CAL_VIEW_EVENT, EaCalViewEventClass)) -#define EA_IS_CAL_VIEW_EVENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_CAL_VIEW_EVENT)) -#define EA_IS_CAL_VIEW_EVENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_CAL_VIEW_EVENT)) -#define EA_CAL_VIEW_EVENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_CAL_VIEW_EVENT, EaCalViewEventClass)) - -typedef struct _EaCalViewEvent EaCalViewEvent; -typedef struct _EaCalViewEventClass EaCalViewEventClass; - -struct _EaCalViewEvent -{ - AtkGObjectAccessible parent; - AtkStateSet *state_set; -}; - -GType ea_cal_view_event_get_type (void); - -struct _EaCalViewEventClass -{ - AtkGObjectAccessibleClass parent_class; -}; - -AtkObject *ea_cal_view_event_new (GObject *obj); - -G_END_DECLS - - -#endif /* __EA_CAL_VIEW_EVENT_H__ */ diff --git a/calendar/gui/a11y/ea-cal-view.c b/calendar/gui/a11y/ea-cal-view.c deleted file mode 100644 index 952afcc791..0000000000 --- a/calendar/gui/a11y/ea-cal-view.c +++ /dev/null @@ -1,426 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "ea-cal-view.h" -#include "ea-calendar-helpers.h" -#include "e-day-view.h" -#include "e-week-view.h" -#include "calendar-commands.h" -#include "goto.h" -#include -#include - -static void ea_cal_view_class_init (EaCalViewClass *klass); - -static AtkObject* ea_cal_view_get_parent (AtkObject *accessible); -static void ea_cal_view_real_initialize (AtkObject *accessible, gpointer data); - -static void ea_cal_view_event_changed_cb (ECalendarView *cal_view, - ECalendarViewEvent *event, gpointer data); -static void ea_cal_view_event_added_cb (ECalendarView *cal_view, - ECalendarViewEvent *event, gpointer data); - -static gboolean idle_dates_changed (gpointer data); -static void ea_cal_view_dates_change_cb (GnomeCalendar *gcal, gpointer data); - -static void atk_action_interface_init (AtkActionIface *iface); -static gboolean action_interface_do_action (AtkAction *action, gint i); -static gint action_interface_get_n_actions (AtkAction *action); -static G_CONST_RETURN gchar * -action_interface_get_description(AtkAction *action, gint i); -static G_CONST_RETURN gchar * -action_interface_get_keybinding (AtkAction *action, gint i); -static G_CONST_RETURN gchar * -action_interface_action_get_name(AtkAction *action, gint i); - -static gpointer parent_class = NULL; - -GType -ea_cal_view_get_type (void) -{ - static GType type = 0; - AtkObjectFactory *factory; - GTypeQuery query; - GType derived_atk_type; - - if (!type) { - static GTypeInfo tinfo = { - sizeof (EaCalViewClass), - (GBaseInitFunc) NULL, /* base init */ - (GBaseFinalizeFunc) NULL, /* base finalize */ - (GClassInitFunc) ea_cal_view_class_init, /* class init */ - (GClassFinalizeFunc) NULL, /* class finalize */ - NULL, /* class data */ - sizeof (EaCalView), /* instance size */ - 0, /* nb preallocs */ - (GInstanceInitFunc) NULL, /* instance init */ - NULL /* value table */ - }; - - static const GInterfaceInfo atk_action_info = { - (GInterfaceInitFunc) atk_action_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - /* - * Figure out the size of the class and instance - * we are run-time deriving from (GailWidget, in this case) - */ - - factory = atk_registry_get_factory (atk_get_default_registry (), - GTK_TYPE_WIDGET); - derived_atk_type = atk_object_factory_get_accessible_type (factory); - g_type_query (derived_atk_type, &query); - - tinfo.class_size = query.class_size; - tinfo.instance_size = query.instance_size; - - type = g_type_register_static (derived_atk_type, - "EaCalView", &tinfo, 0); - g_type_add_interface_static (type, ATK_TYPE_ACTION, - &atk_action_info); - } - - return type; -} - -static void -ea_cal_view_class_init (EaCalViewClass *klass) -{ - AtkObjectClass *class = ATK_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - class->get_parent = ea_cal_view_get_parent; - class->initialize = ea_cal_view_real_initialize; -} - -AtkObject* -ea_cal_view_new (GtkWidget *widget) -{ - GObject *object; - AtkObject *accessible; - - g_return_val_if_fail (E_IS_CALENDAR_VIEW (widget), NULL); - - object = g_object_new (EA_TYPE_CAL_VIEW, NULL); - - accessible = ATK_OBJECT (object); - atk_object_initialize (accessible, widget); - - return accessible; -} - -static void -ea_cal_view_real_initialize (AtkObject *accessible, gpointer data) -{ - ECalendarView *cal_view; - GnomeCalendar *gcal; - static AtkRole role = ATK_ROLE_INVALID; - - g_return_if_fail (EA_IS_CAL_VIEW (accessible)); - g_return_if_fail (E_IS_CALENDAR_VIEW (data)); - - ATK_OBJECT_CLASS (parent_class)->initialize (accessible, data); - if (role == ATK_ROLE_INVALID) - role = atk_role_register ("Calendar View"); - accessible->role = role; - cal_view = E_CALENDAR_VIEW (data); - - /* add listener for event_changed, event_added - * we don't need to listen on event_removed. When the e_text - * of the event is removed, the cal_view_event will go to the state - * of "defunct" (changed by weak ref callback of atkgobjectaccessible - */ - g_signal_connect (G_OBJECT(cal_view), "event_changed", - G_CALLBACK (ea_cal_view_event_changed_cb), NULL); - g_signal_connect (G_OBJECT(cal_view), "event_added", - G_CALLBACK (ea_cal_view_event_added_cb), NULL); - - /* listen for date changes of calendar */ - gcal = e_calendar_view_get_calendar (cal_view); - - if (gcal) - g_signal_connect (gcal, "dates_shown_changed", - G_CALLBACK (ea_cal_view_dates_change_cb), - accessible); -} - -static AtkObject* -ea_cal_view_get_parent (AtkObject *accessible) -{ - ECalendarView *cal_view; - GnomeCalendar *gnomeCalendar; - - g_return_val_if_fail (EA_IS_CAL_VIEW (accessible), NULL); - - if (!GTK_ACCESSIBLE (accessible)->widget) - return NULL; - cal_view = E_CALENDAR_VIEW (GTK_ACCESSIBLE (accessible)->widget); - - gnomeCalendar = e_calendar_view_get_calendar (cal_view); - - return gtk_widget_get_accessible (GTK_WIDGET(gnomeCalendar)); -} - -static void -ea_cal_view_event_changed_cb (ECalendarView *cal_view, ECalendarViewEvent *event, - gpointer data) -{ - AtkObject *atk_obj; - AtkObject *event_atk_obj = NULL; - - g_return_if_fail (E_IS_CALENDAR_VIEW (cal_view)); - - atk_obj = gtk_widget_get_accessible (GTK_WIDGET(cal_view)); - if (!EA_IS_CAL_VIEW (atk_obj)) - return; - - if ((E_IS_DAY_VIEW (cal_view)) && event && event->canvas_item) { - event_atk_obj = - ea_calendar_helpers_get_accessible_for (event->canvas_item); - } - else if ((E_IS_WEEK_VIEW (cal_view)) && event) { - EWeekViewEventSpan *span; - EWeekViewEvent *week_view_event = (EWeekViewEvent *)event; - EWeekView *week_view = E_WEEK_VIEW (cal_view); - /* get the first span of the event */ - span = &g_array_index (week_view->spans, EWeekViewEventSpan, - week_view_event->spans_index); - if (span && span->text_item) - event_atk_obj = ea_calendar_helpers_get_accessible_for (span->text_item); - } - if (event_atk_obj) { -#ifdef ACC_DEBUG - printf ("AccDebug: event=%p changed\n", (gpointer)event); -#endif - g_object_notify (G_OBJECT(event_atk_obj), "accessible-name"); - g_signal_emit_by_name (event_atk_obj, "visible_data_changed"); - } - -} - -static void -ea_cal_view_event_added_cb (ECalendarView *cal_view, ECalendarViewEvent *event, - gpointer data) -{ - AtkObject *atk_obj; - AtkObject *event_atk_obj = NULL; - gint index; - - g_return_if_fail (E_IS_CALENDAR_VIEW (cal_view)); - - atk_obj = gtk_widget_get_accessible (GTK_WIDGET(cal_view)); - if (!EA_IS_CAL_VIEW (atk_obj)) - return; - - if ((E_IS_DAY_VIEW (cal_view)) && event && event->canvas_item) { - event_atk_obj = - ea_calendar_helpers_get_accessible_for (event->canvas_item); - } - else if ((E_IS_WEEK_VIEW (cal_view)) && event) { - EWeekViewEventSpan *span; - EWeekViewEvent *week_view_event = (EWeekViewEvent *)event; - EWeekView *week_view = E_WEEK_VIEW (cal_view); - /* get the first span of the event */ - span = &g_array_index (week_view->spans, EWeekViewEventSpan, - week_view_event->spans_index); - if (span && span->text_item) - event_atk_obj = ea_calendar_helpers_get_accessible_for (span->text_item); - - } - if (event_atk_obj) { - index = atk_object_get_index_in_parent (event_atk_obj); - if (index < 0) - return; -#ifdef ACC_DEBUG - printf ("AccDebug: event=%p added\n", (gpointer)event); -#endif - g_signal_emit_by_name (atk_obj, "children_changed::add", - index, event_atk_obj, NULL); - } -} - -static gboolean -idle_dates_changed (gpointer data) -{ - AtkObject *ea_cal_view; - - g_return_val_if_fail (data, FALSE); - g_return_val_if_fail (EA_IS_CAL_VIEW (data), FALSE); - - ea_cal_view = ATK_OBJECT(data); - - if (ea_cal_view->name) { - g_free (ea_cal_view->name); - ea_cal_view->name = NULL; - } - g_object_notify (G_OBJECT (ea_cal_view), "accessible-name"); - g_signal_emit_by_name (ea_cal_view, "visible_data_changed"); - g_signal_emit_by_name (ea_cal_view, "children_changed", NULL, NULL, NULL); -#ifdef ACC_DEBUG - printf ("AccDebug: cal view date changed\n"); -#endif - - return FALSE; -} - -static void -ea_cal_view_dates_change_cb (GnomeCalendar *gcal, gpointer data) -{ - g_idle_add (idle_dates_changed, data); -} - -/* atk action interface */ - -#define CAL_VIEW_ACTION_NUM 5 - -static const gchar * action_name [CAL_VIEW_ACTION_NUM] = { - N_("New Appointment"), - N_("New All Day Event"), - N_("New Meeting"), - N_("Go to Today"), - N_("Go to Date") -}; - -static void -atk_action_interface_init (AtkActionIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->do_action = action_interface_do_action; - iface->get_n_actions = action_interface_get_n_actions; - iface->get_description = action_interface_get_description; - iface->get_keybinding = action_interface_get_keybinding; - iface->get_name = action_interface_action_get_name; -} - -static gboolean -action_interface_do_action (AtkAction *action, gint index) -{ - GtkWidget *widget; - gboolean return_value = TRUE; - time_t dtstart, dtend; - ECalendarView *cal_view; - - widget = GTK_ACCESSIBLE (action)->widget; - if (widget == NULL) - /* - * State is defunct - */ - return FALSE; - - if (!GTK_WIDGET_IS_SENSITIVE (widget) || !GTK_WIDGET_VISIBLE (widget)) - return FALSE; - - cal_view = E_CALENDAR_VIEW (widget); - switch (index) { - case 0: - /* New Appointment */ - e_calendar_view_new_appointment (cal_view); - break; - case 1: - /* New All Day Event */ - e_calendar_view_get_selected_time_range (cal_view, - &dtstart, &dtend); - e_calendar_view_new_appointment_for (cal_view, - dtstart, dtend, TRUE, FALSE); - break; - case 2: - /* New Meeting */ - e_calendar_view_get_selected_time_range (cal_view, - &dtstart, &dtend); - e_calendar_view_new_appointment_for (cal_view, - dtstart, dtend, FALSE, TRUE); - break; - case 3: - /* Go to today */ - break; - calendar_goto_today (e_calendar_view_get_calendar (cal_view)); - case 4: - /* Go to date */ - goto_dialog (e_calendar_view_get_calendar (cal_view)); - break; - default: - return_value = FALSE; - break; - } - return return_value; -} - -static gint -action_interface_get_n_actions (AtkAction *action) -{ - return CAL_VIEW_ACTION_NUM; -} - -static G_CONST_RETURN gchar * -action_interface_get_description(AtkAction *action, gint index) -{ - return action_interface_action_get_name (action, index); -} - -static G_CONST_RETURN gchar * -action_interface_get_keybinding (AtkAction *action, gint index) -{ - GtkWidget *widget; - - widget = GTK_ACCESSIBLE (action)->widget; - if (widget == NULL) - /* - * State is defunct - */ - return NULL; - - if (!GTK_WIDGET_IS_SENSITIVE (widget) || !GTK_WIDGET_VISIBLE (widget)) - return NULL; - - switch (index) { - case 0: - /* New Appointment */ - return "fna;n"; - case 1: - /* New Event */ - return "fnd;d"; - case 2: - /* New Meeting */ - return "fne;e"; - case 3: - /* Go to today */ - return "vt;t"; - case 4: - /* Go to date */ - return "vd;g"; - default: - break; - } - return NULL; -} - -static G_CONST_RETURN gchar * -action_interface_action_get_name(AtkAction *action, gint i) -{ - if (i >= 0 && i < CAL_VIEW_ACTION_NUM) - return action_name [i]; - return NULL; -} diff --git a/calendar/gui/a11y/ea-cal-view.h b/calendar/gui/a11y/ea-cal-view.h deleted file mode 100644 index 959f7816b5..0000000000 --- a/calendar/gui/a11y/ea-cal-view.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EA_CAL_VIEW_H__ -#define __EA_CAL_VIEW_H__ - -#include -#include "e-calendar-view.h" - -G_BEGIN_DECLS - -#define EA_TYPE_CAL_VIEW (ea_cal_view_get_type ()) -#define EA_CAL_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_CAL_VIEW, EaCalView)) -#define EA_CAL_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_CAL_VIEW, EaCalViewClass)) -#define EA_IS_CAL_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_CAL_VIEW)) -#define EA_IS_CAL_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_CAL_VIEW)) -#define EA_CAL_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_CAL_VIEW, EaCalViewClass)) - -typedef struct _EaCalView EaCalView; -typedef struct _EaCalViewClass EaCalViewClass; - -struct _EaCalView -{ - GtkAccessible parent; -}; - -GType ea_cal_view_get_type (void); - -struct _EaCalViewClass -{ - GtkAccessibleClass parent_class; -}; - -AtkObject* ea_cal_view_new (GtkWidget *widget); - -G_END_DECLS - -#endif /* __EA_CAL_VIEW_H__ */ diff --git a/calendar/gui/a11y/ea-calendar-helpers.c b/calendar/gui/a11y/ea-calendar-helpers.c deleted file mode 100644 index f07cdfa086..0000000000 --- a/calendar/gui/a11y/ea-calendar-helpers.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "ea-calendar-helpers.h" -#include "ea-cal-view-event.h" -#include "ea-jump-button.h" -#include "e-day-view.h" -#include "e-week-view.h" - -#include -#include - -/** - * ea_calendar_helpers_get_accessible_for - * @canvas_item: the canvas item for a event or a jump button - * @returns: the atk object for the canvas_item - * - **/ -AtkObject * -ea_calendar_helpers_get_accessible_for (GnomeCanvasItem *canvas_item) -{ - AtkObject *atk_obj = NULL; - GObject *g_obj; - - g_return_val_if_fail ((E_IS_TEXT (canvas_item)) || (GNOME_IS_CANVAS_ITEM (canvas_item)), NULL);; - - g_obj = G_OBJECT (canvas_item); - /* we cannot use atk_gobject_accessible_for_object here, - * EaDayViewEvent/EaWeekViewEvent cannot be created by the - * registered facotry of E_TEXT - */ - atk_obj = g_object_get_data (g_obj, "accessible-object"); - if (!atk_obj) { - if (E_IS_TEXT (canvas_item)) { - atk_obj = ea_cal_view_event_new (g_obj); - } - else if (GNOME_IS_CANVAS_PIXBUF(canvas_item)) { - atk_obj = ea_jump_button_new (g_obj); - } - else - return NULL; - } - return atk_obj; -} - -/** - * ea_calendar_helpers_get_view_widget_from: - * @canvas_item: the canvas item for a event or a jump button - * @returns: the cal view widget if exists - * - * Get the cal view widget contains the canvas_item. - * - **/ -ECalendarView * -ea_calendar_helpers_get_cal_view_from (GnomeCanvasItem *canvas_item) -{ - GnomeCanvas *canvas; - GtkWidget *view_widget = NULL; - - g_return_val_if_fail (canvas_item, NULL); - g_return_val_if_fail ((E_IS_TEXT (canvas_item)) || (GNOME_IS_CANVAS_ITEM (canvas_item)), NULL); - - /* canvas_item is the e_text for the event */ - /* canvas_item->canvas is the ECanvas for day view */ - /* parent of canvas_item->canvas is the EDayView or EWeekView widget */ - canvas = canvas_item->canvas; - view_widget = gtk_widget_get_parent (GTK_WIDGET(canvas)); - if (!view_widget || !E_IS_CALENDAR_VIEW (view_widget)) - return NULL; - - return E_CALENDAR_VIEW (view_widget); -} - -/** - * ea_calendar_helpers_get_cal_view_event_from - * @canvas_item: the cavas_item (e_text) for the event - * @returns: the ECalendarViewEvent - * - * Get the ECalendarViewEvent for the canvas_item. - * - **/ -ECalendarViewEvent * -ea_calendar_helpers_get_cal_view_event_from (GnomeCanvasItem *canvas_item) -{ - ECalendarView *cal_view; - gboolean event_found; - ECalendarViewEvent *cal_view_event; - - g_return_val_if_fail (E_IS_TEXT (canvas_item), NULL); - - cal_view = ea_calendar_helpers_get_cal_view_from (canvas_item); - - if (!cal_view) - return NULL; - - if (E_IS_DAY_VIEW (cal_view)) { - gint event_day, event_num; - EDayViewEvent *day_view_event; - EDayView *day_view = E_DAY_VIEW (cal_view); - event_found = e_day_view_find_event_from_item (day_view, canvas_item, - &event_day, &event_num); - if (!event_found) - return NULL; - if (event_day == E_DAY_VIEW_LONG_EVENT) { - /* a long event */ - day_view_event = &g_array_index (day_view->long_events, - EDayViewEvent, event_num); - } - else { - /* a main canvas event */ - day_view_event = &g_array_index (day_view->events[event_day], - EDayViewEvent, event_num); - } - cal_view_event = (ECalendarViewEvent *) day_view_event; - } - else if (E_IS_WEEK_VIEW (cal_view)) { - gint event_num, span_num; - EWeekViewEvent *week_view_event; - EWeekView *week_view = E_WEEK_VIEW (cal_view); - event_found = e_week_view_find_event_from_item (week_view, - canvas_item, - &event_num, - &span_num); - if (!event_found) - return NULL; - - week_view_event = &g_array_index (week_view->events, EWeekViewEvent, - event_num); - - cal_view_event = (ECalendarViewEvent *)week_view_event; - } - else { - g_return_val_if_reached (NULL); - } - return cal_view_event; -} diff --git a/calendar/gui/a11y/ea-calendar-helpers.h b/calendar/gui/a11y/ea-calendar-helpers.h deleted file mode 100644 index a4045cd7af..0000000000 --- a/calendar/gui/a11y/ea-calendar-helpers.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -/* Evolution Accessibility - */ - -#ifndef _EA_CALENDAR_HELPERS_H__ -#define _EA_CALENDAR_HELPERS_H__ - -#include "ea-cal-view.h" - -AtkObject * -ea_calendar_helpers_get_accessible_for (GnomeCanvasItem *canvas_item); - -ECalendarView * -ea_calendar_helpers_get_cal_view_from (GnomeCanvasItem *canvas_item); - -ECalendarViewEvent * -ea_calendar_helpers_get_cal_view_event_from (GnomeCanvasItem *canvas_item); - -#endif /* _EA_CALENDAR_HELPERS_H__ */ diff --git a/calendar/gui/a11y/ea-calendar.c b/calendar/gui/a11y/ea-calendar.c deleted file mode 100644 index d09efae4d2..0000000000 --- a/calendar/gui/a11y/ea-calendar.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include -#include -#include "ea-calendar-helpers.h" -#include "a11y/ea-factory.h" -#include "ea-calendar.h" - -#include "calendar/ea-cal-view.h" -#include "calendar/ea-cal-view-event.h" -#include "calendar/ea-day-view.h" -#include "calendar/ea-day-view-main-item.h" -#include "calendar/ea-week-view.h" -#include "calendar/ea-week-view-main-item.h" -#include "calendar/ea-gnome-calendar.h" - - -EA_FACTORY (EA_TYPE_CAL_VIEW, ea_cal_view, ea_cal_view_new) -EA_FACTORY (EA_TYPE_DAY_VIEW, ea_day_view, ea_day_view_new) -EA_FACTORY_GOBJECT (EA_TYPE_DAY_VIEW_MAIN_ITEM, ea_day_view_main_item, ea_day_view_main_item_new) -EA_FACTORY (EA_TYPE_WEEK_VIEW, ea_week_view, ea_week_view_new) -EA_FACTORY_GOBJECT (EA_TYPE_WEEK_VIEW_MAIN_ITEM, ea_week_view_main_item, ea_week_view_main_item_new) -EA_FACTORY (EA_TYPE_GNOME_CALENDAR, ea_gnome_calendar, ea_gnome_calendar_new) - -static gboolean ea_calendar_focus_watcher (GSignalInvocationHint *ihint, - guint n_param_values, - const GValue *param_values, - gpointer data); - -static gpointer e_text_type, pixbuf_type, e_day_view_type, e_week_view_type; -static gpointer e_day_view_main_item_type, e_week_view_main_item_type; - -void -gnome_calendar_a11y_init (void) -{ - /* we only add focus watcher when accessibility is enabled - */ - if (atk_get_root ()) { - EA_SET_FACTORY (gnome_calendar_get_type(), ea_gnome_calendar); - - /* force loading some types */ - e_text_type = g_type_class_ref (E_TYPE_TEXT); - pixbuf_type = g_type_class_ref (GNOME_TYPE_CANVAS_PIXBUF); - e_day_view_type = g_type_class_ref (e_day_view_get_type ()); - e_week_view_type = g_type_class_ref (e_week_view_get_type ()); - e_day_view_main_item_type = g_type_class_ref (e_day_view_main_item_get_type ()); - e_week_view_main_item_type = g_type_class_ref (e_week_view_main_item_get_type ()); - - g_signal_add_emission_hook (g_signal_lookup ("event", E_TYPE_TEXT), - 0, ea_calendar_focus_watcher, - NULL, (GDestroyNotify) NULL); - g_signal_add_emission_hook (g_signal_lookup ("event", GNOME_TYPE_CANVAS_PIXBUF), - 0, ea_calendar_focus_watcher, - NULL, (GDestroyNotify) NULL); - g_signal_add_emission_hook (g_signal_lookup ("event-after", - e_day_view_get_type()), - 0, ea_calendar_focus_watcher, - NULL, (GDestroyNotify) NULL); - g_signal_add_emission_hook (g_signal_lookup ("event", - e_day_view_main_item_get_type()), - 0, ea_calendar_focus_watcher, - NULL, (GDestroyNotify) NULL); - g_signal_add_emission_hook (g_signal_lookup ("event-after", - e_week_view_get_type()), - 0, ea_calendar_focus_watcher, - NULL, (GDestroyNotify) NULL); - g_signal_add_emission_hook (g_signal_lookup ("event", - e_week_view_main_item_get_type()), - 0, ea_calendar_focus_watcher, - NULL, (GDestroyNotify) NULL); - - } -} - -void -e_cal_view_a11y_init (void) -{ - EA_SET_FACTORY (e_calendar_view_get_type(), ea_cal_view); -} - -void -e_day_view_a11y_init (void) -{ - EA_SET_FACTORY (e_day_view_get_type(), ea_day_view); -} - -void -e_day_view_main_item_a11y_init (void) -{ - EA_SET_FACTORY (e_day_view_main_item_get_type (), ea_day_view_main_item); -} - -void -e_week_view_a11y_init (void) -{ - EA_SET_FACTORY (e_week_view_get_type(), ea_week_view); -} - -void -e_week_view_main_item_a11y_init (void) -{ - EA_SET_FACTORY (e_week_view_main_item_get_type (), ea_week_view_main_item); -} - -static gboolean -ea_calendar_focus_watcher (GSignalInvocationHint *ihint, - guint n_param_values, - const GValue *param_values, - gpointer data) -{ - GObject *object; - GdkEvent *event; - AtkObject *ea_event = NULL; - - object = g_value_get_object (param_values + 0); - event = g_value_get_boxed (param_values + 1); - - if ((E_IS_TEXT (object)) || (GNOME_IS_CANVAS_PIXBUF (object))) { - /* "event" signal on canvas item - */ - GnomeCanvasItem *canvas_item; - - canvas_item = GNOME_CANVAS_ITEM (object); - if (event->type == GDK_FOCUS_CHANGE) { - if (event->focus_change.in) { - ea_event = - ea_calendar_helpers_get_accessible_for (canvas_item); - if (!ea_event) - /* not canvas item we want */ - return TRUE; - - } - atk_focus_tracker_notify (ea_event); - } - } - else if (E_IS_DAY_VIEW (object)) { - EDayView *day_view = E_DAY_VIEW (object); - if (event->type == GDK_FOCUS_CHANGE) { - if (event->focus_change.in) { - /* give main item chance to emit focus */ - gnome_canvas_item_grab_focus (day_view->main_canvas_item); - } - } - } - else if (E_IS_DAY_VIEW_MAIN_ITEM (object)) { - if (event->type == GDK_FOCUS_CHANGE) { - if (event->focus_change.in) { - /* we should emit focus on main item */ - ea_event = atk_gobject_accessible_for_object (object); - } - else - /* focus out */ - ea_event = NULL; -#ifdef ACC_DEBUG - printf ("EvoAcc: focus notify on day main item %p\n", (gpointer)object); -#endif - atk_focus_tracker_notify (ea_event); - } - } else if (E_IS_WEEK_VIEW (object)) { - EWeekView *week_view = E_WEEK_VIEW (object); - if (event->type == GDK_FOCUS_CHANGE) { - if (event->focus_change.in) { - /* give main item chance to emit focus */ - gnome_canvas_item_grab_focus (week_view->main_canvas_item); - } - } - } - else if (E_IS_WEEK_VIEW_MAIN_ITEM (object)) { - if (event->type == GDK_FOCUS_CHANGE) { - if (event->focus_change.in) { - /* we should emit focus on main item */ - ea_event = atk_gobject_accessible_for_object (object); - } - else - /* focus out */ - ea_event = NULL; -#ifdef ACC_DEBUG - printf ("EvoAcc: focus notify on week main item %p\n", (gpointer)object); -#endif - atk_focus_tracker_notify (ea_event); - } - } - return TRUE; -} diff --git a/calendar/gui/a11y/ea-calendar.h b/calendar/gui/a11y/ea-calendar.h deleted file mode 100644 index b2238ffdbc..0000000000 --- a/calendar/gui/a11y/ea-calendar.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -/* Evolution Accessibility -*/ - -#ifndef _EA_CALENDAR_H__ -#define _EA_CALENDAR_H__ - -void gnome_calendar_a11y_init (void); -void e_cal_view_a11y_init (void); -void e_day_view_a11y_init (void); -void e_day_view_main_item_a11y_init (void); -void e_week_view_a11y_init (void); -void e_week_view_main_item_a11y_init (void); - -#endif /* _EA_CALENDAR_H__ */ diff --git a/calendar/gui/a11y/ea-day-view-cell.c b/calendar/gui/a11y/ea-day-view-cell.c deleted file mode 100644 index fa491e87ea..0000000000 --- a/calendar/gui/a11y/ea-day-view-cell.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "ea-day-view-cell.h" -#include "ea-day-view-main-item.h" -#include "ea-day-view.h" -#include "a11y/ea-factory.h" - -/* EDayViewCell */ - -static void e_day_view_cell_class_init (EDayViewCellClass *class); - -EA_FACTORY_GOBJECT (EA_TYPE_DAY_VIEW_CELL, ea_day_view_cell, ea_day_view_cell_new) - -GType -e_day_view_cell_get_type (void) -{ - static GType type = 0; - - if (!type) { - static GTypeInfo tinfo = { - sizeof (EDayViewCellClass), - (GBaseInitFunc) NULL, /* base init */ - (GBaseFinalizeFunc) NULL, /* base finalize */ - (GClassInitFunc) e_day_view_cell_class_init, /* class init */ - (GClassFinalizeFunc) NULL, /* class finalize */ - NULL, /* class data */ - sizeof (EDayViewCell), /* instance size */ - 0, /* nb preallocs */ - (GInstanceInitFunc) NULL, /* instance init */ - NULL /* value table */ - }; - - type = g_type_register_static (G_TYPE_OBJECT, - "EDayViewCell", &tinfo, 0); - } - - return type; -} - -static void -e_day_view_cell_class_init (EDayViewCellClass *class) -{ - EA_SET_FACTORY (e_day_view_cell_get_type (), ea_day_view_cell); -} - -EDayViewCell * -e_day_view_cell_new (EDayView *day_view, gint row, gint column) -{ - GObject *object; - EDayViewCell *cell; - - g_return_val_if_fail (E_IS_DAY_VIEW (day_view), NULL); - - object = g_object_new (E_TYPE_DAY_VIEW_CELL, NULL); - cell = E_DAY_VIEW_CELL (object); - cell->day_view = day_view; - cell->row = row; - cell->column = column; - -#ifdef ACC_DEBUG - printf ("EvoAcc: e_day_view_cell created %p\n", (gpointer)cell); -#endif - - return cell; -} - -/* EaDayViewCell */ - -static void ea_day_view_cell_class_init (EaDayViewCellClass *klass); - -static G_CONST_RETURN gchar * ea_day_view_cell_get_name (AtkObject *accessible); -static G_CONST_RETURN gchar * ea_day_view_cell_get_description (AtkObject *accessible); -static AtkStateSet* ea_day_view_cell_ref_state_set (AtkObject *obj); -static AtkObject * ea_day_view_cell_get_parent (AtkObject *accessible); -static gint ea_day_view_cell_get_index_in_parent (AtkObject *accessible); - -/* component interface */ -static void atk_component_interface_init (AtkComponentIface *iface); -static void component_interface_get_extents (AtkComponent *component, - gint *x, gint *y, - gint *width, gint *height, - AtkCoordType coord_type); -static gboolean component_interface_grab_focus (AtkComponent *component); - -static gpointer parent_class = NULL; - -#ifdef ACC_DEBUG -static gint n_ea_day_view_cell_created = 0, n_ea_day_view_cell_destroyed = 0; -static void ea_day_view_cell_finalize (GObject *object); -#endif - -GType -ea_day_view_cell_get_type (void) -{ - static GType type = 0; - - if (!type) { - static GTypeInfo tinfo = { - sizeof (EaDayViewCellClass), - (GBaseInitFunc) NULL, /* base init */ - (GBaseFinalizeFunc) NULL, /* base finalize */ - (GClassInitFunc) ea_day_view_cell_class_init, /* class init */ - (GClassFinalizeFunc) NULL, /* class finalize */ - NULL, /* class data */ - sizeof (EaDayViewCell), /* instance size */ - 0, /* nb preallocs */ - (GInstanceInitFunc) NULL, /* instance init */ - NULL /* value table */ - }; - - static const GInterfaceInfo atk_component_info = { - (GInterfaceInitFunc) atk_component_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - type = g_type_register_static (ATK_TYPE_GOBJECT_ACCESSIBLE, - "EaDayViewCell", &tinfo, 0); - g_type_add_interface_static (type, ATK_TYPE_COMPONENT, - &atk_component_info); - } - - return type; -} - -static void -ea_day_view_cell_class_init (EaDayViewCellClass *klass) -{ - AtkObjectClass *class = ATK_OBJECT_CLASS (klass); - -#ifdef ACC_DEBUG - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = ea_day_view_cell_finalize; -#endif - - parent_class = g_type_class_peek_parent (klass); - - class->get_name = ea_day_view_cell_get_name; - class->get_description = ea_day_view_cell_get_description; - class->ref_state_set = ea_day_view_cell_ref_state_set; - - class->get_parent = ea_day_view_cell_get_parent; - class->get_index_in_parent = ea_day_view_cell_get_index_in_parent; -} - -AtkObject* -ea_day_view_cell_new (GObject *obj) -{ - gpointer object; - AtkObject *atk_object; - - g_return_val_if_fail (E_IS_DAY_VIEW_CELL (obj), NULL); - - object = g_object_new (EA_TYPE_DAY_VIEW_CELL, NULL); - atk_object = ATK_OBJECT (object); - atk_object_initialize (atk_object, obj); - atk_object->role = ATK_ROLE_UNKNOWN; - -#ifdef ACC_DEBUG - ++n_ea_day_view_cell_created; - printf ("ACC_DEBUG: n_ea_day_view_cell_created = %d\n", - n_ea_day_view_cell_created); -#endif - return atk_object; -} - -#ifdef ACC_DEBUG -static void ea_day_view_cell_finalize (GObject *object) -{ - G_OBJECT_CLASS (parent_class)->finalize (object); - - ++n_ea_day_view_cell_destroyed; - printf ("ACC_DEBUG: n_ea_day_view_cell_destroyed = %d\n", - n_ea_day_view_cell_destroyed); -} -#endif - -static G_CONST_RETURN gchar * -ea_day_view_cell_get_name (AtkObject *accessible) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewCell *cell; - - g_return_val_if_fail (EA_IS_DAY_VIEW_CELL (accessible), NULL); - - if (!accessible->name) { - AtkObject *ea_main_item; - GnomeCanvasItem *main_item; - gchar *new_name = g_strdup (""); - const gchar *row_label, *column_label; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return NULL; - - cell = E_DAY_VIEW_CELL (g_obj); - main_item = cell->day_view->main_canvas_item; - ea_main_item = atk_gobject_accessible_for_object (G_OBJECT (main_item)); - column_label = atk_table_get_column_description (ATK_TABLE (ea_main_item), - cell->column); - row_label = atk_table_get_row_description (ATK_TABLE (ea_main_item), - cell->row); - new_name = g_strconcat (column_label, " ", row_label, NULL); - ATK_OBJECT_CLASS (parent_class)->set_name (accessible, new_name); - g_free (new_name); - } - return accessible->name; -} - -static G_CONST_RETURN gchar * -ea_day_view_cell_get_description (AtkObject *accessible) -{ - return ea_day_view_cell_get_name (accessible); -} - -static AtkStateSet* -ea_day_view_cell_ref_state_set (AtkObject *obj) -{ - AtkStateSet *state_set; - GObject *g_obj; - AtkObject *parent; - gint x, y, width, height; - gint parent_x, parent_y, parent_width, parent_height; - - state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (obj); - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(obj)); - if (!g_obj) - return state_set; - - atk_state_set_add_state (state_set, ATK_STATE_SELECTABLE); - - parent = atk_object_get_parent (obj); - atk_component_get_extents (ATK_COMPONENT (obj), &x, &y, - &width, &height, ATK_XY_WINDOW); - atk_component_get_extents (ATK_COMPONENT (parent), &parent_x, &parent_y, - &parent_width, &parent_height, ATK_XY_WINDOW); - - - if (x + width < parent_x || x > parent_x + parent_width || - y + height < parent_y || y > parent_y + parent_height) - /* the cell is out of the main canvas */ - ; - else - atk_state_set_add_state (state_set, ATK_STATE_VISIBLE); - - return state_set; -} - -static AtkObject * -ea_day_view_cell_get_parent (AtkObject *accessible) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewCell *cell; - - g_return_val_if_fail (EA_IS_DAY_VIEW_CELL (accessible), NULL); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return NULL; - - cell = E_DAY_VIEW_CELL (g_obj); - return atk_gobject_accessible_for_object (G_OBJECT (cell->day_view->main_canvas_item)); -} - -static gint -ea_day_view_cell_get_index_in_parent (AtkObject *accessible) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewCell *cell; - AtkObject *parent; - - g_return_val_if_fail (EA_IS_DAY_VIEW_CELL (accessible), -1); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - cell = E_DAY_VIEW_CELL (g_obj); - parent = atk_object_get_parent (accessible); - return atk_table_get_index_at (ATK_TABLE (parent), - cell->row, cell->column); -} - -/* Atk Component Interface */ - -static void -atk_component_interface_init (AtkComponentIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->get_extents = component_interface_get_extents; - iface->grab_focus = component_interface_grab_focus; -} - -static void -component_interface_get_extents (AtkComponent *component, - gint *x, gint *y, gint *width, gint *height, - AtkCoordType coord_type) -{ - GObject *g_obj; - AtkObject *atk_obj; - EDayViewCell *cell; - EDayView *day_view; - GtkWidget *main_canvas; - gint day_view_width, day_view_height; - gint scroll_x, scroll_y; - - *x = *y = *width = *height = 0; - - g_return_if_fail (EA_IS_DAY_VIEW_CELL (component)); - - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(component)); - if (!g_obj) - /* defunct object*/ - return; - - cell = E_DAY_VIEW_CELL (g_obj); - day_view = cell->day_view; - main_canvas = cell->day_view->main_canvas; - - atk_obj = atk_gobject_accessible_for_object (G_OBJECT (main_canvas)); - atk_component_get_extents (ATK_COMPONENT (atk_obj), - x, y, - &day_view_width, &day_view_height, - coord_type); - gnome_canvas_get_scroll_offsets (GNOME_CANVAS (day_view->main_canvas), - &scroll_x, &scroll_y); - *x += day_view->day_offsets[cell->column] - scroll_x; - *y += day_view->row_height * cell->row - - scroll_y; - *width = day_view->day_widths[cell->column]; - *height = day_view->row_height; -} - -static gboolean -component_interface_grab_focus (AtkComponent *comp) -{ - GObject *g_obj; - EDayViewCell *cell; - EDayView *day_view; - GtkWidget *toplevel; - - g_return_val_if_fail (EA_IS_DAY_VIEW_CELL (comp), FALSE); - - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (comp)); - if (!g_obj) - return FALSE; - - cell = E_DAY_VIEW_CELL (g_obj); - day_view = cell->day_view; - - day_view->selection_start_day = cell->column; - day_view->selection_end_day = cell->column; - day_view->selection_start_row = cell->row; - day_view->selection_end_row = cell->row; - - e_day_view_ensure_rows_visible (day_view, - day_view->selection_start_row, - day_view->selection_end_row); - e_day_view_update_calendar_selection_time (day_view); - gtk_widget_queue_draw (day_view->main_canvas); - - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (day_view)); - if (GTK_WIDGET_TOPLEVEL (toplevel)) - gtk_window_present (GTK_WINDOW (toplevel)); - - return TRUE; -} - diff --git a/calendar/gui/a11y/ea-day-view-cell.h b/calendar/gui/a11y/ea-day-view-cell.h deleted file mode 100644 index 669fb1abae..0000000000 --- a/calendar/gui/a11y/ea-day-view-cell.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EA_DAY_VIEW_CELL_H__ -#define __EA_DAY_VIEW_CELL_H__ - -#include -#include "e-day-view.h" - -G_BEGIN_DECLS - -#define E_TYPE_DAY_VIEW_CELL (e_day_view_cell_get_type ()) -#define E_DAY_VIEW_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_DAY_VIEW_CELL, EDayViewCell)) -#define E_DAY_VIEW_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_DAY_VIEW_CELL, EDayViewCellClass)) -#define E_IS_DAY_VIEW_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_DAY_VIEW_CELL)) -#define E_IS_DAY_VIEW_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_DAY_VIEW_CELL)) -#define E_DAY_VIEW_CELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_DAY_VIEW_CELL, EDayViewCellClass)) - -typedef struct _EDayViewCell EDayViewCell; -typedef struct _EDayViewCellClass EDayViewCellClass; - -struct _EDayViewCell -{ - GObject parent; - EDayView *day_view; - gint row; - gint column; -}; - -GType e_day_view_cell_get_type (void); - -struct _EDayViewCellClass -{ - GObjectClass parent_class; -}; - -EDayViewCell * e_day_view_cell_new (EDayView *day_view, gint row, gint column); - -#define EA_TYPE_DAY_VIEW_CELL (ea_day_view_cell_get_type ()) -#define EA_DAY_VIEW_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_DAY_VIEW_CELL, EaDayViewCell)) -#define EA_DAY_VIEW_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_DAY_VIEW_CELL, EaDayViewCellClass)) -#define EA_IS_DAY_VIEW_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_DAY_VIEW_CELL)) -#define EA_IS_DAY_VIEW_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_DAY_VIEW_CELL)) -#define EA_DAY_VIEW_CELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_DAY_VIEW_CELL, EaDayViewCellClass)) - -typedef struct _EaDayViewCell EaDayViewCell; -typedef struct _EaDayViewCellClass EaDayViewCellClass; - -struct _EaDayViewCell -{ - AtkGObjectAccessible parent; -}; - -GType ea_day_view_cell_get_type (void); - -struct _EaDayViewCellClass -{ - AtkGObjectAccessibleClass parent_class; -}; - -AtkObject* ea_day_view_cell_new (GObject *gobj); - -G_END_DECLS - -#endif /* __EA_DAY_VIEW_CELL_H__ */ diff --git a/calendar/gui/a11y/ea-day-view-main-item.c b/calendar/gui/a11y/ea-day-view-main-item.c deleted file mode 100644 index 3bfd56f0b3..0000000000 --- a/calendar/gui/a11y/ea-day-view-main-item.c +++ /dev/null @@ -1,1289 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "ea-day-view-main-item.h" -#include "e-day-view-top-item.h" -#include "ea-day-view.h" -#include "ea-day-view-cell.h" -#include "ea-cell-table.h" -#include - -/* EaDayViewMainItem */ -static void ea_day_view_main_item_class_init (EaDayViewMainItemClass *klass); - -static void ea_day_view_main_item_finalize (GObject *object); -static G_CONST_RETURN gchar * ea_day_view_main_item_get_name (AtkObject *accessible); -static G_CONST_RETURN gchar * ea_day_view_main_item_get_description (AtkObject *accessible); - -static gint ea_day_view_main_item_get_n_children (AtkObject *obj); -static AtkObject* ea_day_view_main_item_ref_child (AtkObject *obj, - gint i); -static AtkObject * ea_day_view_main_item_get_parent (AtkObject *accessible); -static gint ea_day_view_main_item_get_index_in_parent (AtkObject *accessible); - -/* callbacks */ -static void ea_day_view_main_item_dates_change_cb (GnomeCalendar *gcal, gpointer data); -static void ea_day_view_main_item_time_change_cb (EDayView *day_view, gpointer data); - -/* component interface */ -static void atk_component_interface_init (AtkComponentIface *iface); -static void component_interface_get_extents (AtkComponent *component, - gint *x, gint *y, - gint *width, gint *height, - AtkCoordType coord_type); -/* atk table interface */ -static void atk_table_interface_init (AtkTableIface *iface); -static gint table_interface_get_index_at (AtkTable *table, - gint row, - gint column); -static gint table_interface_get_column_at_index (AtkTable *table, - gint index); -static gint table_interface_get_row_at_index (AtkTable *table, - gint index); -static AtkObject* table_interface_ref_at (AtkTable *table, - gint row, - gint column); -static gint table_interface_get_n_rows (AtkTable *table); -static gint table_interface_get_n_columns (AtkTable *table); -static gint table_interface_get_column_extent_at (AtkTable *table, - gint row, - gint column); -static gint table_interface_get_row_extent_at (AtkTable *table, - gint row, - gint column); - -static gboolean table_interface_is_row_selected (AtkTable *table, - gint row); -static gboolean table_interface_is_column_selected (AtkTable *table, - gint row); -static gboolean table_interface_is_selected (AtkTable *table, - gint row, - gint column); -static gint table_interface_get_selected_rows (AtkTable *table, - gint **rows_selected); -static gint table_interface_get_selected_columns (AtkTable *table, - gint **columns_selected); -static gboolean table_interface_add_row_selection (AtkTable *table, gint row); -static gboolean table_interface_remove_row_selection (AtkTable *table, - gint row); -static gboolean table_interface_add_column_selection (AtkTable *table, - gint column); -static gboolean table_interface_remove_column_selection (AtkTable *table, - gint column); -static AtkObject* table_interface_get_row_header (AtkTable *table, gint row); -static AtkObject* table_interface_get_column_header (AtkTable *table, - gint in_col); -static AtkObject* table_interface_get_caption (AtkTable *table); - -static G_CONST_RETURN gchar * -table_interface_get_column_description (AtkTable *table, gint in_col); - -static G_CONST_RETURN gchar * -table_interface_get_row_description (AtkTable *table, gint row); - -static AtkObject* table_interface_get_summary (AtkTable *table); - -/* atk selection interface */ -static void atk_selection_interface_init (AtkSelectionIface *iface); -static gboolean selection_interface_add_selection (AtkSelection *selection, - gint i); -static gboolean selection_interface_clear_selection (AtkSelection *selection); -static AtkObject* selection_interface_ref_selection (AtkSelection *selection, - gint i); -static gint selection_interface_get_selection_count (AtkSelection *selection); -static gboolean selection_interface_is_child_selected (AtkSelection *selection, - gint i); - -/* helpers */ -static EaCellTable * -ea_day_view_main_item_get_cell_data (EaDayViewMainItem *ea_main_item); - -static void -ea_day_view_main_item_destory_cell_data (EaDayViewMainItem *ea_main_item); - -static gint -ea_day_view_main_item_get_child_index_at (EaDayViewMainItem *ea_main_item, - gint row, gint column); -static gint -ea_day_view_main_item_get_row_at_index (EaDayViewMainItem *ea_main_item, - gint index); -static gint -ea_day_view_main_item_get_column_at_index (EaDayViewMainItem *ea_main_item, - gint index); -static gint -ea_day_view_main_item_get_row_label (EaDayViewMainItem *ea_main_item, - gint row, gchar *buffer, - gint buffer_size); - -#ifdef ACC_DEBUG -static gint n_ea_day_view_main_item_created = 0; -static gint n_ea_day_view_main_item_destroyed = 0; -#endif - -static gpointer parent_class = NULL; - -GType -ea_day_view_main_item_get_type (void) -{ - static GType type = 0; - AtkObjectFactory *factory; - GTypeQuery query; - GType derived_atk_type; - - if (!type) { - static GTypeInfo tinfo = { - sizeof (EaDayViewMainItemClass), - (GBaseInitFunc) NULL, /* base init */ - (GBaseFinalizeFunc) NULL, /* base finalize */ - (GClassInitFunc) ea_day_view_main_item_class_init, - (GClassFinalizeFunc) NULL, /* class finalize */ - NULL, /* class data */ - sizeof (EaDayViewMainItem), /* instance size */ - 0, /* nb preallocs */ - (GInstanceInitFunc) NULL, /* instance init */ - NULL /* value table */ - }; - - static const GInterfaceInfo atk_component_info = { - (GInterfaceInitFunc) atk_component_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - static const GInterfaceInfo atk_table_info = { - (GInterfaceInitFunc) atk_table_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - static const GInterfaceInfo atk_selection_info = { - (GInterfaceInitFunc) atk_selection_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - - /* - * Figure out the size of the class and instance - * we are run-time deriving from (GailCanvasItem, in this case) - * - */ - - factory = atk_registry_get_factory (atk_get_default_registry (), - e_day_view_main_item_get_type()); - derived_atk_type = atk_object_factory_get_accessible_type (factory); - g_type_query (derived_atk_type, &query); - - tinfo.class_size = query.class_size; - tinfo.instance_size = query.instance_size; - - type = g_type_register_static (derived_atk_type, - "EaDayViewMainItem", &tinfo, 0); - g_type_add_interface_static (type, ATK_TYPE_COMPONENT, - &atk_component_info); - g_type_add_interface_static (type, ATK_TYPE_TABLE, - &atk_table_info); - g_type_add_interface_static (type, ATK_TYPE_SELECTION, - &atk_selection_info); - } - - return type; -} - -static void -ea_day_view_main_item_class_init (EaDayViewMainItemClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - AtkObjectClass *class = ATK_OBJECT_CLASS (klass); - - gobject_class->finalize = ea_day_view_main_item_finalize; - parent_class = g_type_class_peek_parent (klass); - - class->get_name = ea_day_view_main_item_get_name; - class->get_description = ea_day_view_main_item_get_description; - - class->get_n_children = ea_day_view_main_item_get_n_children; - class->ref_child = ea_day_view_main_item_ref_child; - class->get_parent = ea_day_view_main_item_get_parent; - class->get_index_in_parent = ea_day_view_main_item_get_index_in_parent; -} - -AtkObject* -ea_day_view_main_item_new (GObject *obj) -{ - AtkObject *accessible; - GnomeCalendar *gcal; - EDayViewMainItem *main_item; - - g_return_val_if_fail (E_IS_DAY_VIEW_MAIN_ITEM (obj), NULL); - - accessible = ATK_OBJECT (g_object_new (EA_TYPE_DAY_VIEW_MAIN_ITEM, - NULL)); - - atk_object_initialize (accessible, obj); - accessible->role = ATK_ROLE_TABLE; - -#ifdef ACC_DEBUG - ++n_ea_day_view_main_item_created; - printf ("ACC_DEBUG: n_ea_day_view_main_item_created = %d\n", - n_ea_day_view_main_item_created); -#endif - main_item = E_DAY_VIEW_MAIN_ITEM (obj); - g_signal_connect (main_item->day_view, "selected_time_changed", - G_CALLBACK (ea_day_view_main_item_time_change_cb), - accessible); - - /* listen for date changes of calendar */ - gcal = e_calendar_view_get_calendar (E_CALENDAR_VIEW (main_item->day_view)); - if (gcal) - g_signal_connect (gcal, "dates_shown_changed", - G_CALLBACK (ea_day_view_main_item_dates_change_cb), - accessible); - - return accessible; -} - -static void -ea_day_view_main_item_finalize (GObject *object) -{ - EaDayViewMainItem *ea_main_item; - - g_return_if_fail (EA_IS_DAY_VIEW_MAIN_ITEM (object)); - - ea_main_item = EA_DAY_VIEW_MAIN_ITEM (object); - - /* Free the allocated cell data */ - ea_day_view_main_item_destory_cell_data (ea_main_item); - - G_OBJECT_CLASS (parent_class)->finalize (object); -#ifdef ACC_DEBUG - ++n_ea_day_view_main_item_destroyed; - printf ("ACC_DEBUG: n_ea_day_view_main_item_destroyed = %d\n", - n_ea_day_view_main_item_destroyed); -#endif -} - -static G_CONST_RETURN gchar * -ea_day_view_main_item_get_name (AtkObject *accessible) -{ - AtkObject *parent; - g_return_val_if_fail (EA_IS_DAY_VIEW_MAIN_ITEM (accessible), NULL); - parent = atk_object_get_parent (accessible); - - if (!parent) - return NULL; - - return atk_object_get_name (parent); -} - -static G_CONST_RETURN gchar * -ea_day_view_main_item_get_description (AtkObject *accessible) -{ - return _("a table to view and select the current time range"); -} - -static gint -ea_day_view_main_item_get_n_children (AtkObject *accessible) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - - g_return_val_if_fail (EA_IS_DAY_VIEW_MAIN_ITEM (accessible), -1); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - return day_view->rows * day_view->days_shown; -} - -static AtkObject * -ea_day_view_main_item_ref_child (AtkObject *accessible, gint index) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - gint n_children; - EDayViewCell *cell; - EaCellTable *cell_data; - EaDayViewMainItem *ea_main_item; - - g_return_val_if_fail (EA_IS_DAY_VIEW_MAIN_ITEM (accessible), NULL); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return NULL; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - n_children = ea_day_view_main_item_get_n_children (accessible); - if (index < 0 || index >= n_children) - return NULL; - - ea_main_item = EA_DAY_VIEW_MAIN_ITEM (accessible); - cell_data = ea_day_view_main_item_get_cell_data (ea_main_item); - if (!cell_data) - return NULL; - - cell = ea_cell_table_get_cell_at_index (cell_data, index); - if (!cell) { - gint row, column; - - row = ea_day_view_main_item_get_row_at_index (ea_main_item, index); - column = ea_day_view_main_item_get_column_at_index (ea_main_item, index); - cell = e_day_view_cell_new (day_view, row, column); - ea_cell_table_set_cell_at_index (cell_data, index, cell); - g_object_unref (cell); - } - return g_object_ref (atk_gobject_accessible_for_object (G_OBJECT(cell))); -} - -static AtkObject * -ea_day_view_main_item_get_parent (AtkObject *accessible) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - - g_return_val_if_fail (EA_IS_DAY_VIEW_MAIN_ITEM (accessible), NULL); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return NULL; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - return gtk_widget_get_accessible (GTK_WIDGET (main_item->day_view)); -} - -static gint -ea_day_view_main_item_get_index_in_parent (AtkObject *accessible) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - - g_return_val_if_fail (EA_IS_DAY_VIEW_MAIN_ITEM (accessible), -1); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - /* always the first child of ea-day-view */ - return 0; -} - -/* callbacks */ - -static void -ea_day_view_main_item_dates_change_cb (GnomeCalendar *gcal, gpointer data) -{ - EaDayViewMainItem *ea_main_item; - - g_return_if_fail (GNOME_IS_CALENDAR (gcal)); - g_return_if_fail (data); - g_return_if_fail (EA_IS_DAY_VIEW_MAIN_ITEM (data)); - - ea_main_item = EA_DAY_VIEW_MAIN_ITEM (data); - -#ifdef ACC_DEBUG - printf ("EvoAcc: ea_day_view_main_item update cb\n"); -#endif - - ea_day_view_main_item_destory_cell_data (ea_main_item); -} - -static void -ea_day_view_main_item_time_change_cb (EDayView *day_view, gpointer data) -{ - EaDayViewMainItem *ea_main_item; - AtkObject *item_cell = NULL; - - g_return_if_fail (E_IS_DAY_VIEW (day_view)); - g_return_if_fail (data); - g_return_if_fail (EA_IS_DAY_VIEW_MAIN_ITEM (data)); - - ea_main_item = EA_DAY_VIEW_MAIN_ITEM (data); - -#ifdef ACC_DEBUG - printf ("EvoAcc: ea_day_view_main_item time changed cb\n"); -#endif - /* only deal with the first selected child, for now */ - item_cell = atk_selection_ref_selection (ATK_SELECTION (ea_main_item), - 0); - if (item_cell) { - AtkStateSet *state_set; - state_set = atk_object_ref_state_set (item_cell); - atk_state_set_add_state (state_set, ATK_STATE_FOCUSED); - g_object_unref (state_set); - - g_signal_emit_by_name (ea_main_item, - "active-descendant-changed", - item_cell); - g_signal_emit_by_name (data, "selection_changed"); - - atk_focus_tracker_notify (item_cell); - g_object_unref (item_cell); - } - -} - -/* helpers */ - -static gint -ea_day_view_main_item_get_child_index_at (EaDayViewMainItem *ea_main_item, - gint row, gint column) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - - g_return_val_if_fail (ea_main_item, -1); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - if (row >= 0 && row < day_view->rows && - column >= 0 && column < day_view->days_shown) - return column * day_view->rows + row; - return -1; -} - -static gint -ea_day_view_main_item_get_row_at_index (EaDayViewMainItem *ea_main_item, - gint index) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - gint n_children; - - g_return_val_if_fail (ea_main_item, -1); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - n_children = ea_day_view_main_item_get_n_children (ATK_OBJECT (ea_main_item)); - if (index >= 0 && index < n_children) - return index % day_view->rows; - return -1; -} - -static gint -ea_day_view_main_item_get_column_at_index (EaDayViewMainItem *ea_main_item, - gint index) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - gint n_children; - - g_return_val_if_fail (ea_main_item, -1); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - n_children = ea_day_view_main_item_get_n_children (ATK_OBJECT (ea_main_item)); - if (index >= 0 && index < n_children) - return index / day_view->rows; - return -1; -} - -static gint -ea_day_view_main_item_get_row_label (EaDayViewMainItem *ea_main_item, - gint row, gchar *buffer, gint buffer_size) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - const gchar *suffix; - gint hour, minute, suffix_width; - - g_return_val_if_fail (ea_main_item, 0); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return 0; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - hour = day_view->first_hour_shown; - minute = day_view->first_minute_shown; - minute += row * day_view->mins_per_row; - hour = (hour + minute / 60) % 24; - minute %= 60; - - e_day_view_convert_time_to_display (day_view, hour, &hour, - &suffix, &suffix_width); - return g_snprintf (buffer, buffer_size, "%i:%02i %s", - hour, minute, suffix); -} - -static EaCellTable * -ea_day_view_main_item_get_cell_data (EaDayViewMainItem *ea_main_item) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - EaCellTable *cell_data; - - g_return_val_if_fail (ea_main_item, NULL); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return NULL; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - cell_data = g_object_get_data (G_OBJECT(ea_main_item), - "ea-day-view-cell-table"); - if (!cell_data) { - cell_data = ea_cell_table_create (day_view->rows, - day_view->days_shown, TRUE); - g_object_set_data (G_OBJECT(ea_main_item), - "ea-day-view-cell-table", cell_data); - } - return cell_data; -} - -static void -ea_day_view_main_item_destory_cell_data (EaDayViewMainItem *ea_main_item) -{ - EaCellTable *cell_data; - - g_return_if_fail (ea_main_item); - - cell_data = g_object_get_data (G_OBJECT(ea_main_item), - "ea-day-view-cell-table"); - if (cell_data) { - g_object_set_data (G_OBJECT(ea_main_item), - "ea-day-view-cell-table", NULL); - ea_cell_table_destroy (cell_data); - } -} - -/* Atk Component Interface */ - -static void -atk_component_interface_init (AtkComponentIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->get_extents = component_interface_get_extents; -} - -static void -component_interface_get_extents (AtkComponent *component, - gint *x, gint *y, gint *width, gint *height, - AtkCoordType coord_type) -{ - GObject *g_obj; - AtkObject *ea_canvas; - EDayViewMainItem *main_item; - EDayView *day_view; - - *x = *y = *width = *height = 0; - - g_return_if_fail (EA_IS_DAY_VIEW_MAIN_ITEM (component)); - - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(component)); - if (!g_obj) - /* defunct object*/ - return; - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - ea_canvas = gtk_widget_get_accessible (day_view->main_canvas); - atk_component_get_extents (ATK_COMPONENT (ea_canvas), x, y, - width, height, coord_type); -} - -/* atk table interface */ - -static void -atk_table_interface_init (AtkTableIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->ref_at = table_interface_ref_at; - - iface->get_n_rows = table_interface_get_n_rows; - iface->get_n_columns = table_interface_get_n_columns; - iface->get_index_at = table_interface_get_index_at; - iface->get_column_at_index = table_interface_get_column_at_index; - iface->get_row_at_index = table_interface_get_row_at_index; - iface->get_column_extent_at = table_interface_get_column_extent_at; - iface->get_row_extent_at = table_interface_get_row_extent_at; - - iface->is_selected = table_interface_is_selected; - iface->get_selected_rows = table_interface_get_selected_rows; - iface->get_selected_columns = table_interface_get_selected_columns; - iface->is_row_selected = table_interface_is_row_selected; - iface->is_column_selected = table_interface_is_column_selected; - iface->add_row_selection = table_interface_add_row_selection; - iface->remove_row_selection = table_interface_remove_row_selection; - iface->add_column_selection = table_interface_add_column_selection; - iface->remove_column_selection = table_interface_remove_column_selection; - - iface->get_row_header = table_interface_get_row_header; - iface->get_column_header = table_interface_get_column_header; - iface->get_caption = table_interface_get_caption; - iface->get_summary = table_interface_get_summary; - iface->get_row_description = table_interface_get_row_description; - iface->get_column_description = table_interface_get_column_description; -} - -static AtkObject* -table_interface_ref_at (AtkTable *table, - gint row, - gint column) -{ - gint index; - - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); - index = ea_day_view_main_item_get_child_index_at (ea_main_item, - row, column); - return ea_day_view_main_item_ref_child (ATK_OBJECT (ea_main_item), index); -} - -static gint -table_interface_get_n_rows (AtkTable *table) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - return day_view->rows; -} - -static gint -table_interface_get_n_columns (AtkTable *table) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - return day_view->days_shown; -} - -static gint -table_interface_get_index_at (AtkTable *table, - gint row, - gint column) -{ - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); - return ea_day_view_main_item_get_child_index_at (ea_main_item, - row, column); -} - -static gint -table_interface_get_column_at_index (AtkTable *table, - gint index) -{ - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); - return ea_day_view_main_item_get_column_at_index (ea_main_item, index); -} - -static gint -table_interface_get_row_at_index (AtkTable *table, - gint index) -{ - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); - return ea_day_view_main_item_get_row_at_index (ea_main_item, index); -} - -static gint -table_interface_get_column_extent_at (AtkTable *table, - gint row, - gint column) -{ - gint index; - gint width = 0, height = 0; - AtkObject *child; - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); - - index = ea_day_view_main_item_get_child_index_at (ea_main_item, - row, column); - child = atk_object_ref_accessible_child (ATK_OBJECT (ea_main_item), - index); - if (child) - atk_component_get_size (ATK_COMPONENT (child), - &width, &height); - - return width; -} - -static gint -table_interface_get_row_extent_at (AtkTable *table, - gint row, - gint column) -{ - gint index; - gint width = 0, height = 0; - AtkObject *child; - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); - - index = ea_day_view_main_item_get_child_index_at (ea_main_item, - row, column); - child = atk_object_ref_accessible_child (ATK_OBJECT (ea_main_item), - index); - if (child) - atk_component_get_size (ATK_COMPONENT (child), - &width, &height); - - return height; -} - -static gboolean -table_interface_is_row_selected (AtkTable *table, - gint row) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - if (day_view->selection_start_day == -1) - /* no selection */ - return FALSE; - if (day_view->selection_start_day != day_view->selection_end_day) - /* all row is selected */ - return TRUE; - if (row >= day_view->selection_start_row && - row <= day_view->selection_end_row) - return TRUE; - return FALSE; -} - -static gboolean -table_interface_is_selected (AtkTable *table, - gint row, - gint column) -{ - return table_interface_is_row_selected (table, row) && - table_interface_is_column_selected (table, column); -} - -static gboolean -table_interface_is_column_selected (AtkTable *table, - gint column) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - if (column >= day_view->selection_start_day && - column <= day_view->selection_end_day) - return TRUE; - return FALSE; -} - -static gint -table_interface_get_selected_rows (AtkTable *table, - gint **rows_selected) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); - gint start_row = -1, n_rows = 0; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - if (day_view->selection_start_day == -1) - return 0; - - if (day_view->selection_start_day != day_view->selection_end_day) { - /* all the rows should be selected */ - n_rows = day_view->rows; - start_row = 0; - } - else if (day_view->selection_start_row != -1) { - start_row = day_view->selection_start_row; - n_rows = day_view->selection_end_row - start_row + 1; - } - if (n_rows > 0 && start_row != -1 && rows_selected) { - gint index; - - *rows_selected = (gint *) g_malloc (n_rows * sizeof (gint)); - for (index = 0; index < n_rows; ++index) - (*rows_selected)[index] = start_row + index; - } - return n_rows; -} - -static gint -table_interface_get_selected_columns (AtkTable *table, - gint **columns_selected) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); - gint start_column = -1, n_columns = 0; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - if (day_view->selection_start_day == -1) - return 0; - - start_column = day_view->selection_start_day; - n_columns = day_view->selection_end_day - start_column + 1; - if (n_columns > 0 && start_column != -1 && columns_selected) { - gint index; - - *columns_selected = (gint *) g_malloc (n_columns * sizeof (gint)); - for (index = 0; index < n_columns; ++index) - (*columns_selected)[index] = start_column + index; - } - return n_columns; -} - -static gboolean -table_interface_add_row_selection (AtkTable *table, - gint row) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - /* FIXME: we need multi-selection */ - - day_view->selection_start_day = 0; - day_view->selection_end_day = 0; - day_view->selection_start_row = row; - day_view->selection_end_row = row; - - e_day_view_ensure_rows_visible (day_view, - day_view->selection_start_row, - day_view->selection_end_row); - e_day_view_update_calendar_selection_time (day_view); - gtk_widget_queue_draw (day_view->main_canvas); - return TRUE; -} - -static gboolean -table_interface_remove_row_selection (AtkTable *table, - gint row) -{ - return FALSE; -} - -static gboolean -table_interface_add_column_selection (AtkTable *table, - gint column) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - /* FIXME: we need multi-selection */ - - day_view->selection_start_day = column; - day_view->selection_end_day = column; - day_view->selection_start_row = 0; - day_view->selection_end_row = day_view->rows; - - e_day_view_update_calendar_selection_time (day_view); - gtk_widget_queue_draw (day_view->main_canvas); - return TRUE; -} - -static gboolean -table_interface_remove_column_selection (AtkTable *table, - gint column) -{ - /* FIXME: NOT IMPLEMENTED */ - return FALSE; -} - -static AtkObject* -table_interface_get_row_header (AtkTable *table, - gint row) -{ - /* FIXME: NOT IMPLEMENTED */ - return NULL; -} - -static AtkObject* -table_interface_get_column_header (AtkTable *table, - gint in_col) -{ - /* FIXME: NOT IMPLEMENTED */ - return NULL; -} - -static AtkObject* -table_interface_get_caption (AtkTable *table) -{ - /* FIXME: NOT IMPLEMENTED */ - return NULL; -} - -static G_CONST_RETURN gchar * -table_interface_get_column_description (AtkTable *table, - gint in_col) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); - const gchar *description; - EaCellTable *cell_data; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return NULL; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - if (in_col < 0 || in_col >= day_view->days_shown) - return NULL; - cell_data = ea_day_view_main_item_get_cell_data (ea_main_item); - if (!cell_data) - return NULL; - - description = ea_cell_table_get_column_label (cell_data, in_col); - if (!description) { - gchar buffer[128]; - e_day_view_top_item_get_day_label (day_view, in_col, buffer, 128); - ea_cell_table_set_column_label (cell_data, in_col, buffer); - description = ea_cell_table_get_column_label (cell_data, in_col); - } - return description; -} - -static G_CONST_RETURN gchar * -table_interface_get_row_description (AtkTable *table, - gint row) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); - const gchar *description; - EaCellTable *cell_data; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return NULL; - - if (row < 0 || row >= 12 * 24) - return NULL; - cell_data = ea_day_view_main_item_get_cell_data (ea_main_item); - if (!cell_data) - return NULL; - - description = ea_cell_table_get_row_label (cell_data, row); - if (!description) { - gchar buffer[128]; - ea_day_view_main_item_get_row_label (ea_main_item, row, buffer, sizeof (buffer)); - ea_cell_table_set_row_label (cell_data, row, buffer); - description = ea_cell_table_get_row_label (cell_data, - row); - } - return description; -} - -static AtkObject* -table_interface_get_summary (AtkTable *table) -{ - /* FIXME: NOT IMPLEMENTED */ - return NULL; -} - -/* atkselection interface */ - -static void -atk_selection_interface_init (AtkSelectionIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->add_selection = selection_interface_add_selection; - iface->clear_selection = selection_interface_clear_selection; - iface->ref_selection = selection_interface_ref_selection; - iface->get_selection_count = selection_interface_get_selection_count; - iface->is_child_selected = selection_interface_is_child_selected; -} - -static gboolean -selection_interface_add_selection (AtkSelection *selection, gint i) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (selection); - gint column, row; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - row = ea_day_view_main_item_get_row_at_index (ea_main_item, i); - column = ea_day_view_main_item_get_column_at_index (ea_main_item, i); - - if (row == -1 || column == -1) - return FALSE; - - /*FIXME: multi-selection is needed */ - day_view->selection_start_day = column; - day_view->selection_end_day = column; - day_view->selection_start_row = row; - day_view->selection_end_row = row; - - e_day_view_ensure_rows_visible (day_view, - day_view->selection_start_row, - day_view->selection_end_row); - e_day_view_update_calendar_selection_time (day_view); - gtk_widget_queue_draw (day_view->main_canvas); - return TRUE; -} - -static gboolean -selection_interface_clear_selection (AtkSelection *selection) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (selection); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - day_view->selection_start_row = -1; - day_view->selection_start_day = -1; - day_view->selection_end_row = -1; - day_view->selection_end_day = -1; - - e_day_view_update_calendar_selection_time (day_view); - gtk_widget_queue_draw (day_view->main_canvas); - - return TRUE; -} - -static AtkObject* -selection_interface_ref_selection (AtkSelection *selection, gint i) -{ - gint count; - GObject *g_obj; - EDayView *day_view; - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (selection); - gint start_index; - - count = selection_interface_get_selection_count (selection); - if (i < 0 || i >=count) - return NULL; - - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (ea_main_item)); - day_view = E_DAY_VIEW_MAIN_ITEM (g_obj)->day_view; - start_index = ea_day_view_main_item_get_child_index_at (ea_main_item, - day_view->selection_start_row, - day_view->selection_start_day); - - return ea_day_view_main_item_ref_child (ATK_OBJECT (selection), start_index + i); -} - -static gint -selection_interface_get_selection_count (AtkSelection *selection) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (selection); - gint start_index, end_index; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return 0; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - if (day_view->selection_start_day == -1 || - day_view->selection_start_row == -1) - return 0; - start_index = ea_day_view_main_item_get_child_index_at (ea_main_item, - day_view->selection_start_row, - day_view->selection_start_day); - end_index = ea_day_view_main_item_get_child_index_at (ea_main_item, - day_view->selection_end_row, - day_view->selection_end_day); - - return end_index - start_index + 1; -} - -static gboolean -selection_interface_is_child_selected (AtkSelection *selection, gint i) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EDayViewMainItem *main_item; - EDayView *day_view; - EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (selection); - gint column, row; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); - day_view = main_item->day_view; - - row = ea_day_view_main_item_get_row_at_index (ea_main_item, i); - column = ea_day_view_main_item_get_column_at_index (ea_main_item, i); - - if (column < day_view->selection_start_day || - column > day_view->selection_end_day) - return FALSE; - - if ((column == day_view->selection_start_day || - column == day_view->selection_end_day) && - (row < day_view->selection_start_row || - row > day_view->selection_end_row)) - return FALSE; - - /* if comes here, the cell is selected */ - return TRUE; -} diff --git a/calendar/gui/a11y/ea-day-view-main-item.h b/calendar/gui/a11y/ea-day-view-main-item.h deleted file mode 100644 index c782e6acc8..0000000000 --- a/calendar/gui/a11y/ea-day-view-main-item.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EA_DAY_VIEW_MAIN_ITEM_H__ -#define __EA_DAY_VIEW_MAIN_ITEM_H__ - -#include -#include "e-day-view-main-item.h" - -G_BEGIN_DECLS - -#define EA_TYPE_DAY_VIEW_MAIN_ITEM (ea_day_view_main_item_get_type ()) -#define EA_DAY_VIEW_MAIN_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_DAY_VIEW_MAIN_ITEM, EaDayViewMainItem)) -#define EA_DAY_VIEW_MAIN_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_DAY_VIEW_MAIN_ITEM, EaDayViewMainItemClass)) -#define EA_IS_DAY_VIEW_MAIN_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_DAY_VIEW_MAIN_ITEM)) -#define EA_IS_DAY_VIEW_MAIN_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_DAY_VIEW_MAIN_ITEM)) -#define EA_DAY_VIEW_MAIN_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_DAY_VIEW_MAIN_ITEM, EaDayViewMainItemClass)) - -typedef struct _EaDayViewMainItem EaDayViewMainItem; -typedef struct _EaDayViewMainItemClass EaDayViewMainItemClass; - -struct _EaDayViewMainItem -{ - AtkGObjectAccessible parent; -}; - -GType ea_day_view_main_item_get_type (void); - -struct _EaDayViewMainItemClass -{ - AtkGObjectAccessibleClass parent_class; -}; - -AtkObject* ea_day_view_main_item_new (GObject *obj); - -G_END_DECLS - -#endif /* __EA_DAY_VIEW_MAIN_ITEM_H__ */ diff --git a/calendar/gui/a11y/ea-day-view.c b/calendar/gui/a11y/ea-day-view.c deleted file mode 100644 index 9eb3e343f3..0000000000 --- a/calendar/gui/a11y/ea-day-view.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "ea-day-view.h" -#include "ea-cal-view-event.h" - -#include "ea-calendar-helpers.h" -#include "ea-gnome-calendar.h" -#include "calendar-commands.h" -#include -#include - -static void ea_day_view_class_init (EaDayViewClass *klass); - -static G_CONST_RETURN gchar * ea_day_view_get_name (AtkObject *accessible); -static G_CONST_RETURN gchar * ea_day_view_get_description (AtkObject *accessible); -static gint ea_day_view_get_n_children (AtkObject *obj); -static AtkObject* ea_day_view_ref_child (AtkObject *obj, - gint i); -static gpointer parent_class = NULL; - -GType -ea_day_view_get_type (void) -{ - static GType type = 0; - AtkObjectFactory *factory; - GTypeQuery query; - GType derived_atk_type; - - if (!type) { - static GTypeInfo tinfo = { - sizeof (EaDayViewClass), - (GBaseInitFunc) NULL, /* base init */ - (GBaseFinalizeFunc) NULL, /* base finalize */ - (GClassInitFunc) ea_day_view_class_init, /* class init */ - (GClassFinalizeFunc) NULL, /* class finalize */ - NULL, /* class data */ - sizeof (EaDayView), /* instance size */ - 0, /* nb preallocs */ - (GInstanceInitFunc) NULL, /* instance init */ - NULL /* value table */ - }; - - /* - * Figure out the size of the class and instance - * we are run-time deriving from (EaCalView, in this case) - * - * Note: we must still use run-time deriving here, because - * our parent class EaCalView is run-time deriving. - */ - - factory = atk_registry_get_factory (atk_get_default_registry (), - e_calendar_view_get_type()); - derived_atk_type = atk_object_factory_get_accessible_type (factory); - g_type_query (derived_atk_type, &query); - - tinfo.class_size = query.class_size; - tinfo.instance_size = query.instance_size; - - type = g_type_register_static (derived_atk_type, - "EaDayView", &tinfo, 0); - } - - return type; -} - -static void -ea_day_view_class_init (EaDayViewClass *klass) -{ - AtkObjectClass *class = ATK_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - class->get_name = ea_day_view_get_name; - class->get_description = ea_day_view_get_description; - - class->get_n_children = ea_day_view_get_n_children; - class->ref_child = ea_day_view_ref_child; -} - -AtkObject* -ea_day_view_new (GtkWidget *widget) -{ - GObject *object; - AtkObject *accessible; - - g_return_val_if_fail (E_IS_DAY_VIEW (widget), NULL); - - object = g_object_new (EA_TYPE_DAY_VIEW, NULL); - - accessible = ATK_OBJECT (object); - atk_object_initialize (accessible, widget); - -#ifdef ACC_DEBUG - printf ("EvoAcc: ea_day_view created %p\n", (gpointer)accessible); -#endif - - return accessible; -} - -static G_CONST_RETURN gchar * -ea_day_view_get_name (AtkObject *accessible) -{ - EDayView *day_view; - GnomeCalendar *gcal; - const gchar *label_text; - GnomeCalendarViewType view_type; - gint n_events; - gchar *event_str, *name_str; - - g_return_val_if_fail (EA_IS_DAY_VIEW (accessible), NULL); - - if (!GTK_ACCESSIBLE (accessible)->widget) - return NULL; - - day_view = E_DAY_VIEW (GTK_ACCESSIBLE (accessible)->widget); - gcal = e_calendar_view_get_calendar (E_CALENDAR_VIEW (day_view)); - if (!GTK_WIDGET_VISIBLE (GTK_WIDGET (gcal))) - return NULL; - - label_text = ea_gnome_calendar_get_label_description (gcal); - - n_events = atk_object_get_n_accessible_children (accessible); - /* the child main item is always there */ - --n_events; - if (n_events >= 1) - /* To translators: Here, "It" is either like "Work Week View: July - 10th - July 14th, 2006." or "Day View: Thursday July 13th, 2006." */ - event_str = g_strdup_printf (ngettext ("It has %d event.", "It has %d events.", n_events), n_events); - else - /* To translators: Here, "It" is either like "Work Week View: July - 10th - July 14th, 2006." or "Day View: Thursday July 13th, 2006." */ - event_str = g_strdup (_("It has no events.")); - - view_type = gnome_calendar_get_view (gcal); - if (view_type == GNOME_CAL_WORK_WEEK_VIEW) - /* To translators: First %s is the week, for example "July 10th - - July 14th, 2006". Second %s is the number of events in this work - week, for example "It has %d event/events." or "It has no events." */ - name_str = g_strdup_printf (_("Work Week View: %s. %s"), - label_text, event_str); - else - /* To translators: First %s is the day, for example "Thursday July - 13th, 2006". Second %s is the number of events on this day, for - example "It has %d event/events." or "It has no events." */ - name_str = g_strdup_printf (_("Day View: %s. %s"), - label_text, event_str); - - ATK_OBJECT_CLASS (parent_class)->set_name (accessible, name_str); - g_free (name_str); - g_free (event_str); - - return accessible->name; -} - -static G_CONST_RETURN gchar * -ea_day_view_get_description (AtkObject *accessible) -{ - EDayView *day_view; - - g_return_val_if_fail (EA_IS_DAY_VIEW (accessible), NULL); - - if (!GTK_ACCESSIBLE (accessible)->widget) - return NULL; - day_view = E_DAY_VIEW (GTK_ACCESSIBLE (accessible)->widget); - - if (accessible->description) - return accessible->description; - else { - GnomeCalendar *gcal; - GnomeCalendarViewType view_type; - - gcal = e_calendar_view_get_calendar (E_CALENDAR_VIEW (day_view)); - view_type = gnome_calendar_get_view (gcal); - - if (view_type == GNOME_CAL_WORK_WEEK_VIEW) - return _("calendar view for a work week"); - else - return _("calendar view for one or more days"); - } -} - -static gint -ea_day_view_get_n_children (AtkObject *accessible) -{ - EDayView *day_view; - gint day; - gint child_num = 0; - - g_return_val_if_fail (EA_IS_DAY_VIEW (accessible), -1); - - if (!GTK_ACCESSIBLE (accessible)->widget) - return -1; - - day_view = E_DAY_VIEW (GTK_ACCESSIBLE (accessible)->widget); - - child_num += day_view->long_events->len; - - for (day = 0; day < day_view->days_shown; day++) { - child_num += day_view->events[day]->len; - } - - /* "+1" for the main item */ - return child_num + 1; -} - -static AtkObject * -ea_day_view_ref_child (AtkObject *accessible, gint index) -{ - EDayView *day_view; - gint child_num; - gint day; - AtkObject *atk_object = NULL; - EDayViewEvent *event = NULL; - - g_return_val_if_fail (EA_IS_DAY_VIEW (accessible), NULL); - - child_num = atk_object_get_n_accessible_children (accessible); - if (child_num <= 0 || index < 0 || index >= child_num) - return NULL; - - if (!GTK_ACCESSIBLE (accessible)->widget) - return NULL; - day_view = E_DAY_VIEW (GTK_ACCESSIBLE (accessible)->widget); - - if (index == 0) { - /* index == 0 is the main item */ - atk_object = atk_gobject_accessible_for_object (G_OBJECT (day_view->main_canvas_item)); - g_object_ref (atk_object); - } - else { - --index; - /* a long event */ - if (index < day_view->long_events->len) { - event = &g_array_index (day_view->long_events, - EDayViewEvent, index); - } - else { - index -= day_view->long_events->len; - day = 0; - while (index >= day_view->events[day]->len) { - index -= day_view->events[day]->len; - ++day; - } - - event = &g_array_index (day_view->events[day], - EDayViewEvent, index); - } - if (event && event->canvas_item) { - /* Not use atk_gobject_accessible_for_object here, - * we need to do special thing here - */ - atk_object = ea_calendar_helpers_get_accessible_for (event->canvas_item); - g_object_ref (atk_object); - } - } - return atk_object; -} diff --git a/calendar/gui/a11y/ea-day-view.h b/calendar/gui/a11y/ea-day-view.h deleted file mode 100644 index 33399f6600..0000000000 --- a/calendar/gui/a11y/ea-day-view.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EA_DAY_VIEW_H__ -#define __EA_DAY_VIEW_H__ - -#include "ea-cal-view.h" -#include "e-day-view.h" - -G_BEGIN_DECLS - -#define EA_TYPE_DAY_VIEW (ea_day_view_get_type ()) -#define EA_DAY_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_DAY_VIEW, EaDayView)) -#define EA_DAY_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_DAY_VIEW, EaDayViewClass)) -#define EA_IS_DAY_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_DAY_VIEW)) -#define EA_IS_DAY_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_DAY_VIEW)) -#define EA_DAY_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_DAY_VIEW, EaDayViewClass)) - -typedef struct _EaDayView EaDayView; -typedef struct _EaDayViewClass EaDayViewClass; - -struct _EaDayView -{ - EaCalView parent; -}; - -GType ea_day_view_get_type (void); - -struct _EaDayViewClass -{ - EaCalViewClass parent_class; -}; - -AtkObject* ea_day_view_new (GtkWidget *widget); - -G_END_DECLS - -#endif /* __EA_DAY_VIEW_H__ */ diff --git a/calendar/gui/a11y/ea-gnome-calendar.c b/calendar/gui/a11y/ea-gnome-calendar.c deleted file mode 100644 index e5d9654c1a..0000000000 --- a/calendar/gui/a11y/ea-gnome-calendar.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "ea-gnome-calendar.h" -#include "calendar-commands.h" -#include -#include -#include -#include -#include - -static void ea_gnome_calendar_class_init (EaGnomeCalendarClass *klass); - -static G_CONST_RETURN gchar * ea_gnome_calendar_get_name (AtkObject *accessible); -static G_CONST_RETURN gchar * ea_gnome_calendar_get_description (AtkObject *accessible); -static gint ea_gnome_calendar_get_n_children (AtkObject* obj); -static AtkObject * ea_gnome_calendar_ref_child (AtkObject *obj, gint i); - -static void ea_gcal_switch_view_cb (GtkNotebook *widget, GtkNotebookPage *page, - guint index, gpointer data); -static void ea_gcal_dates_change_cb (GnomeCalendar *gcal, gpointer data); - -static gpointer parent_class = NULL; - -GType -ea_gnome_calendar_get_type (void) -{ - static GType type = 0; - AtkObjectFactory *factory; - GTypeQuery query; - GType derived_atk_type; - - if (!type) { - static GTypeInfo tinfo = { - sizeof (EaGnomeCalendarClass), - (GBaseInitFunc) NULL, /* base init */ - (GBaseFinalizeFunc) NULL, /* base finalize */ - (GClassInitFunc) ea_gnome_calendar_class_init, /* class init */ - (GClassFinalizeFunc) NULL, /* class finalize */ - NULL, /* class data */ - sizeof (EaGnomeCalendar), /* instance size */ - 0, /* nb preallocs */ - (GInstanceInitFunc) NULL, /* instance init */ - NULL /* value table */ - }; - - /* - * Figure out the size of the class and instance - * we are run-time deriving from (GailWidget, in this case) - */ - - factory = atk_registry_get_factory (atk_get_default_registry (), - GTK_TYPE_WIDGET); - derived_atk_type = atk_object_factory_get_accessible_type (factory); - g_type_query (derived_atk_type, &query); - tinfo.class_size = query.class_size; - tinfo.instance_size = query.instance_size; - - type = g_type_register_static (derived_atk_type, - "EaGnomeCalendar", &tinfo, 0); - - } - - return type; -} - -static void -ea_gnome_calendar_class_init (EaGnomeCalendarClass *klass) -{ - AtkObjectClass *class = ATK_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - class->get_name = ea_gnome_calendar_get_name; - class->get_description = ea_gnome_calendar_get_description; - - class->get_n_children = ea_gnome_calendar_get_n_children; - class->ref_child = ea_gnome_calendar_ref_child; -} - -AtkObject* -ea_gnome_calendar_new (GtkWidget *widget) -{ - GObject *object; - AtkObject *accessible; - GnomeCalendar *gcal; - GtkWidget *notebook; - - g_return_val_if_fail (GNOME_IS_CALENDAR (widget), NULL); - - object = g_object_new (EA_TYPE_GNOME_CALENDAR, NULL); - - accessible = ATK_OBJECT (object); - atk_object_initialize (accessible, widget); - - accessible->role = ATK_ROLE_FILLER; - - gcal = GNOME_CALENDAR (widget); - - /* listen on view type change - */ - g_signal_connect (widget, "dates_shown_changed", - G_CALLBACK (ea_gcal_dates_change_cb), - accessible); - notebook = gnome_calendar_get_view_notebook_widget (gcal); - if (notebook) { - g_signal_connect (notebook, "switch_page", - G_CALLBACK (ea_gcal_switch_view_cb), - accessible); - } - -#ifdef ACC_DEBUG - printf ("EvoAcc: ea-gnome-calendar created: %p\n", (gpointer)accessible); -#endif - - return accessible; -} - -const gchar * -ea_gnome_calendar_get_label_description (GnomeCalendar *gcal) -{ - icaltimezone *zone; - struct icaltimetype start_tt, end_tt; - time_t start_time, end_time; - struct tm start_tm, end_tm; - static gchar buffer[512]; - gchar end_buffer[256]; - GnomeCalendarViewType view; - - gnome_calendar_get_visible_time_range (gcal, &start_time, &end_time); - zone = gnome_calendar_get_timezone (gcal); - - start_tt = icaltime_from_timet_with_zone (start_time, FALSE, zone); - start_tm.tm_year = start_tt.year - 1900; - start_tm.tm_mon = start_tt.month - 1; - start_tm.tm_mday = start_tt.day; - start_tm.tm_hour = start_tt.hour; - start_tm.tm_min = start_tt.minute; - start_tm.tm_sec = start_tt.second; - start_tm.tm_isdst = -1; - start_tm.tm_wday = time_day_of_week (start_tt.day, start_tt.month - 1, - start_tt.year); - - /* Take one off end_time so we don't get an extra day. */ - end_tt = icaltime_from_timet_with_zone (end_time - 1, FALSE, zone); - end_tm.tm_year = end_tt.year - 1900; - end_tm.tm_mon = end_tt.month - 1; - end_tm.tm_mday = end_tt.day; - end_tm.tm_hour = end_tt.hour; - end_tm.tm_min = end_tt.minute; - end_tm.tm_sec = end_tt.second; - end_tm.tm_isdst = -1; - end_tm.tm_wday = time_day_of_week (end_tt.day, end_tt.month - 1, - end_tt.year); - - view = gnome_calendar_get_view (gcal); - - switch (view) { - case GNOME_CAL_DAY_VIEW: - case GNOME_CAL_WORK_WEEK_VIEW: - case GNOME_CAL_WEEK_VIEW: - if (start_tm.tm_year == end_tm.tm_year - && start_tm.tm_mon == end_tm.tm_mon - && start_tm.tm_mday == end_tm.tm_mday) { - e_utf8_strftime (buffer, sizeof (buffer), - _("%A %d %b %Y"), &start_tm); - } else if (start_tm.tm_year == end_tm.tm_year) { - e_utf8_strftime (buffer, sizeof (buffer), - _("%a %d %b"), &start_tm); - e_utf8_strftime (end_buffer, sizeof (end_buffer), - _("%a %d %b %Y"), &end_tm); - strcat (buffer, " - "); - strcat (buffer, end_buffer); - } else { - e_utf8_strftime (buffer, sizeof (buffer), - _("%a %d %b %Y"), &start_tm); - e_utf8_strftime (end_buffer, sizeof (end_buffer), - _("%a %d %b %Y"), &end_tm); - strcat (buffer, " - "); - strcat (buffer, end_buffer); - } - break; - case GNOME_CAL_MONTH_VIEW: - case GNOME_CAL_LIST_VIEW: - if (start_tm.tm_year == end_tm.tm_year) { - if (start_tm.tm_mon == end_tm.tm_mon) { - if (start_tm.tm_mday == end_tm.tm_mday) { - buffer [0] = '\0'; - } else { - e_utf8_strftime (buffer, sizeof (buffer), - "%d", &start_tm); - strcat (buffer, " - "); - } - e_utf8_strftime (end_buffer, sizeof (end_buffer), - _("%d %b %Y"), &end_tm); - strcat (buffer, end_buffer); - } else { - e_utf8_strftime (buffer, sizeof (buffer), - _("%d %b"), &start_tm); - e_utf8_strftime (end_buffer, sizeof (end_buffer), - _("%d %b %Y"), &end_tm); - strcat (buffer, " - "); - strcat (buffer, end_buffer); - } - } else { - e_utf8_strftime (buffer, sizeof (buffer), - _("%d %b %Y"), &start_tm); - e_utf8_strftime (end_buffer, sizeof (end_buffer), - _("%d %b %Y"), &end_tm); - strcat (buffer, " - "); - strcat (buffer, end_buffer); - } - break; - default: - g_return_val_if_reached (NULL); - } - return buffer; -} - -static G_CONST_RETURN gchar * -ea_gnome_calendar_get_name (AtkObject *accessible) -{ - if (accessible->name) - return accessible->name; - return _("Gnome Calendar"); -} - -static G_CONST_RETURN gchar * -ea_gnome_calendar_get_description (AtkObject *accessible) -{ - if (accessible->description) - return accessible->description; - return _("Gnome Calendar"); -} - -static gint -ea_gnome_calendar_get_n_children (AtkObject* obj) -{ - g_return_val_if_fail (EA_IS_GNOME_CALENDAR (obj), 0); - - if (!GTK_ACCESSIBLE (obj)->widget) - return -1; - return 4; -} - -static AtkObject * -ea_gnome_calendar_ref_child (AtkObject *obj, gint i) -{ - AtkObject * child = NULL; - GnomeCalendar * calendarWidget; - GtkWidget *childWidget; - - g_return_val_if_fail (EA_IS_GNOME_CALENDAR (obj), NULL); - /* valid child index range is [0-3] */ - if (i < 0 || i >3 ) - return NULL; - - if (!GTK_ACCESSIBLE (obj)->widget) - return NULL; - calendarWidget = GNOME_CALENDAR (GTK_ACCESSIBLE (obj)->widget); - - switch (i) { - case 0: - /* for the search bar */ - childWidget = gnome_calendar_get_search_bar_widget (calendarWidget); - child = gtk_widget_get_accessible (childWidget); - atk_object_set_parent (child, obj); - atk_object_set_name (child, _("search bar")); - atk_object_set_description (child, _("evolution calendar search bar")); - break; - case 1: - /* for the day/week view */ - childWidget = gnome_calendar_get_current_view_widget (calendarWidget); - child = gtk_widget_get_accessible (childWidget); - atk_object_set_parent (child, obj); - break; - case 2: - /* for calendar */ - childWidget = gnome_calendar_get_e_calendar_widget (calendarWidget); - child = gtk_widget_get_accessible (childWidget); - break; - case 3: - /* for todo list */ - childWidget = GTK_WIDGET (gnome_calendar_get_task_pad (calendarWidget)); - child = gtk_widget_get_accessible (childWidget); - break; - default: - break; - } - if (child) - g_object_ref(child); - return child; -} - -static void -ea_gcal_switch_view_cb (GtkNotebook *widget, GtkNotebookPage *page, - guint index, gpointer data) -{ - GtkWidget *new_widget; - - new_widget = gtk_notebook_get_nth_page (widget, index); - - /* views are always the second child in gnome calendar - */ - if (new_widget) - g_signal_emit_by_name (G_OBJECT(data), "children_changed::add", - 1, gtk_widget_get_accessible (new_widget), NULL); - -#ifdef ACC_DEBUG - printf ("AccDebug: view switch to widget %p (index=%d) \n", - (gpointer)new_widget, index); -#endif -} - -static void -ea_gcal_dates_change_cb (GnomeCalendar *gcal, gpointer data) -{ - const gchar *new_name; - - g_return_if_fail (GNOME_IS_CALENDAR (gcal)); - g_return_if_fail (data); - g_return_if_fail (EA_IS_GNOME_CALENDAR (data)); - - new_name = ea_gnome_calendar_get_label_description (gcal); - atk_object_set_name (ATK_OBJECT(data), new_name); - g_signal_emit_by_name (data, "visible_data_changed"); - -#ifdef ACC_DEBUG - printf ("AccDebug: calendar dates changed, label=%s\n", new_name); -#endif -} diff --git a/calendar/gui/a11y/ea-gnome-calendar.h b/calendar/gui/a11y/ea-gnome-calendar.h deleted file mode 100644 index b0d2cf71d2..0000000000 --- a/calendar/gui/a11y/ea-gnome-calendar.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EA_GNOME_CALENDAR_H__ -#define __EA_GNOME_CALENDAR_H__ - -#include -#include "gnome-cal.h" - -G_BEGIN_DECLS - -#define EA_TYPE_GNOME_CALENDAR (ea_gnome_calendar_get_type ()) -#define EA_GNOME_CALENDAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_GNOME_CALENDAR, EaGnomeCalendar)) -#define EA_GNOME_CALENDAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_GNOME_CALENDAR, EaGnomeCalendarClass)) -#define EA_IS_GNOME_CALENDAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_GNOME_CALENDAR)) -#define EA_IS_GNOME_CALENDAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_GNOME_CALENDAR)) -#define EA_GNOME_CALENDAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_GNOME_CALENDAR, EaGnomeCalendarClass)) - -typedef struct _EaGnomeCalendar EaGnomeCalendar; -typedef struct _EaGnomeCalendarClass EaGnomeCalendarClass; - -struct _EaGnomeCalendar -{ - GtkAccessible parent; -}; - -GType ea_gnome_calendar_get_type (void); - -struct _EaGnomeCalendarClass -{ - GtkAccessibleClass parent_class; -}; - -AtkObject* ea_gnome_calendar_new (GtkWidget *widget); - -const gchar * ea_gnome_calendar_get_label_description (GnomeCalendar *gcal); - -G_END_DECLS - - -#endif /* __EA_GNOME_CALENDAR_H__ */ diff --git a/calendar/gui/a11y/ea-jump-button.c b/calendar/gui/a11y/ea-jump-button.c deleted file mode 100644 index eb24bea42c..0000000000 --- a/calendar/gui/a11y/ea-jump-button.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Yang Wu - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "ea-jump-button.h" -#include "ea-calendar-helpers.h" -#include "ea-week-view.h" -#include "e-week-view.h" -#include -#include - -static void ea_jump_button_class_init (EaJumpButtonClass *klass); - -static G_CONST_RETURN gchar * ea_jump_button_get_name (AtkObject *accessible); -static G_CONST_RETURN gchar * ea_jump_button_get_description (AtkObject *accessible); - -/* action interface */ -static void atk_action_interface_init (AtkActionIface *iface); -static gboolean jump_button_do_action (AtkAction *action, - gint i); -static gint jump_button_get_n_actions (AtkAction *action); -static G_CONST_RETURN gchar * jump_button_get_keybinding (AtkAction *action, - gint i); - -static gpointer parent_class = NULL; - -GType -ea_jump_button_get_type (void) -{ - static GType type = 0; - AtkObjectFactory *factory; - GTypeQuery query; - GType derived_atk_type; - - - if (!type) { - static GTypeInfo tinfo = { - sizeof (EaJumpButtonClass), - (GBaseInitFunc) NULL, /* base init */ - (GBaseFinalizeFunc) NULL, /* base finalize */ - (GClassInitFunc) ea_jump_button_class_init, /* class init */ - (GClassFinalizeFunc) NULL, /* class finalize */ - NULL, /* class data */ - sizeof (EaJumpButton), /* instance size */ - 0, /* nb preallocs */ - (GInstanceInitFunc) NULL, /* instance init */ - NULL /* value table */ - }; - - static const GInterfaceInfo atk_action_info = - { - (GInterfaceInitFunc) atk_action_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - /* - * Figure out the size of the class and instance - * we are run-time deriving from (atk object for GNOME_TYPE_CANVAS_ITEM, in this case) - */ - - factory = atk_registry_get_factory (atk_get_default_registry (), - GNOME_TYPE_CANVAS_ITEM); - derived_atk_type = atk_object_factory_get_accessible_type (factory); - g_type_query (derived_atk_type, &query); - - tinfo.class_size = query.class_size; - tinfo.instance_size = query.instance_size; - - /* we inherit the component and other interfaces from GNOME_TYPE_CANVAS_ITEM */ - type = g_type_register_static (derived_atk_type, - "EaJumpButton", &tinfo, 0); - - g_type_add_interface_static (type, ATK_TYPE_ACTION, - &atk_action_info); - } - - return type; -} - -static void -ea_jump_button_class_init (EaJumpButtonClass *klass) -{ - AtkObjectClass *class = ATK_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - class->get_name = ea_jump_button_get_name; - class->get_description = ea_jump_button_get_description; -} - -AtkObject* -ea_jump_button_new (GObject *obj) -{ - AtkObject *atk_obj = NULL; - GObject *target_obj; - - g_return_val_if_fail (GNOME_IS_CANVAS_ITEM (obj), NULL); - - target_obj = obj; - atk_obj = g_object_get_data (target_obj, "accessible-object"); - - if (!atk_obj) { - static AtkRole event_role = ATK_ROLE_INVALID; - atk_obj = ATK_OBJECT (g_object_new (EA_TYPE_JUMP_BUTTON, - NULL)); - atk_object_initialize (atk_obj, target_obj); - if (event_role == ATK_ROLE_INVALID) - event_role = atk_role_register ("Jump Button"); - atk_obj->role = event_role; - } - - /* the registered factory for GNOME_TYPE_CANVAS_ITEM is cannot create a EaJumpbutton, - * we should save the EaJumpbutton object in it. - */ - g_object_set_data (obj, "accessible-object", atk_obj); - - return atk_obj; -} - -static G_CONST_RETURN gchar * -ea_jump_button_get_name (AtkObject *accessible) -{ - g_return_val_if_fail (EA_IS_JUMP_BUTTON (accessible), NULL); - - if (accessible->name) - return accessible->name; - return _("Jump button"); -} - -static G_CONST_RETURN gchar * -ea_jump_button_get_description (AtkObject *accessible) -{ - if (accessible->description) - return accessible->description; - - return _("Click here, you can find more events."); -} - -static void -atk_action_interface_init (AtkActionIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->do_action = jump_button_do_action; - iface->get_n_actions = jump_button_get_n_actions; - iface->get_keybinding = jump_button_get_keybinding; -} - -static gboolean -jump_button_do_action (AtkAction *action, - gint i) -{ - gboolean return_value = TRUE; - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - GnomeCanvasItem *item; - ECalendarView *cal_view; - EWeekView *week_view; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (action); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - item = GNOME_CANVAS_ITEM (g_obj); - cal_view = ea_calendar_helpers_get_cal_view_from (GNOME_CANVAS_ITEM (item)); - week_view = E_WEEK_VIEW (cal_view); - - switch (i) - { - case 0: - e_week_view_jump_to_button_item (week_view, GNOME_CANVAS_ITEM (item)); - break; - default: - return_value = FALSE; - break; - } - return return_value; -} - -static gint -jump_button_get_n_actions (AtkAction *action) -{ - return 1; -} - -static G_CONST_RETURN gchar * -jump_button_get_keybinding (AtkAction *action, - gint i) -{ - const gchar *return_value = NULL; - - switch (i) - { - case 0: - { - return_value = "space or enter"; - break; - } - default: - break; - } - return return_value; -} diff --git a/calendar/gui/a11y/ea-jump-button.h b/calendar/gui/a11y/ea-jump-button.h deleted file mode 100644 index cd3b6e26bb..0000000000 --- a/calendar/gui/a11y/ea-jump-button.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Yang Wu - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EA_JUMP_BUTTON_H__ -#define __EA_JUMP_BUTTON_H__ - -#include - -G_BEGIN_DECLS - -#define EA_TYPE_JUMP_BUTTON (ea_jump_button_get_type ()) -#define EA_JUMP_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_JUMP_BUTTON, EaJumpButton)) -#define EA_JUMP_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_JUMP_BUTTON, EaJumpButtonClass)) -#define EA_IS_JUMP_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_JUMP_BUTTON)) -#define EA_IS_JUMP_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_JUMP_BUTTON)) -#define EA_JUMP_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_JUMP_BUTTON, EaJumpButtonClass)) - -typedef struct _EaJumpButton EaJumpButton; -typedef struct _EaJumpButtonClass EaJumpButtonClass; - -struct _EaJumpButton -{ - AtkGObjectAccessible parent; -}; - -GType ea_jump_button_get_type (void); - -struct _EaJumpButtonClass -{ - AtkGObjectAccessibleClass parent_class; -}; - -AtkObject *ea_jump_button_new (GObject *obj); - -G_END_DECLS - - -#endif /* __EA_JUMP_BUTTON_H__ */ diff --git a/calendar/gui/a11y/ea-week-view-cell.c b/calendar/gui/a11y/ea-week-view-cell.c deleted file mode 100644 index e724592ec8..0000000000 --- a/calendar/gui/a11y/ea-week-view-cell.c +++ /dev/null @@ -1,478 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * Yang Wu - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "ea-week-view-cell.h" -#include "ea-week-view-main-item.h" -#include "a11y/ea-factory.h" - -/* EWeekViewCell */ - -static void e_week_view_cell_class_init (EWeekViewCellClass *class); - -EA_FACTORY_GOBJECT (EA_TYPE_WEEK_VIEW_CELL, ea_week_view_cell, ea_week_view_cell_new) - -GType -e_week_view_cell_get_type (void) -{ - static GType type = 0; - - if (!type) { - static GTypeInfo tinfo = { - sizeof (EWeekViewCellClass), - (GBaseInitFunc) NULL, /* base init */ - (GBaseFinalizeFunc) NULL, /* base finalize */ - (GClassInitFunc) e_week_view_cell_class_init, /* class init */ - (GClassFinalizeFunc) NULL, /* class finalize */ - NULL, /* class data */ - sizeof (EWeekViewCell), /* instance size */ - 0, /* nb preallocs */ - (GInstanceInitFunc) NULL, /* instance init */ - NULL /* value table */ - }; - - type = g_type_register_static (G_TYPE_OBJECT, - "EWeekViewCell", &tinfo, 0); - } - - return type; -} - -static void -e_week_view_cell_class_init (EWeekViewCellClass *class) -{ - EA_SET_FACTORY (e_week_view_cell_get_type (), ea_week_view_cell); -} - -EWeekViewCell * -e_week_view_cell_new (EWeekView *week_view, gint row, gint column) -{ - GObject *object; - EWeekViewCell *cell; - - g_return_val_if_fail (E_IS_WEEK_VIEW (week_view), NULL); - - object = g_object_new (E_TYPE_WEEK_VIEW_CELL, NULL); - cell = E_WEEK_VIEW_CELL (object); - cell->week_view = week_view; - cell->row = row; - cell->column = column; - -#ifdef ACC_DEBUG - printf ("EvoAcc: e_week_view_cell created %p\n", (gpointer)cell); -#endif - - return cell; -} - -/* EaWeekViewCell */ - -static void ea_week_view_cell_class_init (EaWeekViewCellClass *klass); - -static G_CONST_RETURN gchar * ea_week_view_cell_get_name (AtkObject *accessible); -static G_CONST_RETURN gchar * ea_week_view_cell_get_description (AtkObject *accessible); -static AtkStateSet* ea_week_view_cell_ref_state_set (AtkObject *obj); -static AtkObject * ea_week_view_cell_get_parent (AtkObject *accessible); -static gint ea_week_view_cell_get_index_in_parent (AtkObject *accessible); - -/* component interface */ -static void atk_component_interface_init (AtkComponentIface *iface); -static void component_interface_get_extents (AtkComponent *component, - gint *x, gint *y, - gint *width, gint *height, - AtkCoordType coord_type); -static gboolean component_interface_grab_focus (AtkComponent *component); - -static gpointer parent_class = NULL; - -#ifdef ACC_DEBUG -static gint n_ea_week_view_cell_created = 0, n_ea_week_view_cell_destroyed = 0; -static void ea_week_view_cell_finalize (GObject *object); -#endif - -GType -ea_week_view_cell_get_type (void) -{ - static GType type = 0; - - if (!type) { - static GTypeInfo tinfo = { - sizeof (EaWeekViewCellClass), - (GBaseInitFunc) NULL, /* base init */ - (GBaseFinalizeFunc) NULL, /* base finalize */ - (GClassInitFunc) ea_week_view_cell_class_init, /* class init */ - (GClassFinalizeFunc) NULL, /* class finalize */ - NULL, /* class data */ - sizeof (EaWeekViewCell), /* instance size */ - 0, /* nb preallocs */ - (GInstanceInitFunc) NULL, /* instance init */ - NULL /* value table */ - }; - - static const GInterfaceInfo atk_component_info = { - (GInterfaceInitFunc) atk_component_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - type = g_type_register_static (ATK_TYPE_GOBJECT_ACCESSIBLE, - "EaWeekViewCell", &tinfo, 0); - g_type_add_interface_static (type, ATK_TYPE_COMPONENT, - &atk_component_info); - - } - - return type; -} - -static void -ea_week_view_cell_class_init (EaWeekViewCellClass *klass) -{ - AtkObjectClass *class = ATK_OBJECT_CLASS (klass); - -#ifdef ACC_DEBUG - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = ea_week_view_cell_finalize; -#endif - - parent_class = g_type_class_peek_parent (klass); - - class->get_name = ea_week_view_cell_get_name; - class->get_description = ea_week_view_cell_get_description; - class->ref_state_set = ea_week_view_cell_ref_state_set; - - class->get_parent = ea_week_view_cell_get_parent; - class->get_index_in_parent = ea_week_view_cell_get_index_in_parent; - -} - -AtkObject* -ea_week_view_cell_new (GObject *obj) -{ - gpointer object; - AtkObject *atk_object; - - g_return_val_if_fail (E_IS_WEEK_VIEW_CELL (obj), NULL); - object = g_object_new (EA_TYPE_WEEK_VIEW_CELL, NULL); - atk_object = ATK_OBJECT (object); - atk_object_initialize (atk_object, obj); - atk_object->role = ATK_ROLE_UNKNOWN; - -#ifdef ACC_DEBUG - ++n_ea_week_view_cell_created; - printf ("ACC_DEBUG: n_ea_week_view_cell_created = %d\n", - n_ea_week_view_cell_created); -#endif - return atk_object; -} - -#ifdef ACC_DEBUG -static void ea_week_view_cell_finalize (GObject *object) -{ - G_OBJECT_CLASS (parent_class)->finalize (object); - - ++n_ea_week_view_cell_destroyed; - printf ("ACC_DEBUG: n_ea_week_view_cell_destroyed = %d\n", - n_ea_week_view_cell_destroyed); -} -#endif - -static G_CONST_RETURN gchar * -ea_week_view_cell_get_name (AtkObject *accessible) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewCell *cell; - - g_return_val_if_fail (EA_IS_WEEK_VIEW_CELL (accessible), NULL); - - if (!accessible->name) { - AtkObject *ea_main_item; - GnomeCanvasItem *main_item; - gchar *new_name = g_strdup (""); - const gchar *row_label, *column_label; - gint new_column, new_row; - gint start_day; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return NULL; - - cell = E_WEEK_VIEW_CELL (g_obj); - main_item = cell->week_view->main_canvas_item; - ea_main_item = atk_gobject_accessible_for_object (G_OBJECT (main_item)); - - start_day = cell->week_view->display_start_day; - if (cell->column + start_day >= 7) { - new_column = cell->column + start_day - 7; - new_row = cell->row + 1; - } else { - new_column = cell->column + start_day; - new_row = cell->row; - } - - column_label = atk_table_get_column_description (ATK_TABLE (ea_main_item), - new_column); - row_label = atk_table_get_row_description (ATK_TABLE (ea_main_item), - new_row); - new_name = g_strconcat (column_label, " ", row_label, NULL); - ATK_OBJECT_CLASS (parent_class)->set_name (accessible, new_name); - g_free (new_name); - } - return accessible->name; -} - -static G_CONST_RETURN gchar * -ea_week_view_cell_get_description (AtkObject *accessible) -{ - return ea_week_view_cell_get_name (accessible); -} - -static AtkStateSet* -ea_week_view_cell_ref_state_set (AtkObject *obj) -{ - AtkStateSet *state_set; - GObject *g_obj; - AtkObject *parent; - gint x, y, width, height; - gint parent_x, parent_y, parent_width, parent_height; - - state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (obj); - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(obj)); - if (!g_obj) - return state_set; - - atk_state_set_add_state (state_set, ATK_STATE_SELECTABLE); - - parent = atk_object_get_parent (obj); - atk_component_get_extents (ATK_COMPONENT (obj), &x, &y, - &width, &height, ATK_XY_WINDOW); - atk_component_get_extents (ATK_COMPONENT (parent), &parent_x, &parent_y, - &parent_width, &parent_height, ATK_XY_WINDOW); - - - if (x + width < parent_x || x > parent_x + parent_width || - y + height < parent_y || y > parent_y + parent_height) - /* the cell is out of the main canvas */ - ; - else - atk_state_set_add_state (state_set, ATK_STATE_VISIBLE); - - return state_set; -} - -static AtkObject * -ea_week_view_cell_get_parent (AtkObject *accessible) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewCell *cell; - - g_return_val_if_fail (EA_IS_WEEK_VIEW_CELL (accessible), NULL); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return NULL; - - cell = E_WEEK_VIEW_CELL (g_obj); - return atk_gobject_accessible_for_object (G_OBJECT (cell->week_view->main_canvas_item)); -} - -static gint -ea_week_view_cell_get_index_in_parent (AtkObject *accessible) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewCell *cell; - AtkObject *parent; - - g_return_val_if_fail (EA_IS_WEEK_VIEW_CELL (accessible), -1); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - cell = E_WEEK_VIEW_CELL (g_obj); - parent = atk_object_get_parent (accessible); - return atk_table_get_index_at (ATK_TABLE (parent), - cell->row, cell->column); -} - -/* Atk Component Interface */ - -static void -atk_component_interface_init (AtkComponentIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->get_extents = component_interface_get_extents; - iface->grab_focus = component_interface_grab_focus; -} - -static void -component_interface_get_extents (AtkComponent *component, - gint *x, gint *y, gint *width, gint *height, - AtkCoordType coord_type) -{ - GObject *g_obj; - AtkObject *atk_obj; - EWeekViewCell *cell; - EWeekView *week_view; - GtkWidget *main_canvas; - gint week_view_width, week_view_height; - gint scroll_x, scroll_y; - gint start_day; - - *x = *y = *width = *height = 0; - - g_return_if_fail (EA_IS_WEEK_VIEW_CELL (component)); - - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(component)); - if (!g_obj) - /* defunct object*/ - return; - - cell = E_WEEK_VIEW_CELL (g_obj); - week_view = cell->week_view; - main_canvas = cell->week_view->main_canvas; - - atk_obj = atk_gobject_accessible_for_object (G_OBJECT (main_canvas)); - atk_component_get_extents (ATK_COMPONENT (atk_obj), - x, y, - &week_view_width, &week_view_height, - coord_type); - gnome_canvas_get_scroll_offsets (GNOME_CANVAS (week_view->main_canvas), - &scroll_x, &scroll_y); - start_day = week_view->display_start_day; - if (week_view->multi_week_view) { - if (week_view->compress_weekend && (cell->column == (5 - start_day))) { - *height = week_view->row_heights[cell->row*2]; - *width = week_view->col_widths[cell->column]; - *x += week_view->col_offsets[cell->column] - scroll_x; - *y += week_view->row_offsets[cell->row*2]- scroll_y; - } else if (week_view->compress_weekend && (cell->column == (6 - start_day))) { - *height = week_view->row_heights[cell->row*2]; - *width = week_view->col_widths[cell->column - 1]; - *x += week_view->col_offsets[cell->column - 1]- scroll_x; - *y += week_view->row_offsets[cell->row*2 + 1]- scroll_y; - } else if (week_view->compress_weekend && (cell->column > (6 - start_day))){ - *height = week_view->row_heights[cell->row*2]*2; - *width = week_view->col_widths[cell->column - 1]; - *x += week_view->col_offsets[cell->column - 1] - scroll_x; - *y += week_view->row_offsets[cell->row*2]- scroll_y; - } else { - *height = week_view->row_heights[cell->row*2]*2; - *width = week_view->col_widths[cell->column]; - *x += week_view->col_offsets[cell->column] - scroll_x; - *y += week_view->row_offsets[cell->row*2]- scroll_y; - } - } else { - if (start_day < 3) { - if (cell->column < 3) { - *height = week_view->row_heights[cell->column*2]*2; - *width = week_view->col_widths[0]; - *x += week_view->col_offsets[0] - scroll_x; - *y += week_view->row_offsets[cell->column*2]- scroll_y; - } else { - if (cell->column == 5 - start_day) { - *height = week_view->row_heights[(cell->column - 3)*2]; - *width = week_view->col_widths[1]; - *x += week_view->col_offsets[1] - scroll_x; - *y += week_view->row_offsets[(cell->column - 3)*2]- scroll_y; - } else if (cell->column == 6 - start_day) { - *height = week_view->row_heights[(cell->column - 4)*2]; - *width = week_view->col_widths[1]; - *x += week_view->col_offsets[1] - scroll_x; - *y += week_view->row_offsets[(cell->column - 3)*2 - 1]- scroll_y; - } else if (cell->column > 6 - start_day) { - *height = week_view->row_heights[(cell->column - 4)*2]*2; - *width = week_view->col_widths[1]; - *x += week_view->col_offsets[1] - scroll_x; - *y += week_view->row_offsets[(cell->column - 4)*2]- scroll_y; - } else { - *height = week_view->row_heights[(cell->column - 3)*2]*2; - *width = week_view->col_widths[1]; - *x += week_view->col_offsets[1] - scroll_x; - *y += week_view->row_offsets[(cell->column - 3)*2]- scroll_y; - } - } - } else if (cell->column < 4) { - if (cell->column == 5 - start_day) { - *height = week_view->row_heights[cell->column*2]; - *width = week_view->col_widths[0]; - *x += week_view->col_offsets[0] - scroll_x; - *y += week_view->row_offsets[cell->column*2]- scroll_y; - } else if (cell->column == 6 - start_day) { - *height = week_view->row_heights[(cell->column - 1)*2]; - *width = week_view->col_widths[0]; - *x += week_view->col_offsets[0] - scroll_x; - *y += week_view->row_offsets[cell->column*2 - 1]- scroll_y; - } else if (cell->column > 6 - start_day) { - *height = week_view->row_heights[(cell->column - 1)*2]*2; - *width = week_view->col_widths[0]; - *x += week_view->col_offsets[0] - scroll_x; - *y += week_view->row_offsets[(cell->column - 1)*2]- scroll_y; - } else { - *height = week_view->row_heights[(cell->column)*2]*2; - *width = week_view->col_widths[0]; - *x += week_view->col_offsets[0] - scroll_x; - *y += week_view->row_offsets[cell->column*2]- scroll_y; - } - } else { - *height = week_view->row_heights[(cell->column - 4)*2]*2; - *width = week_view->col_widths[1]; - *x += week_view->col_offsets[1] - scroll_x; - *y += week_view->row_offsets[(cell->column - 4)*2]- scroll_y; - } - } -} - -static gboolean -component_interface_grab_focus (AtkComponent *comp) -{ - GObject *g_obj; - EWeekViewCell *cell; - EWeekView *week_view; - GtkWidget *toplevel; - - g_return_val_if_fail (EA_IS_WEEK_VIEW_CELL (comp), FALSE); - - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (comp)); - if (!g_obj) - return FALSE; - - cell = E_WEEK_VIEW_CELL (g_obj); - week_view = cell->week_view; - - week_view->selection_start_day = cell->row * 7 + cell->column; - week_view->selection_end_day = cell->row * 7 + cell->column; - gtk_widget_queue_draw (week_view->main_canvas); - - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (week_view)); - if (GTK_WIDGET_TOPLEVEL (toplevel)) - gtk_window_present (GTK_WINDOW (toplevel)); - - return TRUE; -} diff --git a/calendar/gui/a11y/ea-week-view-cell.h b/calendar/gui/a11y/ea-week-view-cell.h deleted file mode 100644 index 1524e9d3a8..0000000000 --- a/calendar/gui/a11y/ea-week-view-cell.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * Yang Wu - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EA_WEEK_VIEW_CELL_H__ -#define __EA_WEEK_VIEW_CELL_H__ - -#include -#include "e-week-view.h" - -G_BEGIN_DECLS - -#define E_TYPE_WEEK_VIEW_CELL (e_week_view_cell_get_type ()) -#define E_WEEK_VIEW_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_WEEK_VIEW_CELL, EWeekViewCell)) -#define E_WEEK_VIEW_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_WEEK_VIEW_CELL, EWeekViewCellClass)) -#define E_IS_WEEK_VIEW_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_WEEK_VIEW_CELL)) -#define E_IS_WEEK_VIEW_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_WEEK_VIEW_CELL)) -#define E_WEEK_VIEW_CELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_WEEK_VIEW_CELL, EWeekViewCellClass)) - -typedef struct _EWeekViewCell EWeekViewCell; -typedef struct _EWeekViewCellClass EWeekViewCellClass; - -struct _EWeekViewCell -{ - GObject parent; - EWeekView *week_view; - gint row; - gint column; -}; - -GType e_week_view_cell_get_type (void); - -struct _EWeekViewCellClass -{ - GObjectClass parent_class; -}; - -EWeekViewCell * e_week_view_cell_new (EWeekView *week_view, gint row, gint column); - -#define EA_TYPE_WEEK_VIEW_CELL (ea_week_view_cell_get_type ()) -#define EA_WEEK_VIEW_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_WEEK_VIEW_CELL, EaWeekViewCell)) -#define EA_WEEK_VIEW_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_WEEK_VIEW_CELL, EaWeekViewCellClass)) -#define EA_IS_WEEK_VIEW_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_WEEK_VIEW_CELL)) -#define EA_IS_WEEK_VIEW_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_WEEK_VIEW_CELL)) -#define EA_WEEK_VIEW_CELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_WEEK_VIEW_CELL, EaWeekViewCellClass)) - -typedef struct _EaWeekViewCell EaWeekViewCell; -typedef struct _EaWeekViewCellClass EaWeekViewCellClass; - -struct _EaWeekViewCell -{ - AtkGObjectAccessible parent; -}; - -GType ea_week_view_cell_get_type (void); - -struct _EaWeekViewCellClass -{ - AtkGObjectAccessibleClass parent_class; -}; - -AtkObject* ea_week_view_cell_new (GObject *gobj); - -G_END_DECLS - -#endif /* __EA_WEEK_VIEW_CELL_H__ */ diff --git a/calendar/gui/a11y/ea-week-view-main-item.c b/calendar/gui/a11y/ea-week-view-main-item.c deleted file mode 100644 index 74f4695a69..0000000000 --- a/calendar/gui/a11y/ea-week-view-main-item.c +++ /dev/null @@ -1,1247 +0,0 @@ -/* - * Evolution Accessibility: ea-week-view-main-item.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "ea-week-view-main-item.h" -#include "ea-week-view.h" -#include "ea-week-view-cell.h" -#include "ea-cell-table.h" -#include - -/* EaWeekViewMainItem */ -static void ea_week_view_main_item_class_init (EaWeekViewMainItemClass *klass); - -static void ea_week_view_main_item_finalize (GObject *object); -static G_CONST_RETURN gchar * ea_week_view_main_item_get_name (AtkObject *accessible); -static G_CONST_RETURN gchar * ea_week_view_main_item_get_description (AtkObject *accessible); - -static gint ea_week_view_main_item_get_n_children (AtkObject *obj); -static AtkObject* ea_week_view_main_item_ref_child (AtkObject *obj, - gint i); -static AtkObject * ea_week_view_main_item_get_parent (AtkObject *accessible); -static gint ea_week_view_main_item_get_index_in_parent (AtkObject *accessible); - -/* callbacks */ -static void ea_week_view_main_item_dates_change_cb (GnomeCalendar *gcal, gpointer data); -static void ea_week_view_main_item_time_change_cb (EWeekView *week_view, gpointer data); - -/* component interface */ -static void atk_component_interface_init (AtkComponentIface *iface); -static void component_interface_get_extents (AtkComponent *component, - gint *x, gint *y, - gint *width, gint *height, - AtkCoordType coord_type); - -/* atk table interface */ -static void atk_table_interface_init (AtkTableIface *iface); -static gint table_interface_get_index_at (AtkTable *table, - gint row, - gint column); -static gint table_interface_get_column_at_index (AtkTable *table, - gint index); -static gint table_interface_get_row_at_index (AtkTable *table, - gint index); -static AtkObject* table_interface_ref_at (AtkTable *table, - gint row, - gint column); -static gint table_interface_get_n_rows (AtkTable *table); -static gint table_interface_get_n_columns (AtkTable *table); -static gint table_interface_get_column_extent_at (AtkTable *table, - gint row, - gint column); -static gint table_interface_get_row_extent_at (AtkTable *table, - gint row, - gint column); - -static gboolean table_interface_is_row_selected (AtkTable *table, - gint row); -static gboolean table_interface_is_column_selected (AtkTable *table, - gint row); -static gboolean table_interface_is_selected (AtkTable *table, - gint row, - gint column); -static gint table_interface_get_selected_rows (AtkTable *table, - gint **rows_selected); -static gint table_interface_get_selected_columns (AtkTable *table, - gint **columns_selected); -static gboolean table_interface_add_row_selection (AtkTable *table, gint row); -static gboolean table_interface_remove_row_selection (AtkTable *table, - gint row); -static gboolean table_interface_add_column_selection (AtkTable *table, - gint column); -static gboolean table_interface_remove_column_selection (AtkTable *table, - gint column); -static AtkObject* table_interface_get_row_header (AtkTable *table, gint row); -static AtkObject* table_interface_get_column_header (AtkTable *table, - gint in_col); -static AtkObject* table_interface_get_caption (AtkTable *table); - -static G_CONST_RETURN gchar * -table_interface_get_column_description (AtkTable *table, gint in_col); - -static G_CONST_RETURN gchar * -table_interface_get_row_description (AtkTable *table, gint row); - -static AtkObject* table_interface_get_summary (AtkTable *table); - -/* atk selection interface */ -static void atk_selection_interface_init (AtkSelectionIface *iface); -static gboolean selection_interface_add_selection (AtkSelection *selection, - gint i); -static gboolean selection_interface_clear_selection (AtkSelection *selection); -static AtkObject* selection_interface_ref_selection (AtkSelection *selection, - gint i); -static gint selection_interface_get_selection_count (AtkSelection *selection); -static gboolean selection_interface_is_child_selected (AtkSelection *selection, - gint i); - -/* helpers */ -static EaCellTable * -ea_week_view_main_item_get_cell_data (EaWeekViewMainItem *ea_main_item); - -static void -ea_week_view_main_item_destory_cell_data (EaWeekViewMainItem *ea_main_item); - -static gint -ea_week_view_main_item_get_child_index_at (EaWeekViewMainItem *ea_main_item, - gint row, gint column); -static gint -ea_week_view_main_item_get_row_at_index (EaWeekViewMainItem *ea_main_item, - gint index); -static gint -ea_week_view_main_item_get_column_at_index (EaWeekViewMainItem *ea_main_item, - gint index); -static gint -ea_week_view_main_item_get_row_label (EaWeekViewMainItem *ea_main_item, - gint row, gchar *buffer, - gint buffer_size); - -#ifdef ACC_DEBUG -static gint n_ea_week_view_main_item_created = 0; -static gint n_ea_week_view_main_item_destroyed = 0; -#endif - -static gpointer parent_class = NULL; - -GType -ea_week_view_main_item_get_type (void) -{ - static GType type = 0; - AtkObjectFactory *factory; - GTypeQuery query; - GType derived_atk_type; - - if (!type) { - static GTypeInfo tinfo = { - sizeof (EaWeekViewMainItemClass), - (GBaseInitFunc) NULL, /* base init */ - (GBaseFinalizeFunc) NULL, /* base finalize */ - (GClassInitFunc) ea_week_view_main_item_class_init, - (GClassFinalizeFunc) NULL, /* class finalize */ - NULL, /* class data */ - sizeof (EaWeekViewMainItem), /* instance size */ - 0, /* nb preallocs */ - (GInstanceInitFunc) NULL, /* instance init */ - NULL /* value table */ - }; - - static const GInterfaceInfo atk_component_info = { - (GInterfaceInitFunc) atk_component_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - static const GInterfaceInfo atk_table_info = { - (GInterfaceInitFunc) atk_table_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - static const GInterfaceInfo atk_selection_info = { - (GInterfaceInitFunc) atk_selection_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - - /* - * Figure out the size of the class and instance - * we are run-time deriving from (GailCanvasItem, in this case) - * - */ - - factory = atk_registry_get_factory (atk_get_default_registry (), - e_week_view_main_item_get_type()); - derived_atk_type = atk_object_factory_get_accessible_type (factory); - g_type_query (derived_atk_type, &query); - - tinfo.class_size = query.class_size; - tinfo.instance_size = query.instance_size; - - type = g_type_register_static (derived_atk_type, - "EaWeekViewMainItem", &tinfo, 0); - g_type_add_interface_static (type, ATK_TYPE_COMPONENT, - &atk_component_info); - g_type_add_interface_static (type, ATK_TYPE_TABLE, - &atk_table_info); - g_type_add_interface_static (type, ATK_TYPE_SELECTION, - &atk_selection_info); - } - - return type; -} - -static void -ea_week_view_main_item_class_init (EaWeekViewMainItemClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - AtkObjectClass *class = ATK_OBJECT_CLASS (klass); - - gobject_class->finalize = ea_week_view_main_item_finalize; - parent_class = g_type_class_peek_parent (klass); - - class->get_name = ea_week_view_main_item_get_name; - class->get_description = ea_week_view_main_item_get_description; - - class->get_n_children = ea_week_view_main_item_get_n_children; - class->ref_child = ea_week_view_main_item_ref_child; - class->get_parent = ea_week_view_main_item_get_parent; - class->get_index_in_parent = ea_week_view_main_item_get_index_in_parent; -} - -AtkObject* -ea_week_view_main_item_new (GObject *obj) -{ - AtkObject *accessible; - GnomeCalendar *gcal; - EWeekViewMainItem *main_item; - - g_return_val_if_fail (E_IS_WEEK_VIEW_MAIN_ITEM (obj), NULL); - - accessible = ATK_OBJECT (g_object_new (EA_TYPE_WEEK_VIEW_MAIN_ITEM, - NULL)); - - atk_object_initialize (accessible, obj); - accessible->role = ATK_ROLE_TABLE; - -#ifdef ACC_DEBUG - ++n_ea_week_view_main_item_created; - printf ("ACC_DEBUG: n_ea_week_view_main_item_created = %d\n", - n_ea_week_view_main_item_created); -#endif - main_item = E_WEEK_VIEW_MAIN_ITEM (obj); - g_signal_connect (main_item->week_view, "selected_time_changed", - G_CALLBACK (ea_week_view_main_item_time_change_cb), - accessible); - - /* listen for date changes of calendar */ - gcal = e_calendar_view_get_calendar (E_CALENDAR_VIEW (main_item->week_view)); - if (gcal) - g_signal_connect (gcal, "dates_shown_changed", - G_CALLBACK (ea_week_view_main_item_dates_change_cb), - accessible); - - return accessible; -} - -static void -ea_week_view_main_item_finalize (GObject *object) -{ - EaWeekViewMainItem *ea_main_item; - - g_return_if_fail (EA_IS_WEEK_VIEW_MAIN_ITEM (object)); - - ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (object); - - /* Free the allocated cell data */ - ea_week_view_main_item_destory_cell_data (ea_main_item); - - G_OBJECT_CLASS (parent_class)->finalize (object); -#ifdef ACC_DEBUG - ++n_ea_week_view_main_item_destroyed; - printf ("ACC_DEBUG: n_ea_week_view_main_item_destroyed = %d\n", - n_ea_week_view_main_item_destroyed); -#endif -} - -static G_CONST_RETURN gchar * -ea_week_view_main_item_get_name (AtkObject *accessible) -{ - AtkObject *parent; - g_return_val_if_fail (EA_IS_WEEK_VIEW_MAIN_ITEM (accessible), NULL); - parent = atk_object_get_parent (accessible); - return atk_object_get_name (parent); - -} - -static G_CONST_RETURN gchar * -ea_week_view_main_item_get_description (AtkObject *accessible) -{ - return _("a table to view and select the current time range"); -} - -static gint -ea_week_view_main_item_get_n_children (AtkObject *accessible) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewMainItem *main_item; - EWeekView *week_view; - - g_return_val_if_fail (EA_IS_WEEK_VIEW_MAIN_ITEM (accessible), -1); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); - week_view = main_item->week_view; - - if (week_view->multi_week_view) - return 7 * week_view->weeks_shown; - else - return 7; -} - -static AtkObject * -ea_week_view_main_item_ref_child (AtkObject *accessible, gint index) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewMainItem *main_item; - EWeekView *week_view; - gint n_children; - EWeekViewCell *cell; - EaCellTable *cell_data; - EaWeekViewMainItem *ea_main_item; - - g_return_val_if_fail (EA_IS_WEEK_VIEW_MAIN_ITEM (accessible), NULL); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return NULL; - - main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); - week_view = main_item->week_view; - - n_children = ea_week_view_main_item_get_n_children (accessible); - if (index < 0 || index >= n_children) - return NULL; - - ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (accessible); - cell_data = ea_week_view_main_item_get_cell_data (ea_main_item); - if (!cell_data) - return NULL; - cell = ea_cell_table_get_cell_at_index (cell_data, index); - if (!cell) { - gint row, column; - - row = ea_week_view_main_item_get_row_at_index (ea_main_item, index); - column = ea_week_view_main_item_get_column_at_index (ea_main_item, index); - cell = e_week_view_cell_new (week_view, row, column); - ea_cell_table_set_cell_at_index (cell_data, index, cell); - g_object_unref (cell); - } - - return g_object_ref (atk_gobject_accessible_for_object (G_OBJECT(cell))); -} - -static AtkObject * -ea_week_view_main_item_get_parent (AtkObject *accessible) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewMainItem *main_item; - - g_return_val_if_fail (EA_IS_WEEK_VIEW_MAIN_ITEM (accessible), NULL); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return NULL; - - main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); - return gtk_widget_get_accessible (GTK_WIDGET (main_item->week_view)); -} - -static gint -ea_week_view_main_item_get_index_in_parent (AtkObject *accessible) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - - g_return_val_if_fail (EA_IS_WEEK_VIEW_MAIN_ITEM (accessible), -1); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - /* always the first child of ea-week-view */ - return 0; -} - -/* callbacks */ - -static void -ea_week_view_main_item_dates_change_cb (GnomeCalendar *gcal, gpointer data) -{ - EaWeekViewMainItem *ea_main_item; - - g_return_if_fail (GNOME_IS_CALENDAR (gcal)); - g_return_if_fail (data); - g_return_if_fail (EA_IS_WEEK_VIEW_MAIN_ITEM (data)); - - ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (data); - -#ifdef ACC_DEBUG - printf ("EvoAcc: ea_week_view_main_item update cb\n"); -#endif - - ea_week_view_main_item_destory_cell_data (ea_main_item); -} - -static void -ea_week_view_main_item_time_change_cb (EWeekView *week_view, gpointer data) -{ - EaWeekViewMainItem *ea_main_item; - AtkObject *item_cell = NULL; - - g_return_if_fail (E_IS_WEEK_VIEW (week_view)); - g_return_if_fail (data); - g_return_if_fail (EA_IS_WEEK_VIEW_MAIN_ITEM (data)); - - ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (data); - -#ifdef ACC_DEBUG - printf ("EvoAcc: ea_week_view_main_item time changed cb\n"); -#endif - /* only deal with the first selected child, for now */ - item_cell = atk_selection_ref_selection (ATK_SELECTION (ea_main_item), - 0); - if (item_cell) { - AtkStateSet *state_set; - state_set = atk_object_ref_state_set (item_cell); - atk_state_set_add_state (state_set, ATK_STATE_FOCUSED); - g_object_unref (state_set); - - g_signal_emit_by_name (ea_main_item, - "active-descendant-changed", - item_cell); - g_signal_emit_by_name (data, "selection_changed"); - atk_focus_tracker_notify (item_cell); - g_object_unref (item_cell); - } -} - -/* helpers */ - -static gint -ea_week_view_main_item_get_child_index_at (EaWeekViewMainItem *ea_main_item, - gint row, gint column) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewMainItem *main_item; - EWeekView *week_view; - - g_return_val_if_fail (ea_main_item, -1); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); - week_view = main_item->week_view; - - if (row >= 0 && row < week_view->weeks_shown && - column >= 0 && column < 7) - return row * 7 + column; - - return -1; -} - -static gint -ea_week_view_main_item_get_row_at_index (EaWeekViewMainItem *ea_main_item, - gint index) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - gint n_children; - - g_return_val_if_fail (ea_main_item, -1); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - n_children = ea_week_view_main_item_get_n_children (ATK_OBJECT (ea_main_item)); - if (index >= 0 && index < n_children) - return index / 7; - return -1; -} - -static gint -ea_week_view_main_item_get_column_at_index (EaWeekViewMainItem *ea_main_item, - gint index) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - gint n_children; - - g_return_val_if_fail (ea_main_item, -1); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - n_children = ea_week_view_main_item_get_n_children (ATK_OBJECT (ea_main_item)); - if (index >= 0 && index < n_children) - return index % 7; - return -1; -} - -static gint -ea_week_view_main_item_get_row_label (EaWeekViewMainItem *ea_main_item, - gint row, gchar *buffer, gint buffer_size) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - - g_return_val_if_fail (ea_main_item, 0); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return 0; - - return g_snprintf (buffer, buffer_size, "the %i week", - row + 1); - -} - -static EaCellTable * -ea_week_view_main_item_get_cell_data (EaWeekViewMainItem *ea_main_item) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewMainItem *main_item; - EWeekView *week_view; - EaCellTable *cell_data; - - g_return_val_if_fail (ea_main_item, NULL); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return NULL; - - main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); - week_view = main_item->week_view; - - cell_data = g_object_get_data (G_OBJECT(ea_main_item), - "ea-week-view-cell-table"); - if (!cell_data) { - cell_data = ea_cell_table_create (week_view->weeks_shown, 7, TRUE); - g_object_set_data (G_OBJECT(ea_main_item), - "ea-week-view-cell-table", cell_data); - } - return cell_data; -} - -static void -ea_week_view_main_item_destory_cell_data (EaWeekViewMainItem *ea_main_item) -{ - EaCellTable *cell_data; - - g_return_if_fail (ea_main_item); - - cell_data = g_object_get_data (G_OBJECT(ea_main_item), - "ea-week-view-cell-table"); - if (cell_data) { - g_object_set_data (G_OBJECT(ea_main_item), - "ea-week-view-cell-table", NULL); - ea_cell_table_destroy (cell_data); - } -} - -/* Atk Component Interface */ - -static void -atk_component_interface_init (AtkComponentIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->get_extents = component_interface_get_extents; -} - -static void -component_interface_get_extents (AtkComponent *component, - gint *x, gint *y, gint *width, gint *height, - AtkCoordType coord_type) -{ - GObject *g_obj; - AtkObject *ea_canvas; - EWeekViewMainItem *main_item; - EWeekView *week_view; - - *x = *y = *width = *height = 0; - - g_return_if_fail (EA_IS_WEEK_VIEW_MAIN_ITEM (component)); - - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(component)); - if (!g_obj) - /* defunct object*/ - return; - main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); - week_view = main_item->week_view; - - ea_canvas = gtk_widget_get_accessible (week_view->main_canvas); - atk_component_get_extents (ATK_COMPONENT (ea_canvas), x, y, - width, height, coord_type); -} - -/* atk table interface */ - -static void -atk_table_interface_init (AtkTableIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->ref_at = table_interface_ref_at; - - iface->get_n_rows = table_interface_get_n_rows; - iface->get_n_columns = table_interface_get_n_columns; - iface->get_index_at = table_interface_get_index_at; - iface->get_column_at_index = table_interface_get_column_at_index; - iface->get_row_at_index = table_interface_get_row_at_index; - iface->get_column_extent_at = table_interface_get_column_extent_at; - iface->get_row_extent_at = table_interface_get_row_extent_at; - - iface->is_selected = table_interface_is_selected; - iface->get_selected_rows = table_interface_get_selected_rows; - iface->get_selected_columns = table_interface_get_selected_columns; - iface->is_row_selected = table_interface_is_row_selected; - iface->is_column_selected = table_interface_is_column_selected; - iface->add_row_selection = table_interface_add_row_selection; - iface->remove_row_selection = table_interface_remove_row_selection; - iface->add_column_selection = table_interface_add_column_selection; - iface->remove_column_selection = table_interface_remove_column_selection; - - iface->get_row_header = table_interface_get_row_header; - iface->get_column_header = table_interface_get_column_header; - iface->get_caption = table_interface_get_caption; - iface->get_summary = table_interface_get_summary; - iface->get_row_description = table_interface_get_row_description; - iface->get_column_description = table_interface_get_column_description; -} - -static AtkObject* -table_interface_ref_at (AtkTable *table, - gint row, - gint column) -{ - gint index; - - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); - index = ea_week_view_main_item_get_child_index_at (ea_main_item, - row, column); - return ea_week_view_main_item_ref_child (ATK_OBJECT (ea_main_item), index); -} - -static gint -table_interface_get_n_rows (AtkTable *table) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewMainItem *main_item; - EWeekView *week_view; - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); - week_view = main_item->week_view; - - return week_view->weeks_shown; -} - -static gint -table_interface_get_n_columns (AtkTable *table) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - return 7; -} - -static gint -table_interface_get_index_at (AtkTable *table, - gint row, - gint column) -{ - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); - return ea_week_view_main_item_get_child_index_at (ea_main_item, - row, column); -} - -static gint -table_interface_get_column_at_index (AtkTable *table, - gint index) -{ - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); - return ea_week_view_main_item_get_column_at_index (ea_main_item, index); -} - -static gint -table_interface_get_row_at_index (AtkTable *table, - gint index) -{ - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); - return ea_week_view_main_item_get_row_at_index (ea_main_item, index); -} - -static gint -table_interface_get_column_extent_at (AtkTable *table, - gint row, - gint column) -{ - gint index; - gint width = 0, height = 0; - AtkObject *child; - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); - - index = ea_week_view_main_item_get_child_index_at (ea_main_item, - row, column); - child = atk_object_ref_accessible_child (ATK_OBJECT (ea_main_item), - index); - if (child) - atk_component_get_size (ATK_COMPONENT (child), - &width, &height); - - return width; -} - -static gint -table_interface_get_row_extent_at (AtkTable *table, - gint row, - gint column) -{ - gint index; - gint width = 0, height = 0; - AtkObject *child; - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); - - index = ea_week_view_main_item_get_child_index_at (ea_main_item, - row, column); - child = atk_object_ref_accessible_child (ATK_OBJECT (ea_main_item), - index); - if (child) - atk_component_get_size (ATK_COMPONENT (child), - &width, &height); - - return height; -} - -static gboolean -table_interface_is_row_selected (AtkTable *table, - gint row) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewMainItem *main_item; - EWeekView *week_view; - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); - week_view = main_item->week_view; - - if (week_view->selection_start_day == -1) - /* no selection */ - return FALSE; - if ((row < 0)&&(row + 1 > week_view->weeks_shown )) - return FALSE; - if (((week_view->selection_start_day < row*7)&&(week_view->selection_end_dayselection_start_day > row*7+6)&&(week_view->selection_end_day > row*7+6))) - return FALSE; - else - return TRUE; -} - -static gboolean -table_interface_is_selected (AtkTable *table, - gint row, - gint column) -{ - return table_interface_is_row_selected (table, row) && table_interface_is_column_selected(table, column); -} - -static gboolean -table_interface_is_column_selected (AtkTable *table, - gint column) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewMainItem *main_item; - EWeekView *week_view; - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); - week_view = main_item->week_view; - - if ((column <0)||(column >6)) - return FALSE; - else { - gint i; - for (i=0;iweeks_shown;i++) - if ((column + i*7>= week_view->selection_start_day ) && - (column + i*7<= week_view->selection_end_day)) - return TRUE; - return FALSE; - } -} - -static gint -table_interface_get_selected_rows (AtkTable *table, - gint **rows_selected) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewMainItem *main_item; - EWeekView *week_view; - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); - gint start_row = -1, n_rows = 0; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); - week_view = main_item->week_view; - - if (week_view->selection_start_day == -1) - return 0; - - start_row = week_view->selection_start_day; - n_rows = week_view->selection_end_day - start_row + 1; - - if (n_rows > 0 && start_row != -1 && rows_selected) { - gint index; - - *rows_selected = (gint *) g_malloc (n_rows * sizeof (gint)); - for (index = 0; index < n_rows; ++index) - (*rows_selected)[index] = start_row + index; - } - return n_rows; -} - -static gint -table_interface_get_selected_columns (AtkTable *table, - gint **columns_selected) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewMainItem *main_item; - EWeekView *week_view; - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); - gint start_column = -1, n_columns = 0; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); - week_view = main_item->week_view; - - if (week_view->selection_start_day == -1) - return 0; - if (week_view->selection_end_day - week_view->selection_start_day >= 6 ) { - start_column = 0; - n_columns =7; - } else { - start_column = week_view->selection_start_day % 7; - n_columns = (week_view->selection_end_day % 7) - start_column + 1; - } - if (n_columns > 0 && start_column != -1 && columns_selected) { - gint index; - - *columns_selected = (gint *) g_malloc (n_columns * sizeof (gint)); - for (index = 0; index < n_columns; ++index) - (*columns_selected)[index] = start_column + index; - } - return n_columns; -} - -static gboolean -table_interface_add_row_selection (AtkTable *table, - gint row) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewMainItem *main_item; - EWeekView *week_view; - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); - week_view = main_item->week_view; - - /* FIXME: we need multi-selection */ - - week_view->selection_start_day = row * 7; - week_view->selection_end_day = row *7 + 6; - - gtk_widget_queue_draw (week_view->main_canvas); - return TRUE; -} - -static gboolean -table_interface_remove_row_selection (AtkTable *table, - gint row) -{ - return FALSE; -} - -static gboolean -table_interface_add_column_selection (AtkTable *table, - gint column) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewMainItem *main_item; - EWeekView *week_view; - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); - week_view = main_item->week_view; - - /* FIXME: we need multi-selection */ - - week_view->selection_start_day = column; - week_view->selection_end_day = (week_view->weeks_shown - 1)*7+column; - - gtk_widget_queue_draw (week_view->main_canvas); - return TRUE; -} - -static gboolean -table_interface_remove_column_selection (AtkTable *table, - gint column) -{ - /* FIXME: NOT IMPLEMENTED */ - return FALSE; -} - -static AtkObject* -table_interface_get_row_header (AtkTable *table, - gint row) -{ - /* FIXME: NOT IMPLEMENTED */ - return NULL; -} - -static AtkObject* -table_interface_get_column_header (AtkTable *table, - gint in_col) -{ - /* FIXME: NOT IMPLEMENTED */ - return NULL; -} - -static AtkObject* -table_interface_get_caption (AtkTable *table) -{ - /* FIXME: NOT IMPLEMENTED */ - return NULL; -} - -static G_CONST_RETURN gchar * -table_interface_get_column_description (AtkTable *table, - gint in_col) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); - const gchar *description; - EaCellTable *cell_data; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return NULL; - - if (in_col < 0 || in_col > 6) - return NULL; - cell_data = ea_week_view_main_item_get_cell_data (ea_main_item); - if (!cell_data) - return NULL; - - description = ea_cell_table_get_column_label (cell_data, in_col); - if (!description) { - gchar buffer[128]; - - switch (in_col) { - case 0: - g_snprintf(buffer,128,"Monday"); - break; - case 1: - g_snprintf(buffer,128,"Tuesday"); - break; - case 2: - g_snprintf(buffer,128,"Wednesday"); - break; - case 3: - g_snprintf(buffer,128,"Thursday"); - break; - case 4: - g_snprintf(buffer,128,"Friday"); - break; - case 5: - g_snprintf(buffer,128,"Saturday"); - break; - case 6: - g_snprintf(buffer,128,"Sunday"); - break; - default: - break; - } - - ea_cell_table_set_column_label (cell_data, in_col, buffer); - description = ea_cell_table_get_column_label (cell_data, in_col); - } - return description; -} - -static G_CONST_RETURN gchar * -table_interface_get_row_description (AtkTable *table, - gint row) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewMainItem *main_item; - EWeekView *week_view; - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); - const gchar *description; - EaCellTable *cell_data; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return NULL; - - main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); - week_view = main_item->week_view; - - if (row < 0 || row >= week_view->weeks_shown) - return NULL; - cell_data = ea_week_view_main_item_get_cell_data (ea_main_item); - if (!cell_data) - return NULL; - - description = ea_cell_table_get_row_label (cell_data, row); - if (!description) { - gchar buffer[128]; - ea_week_view_main_item_get_row_label (ea_main_item, row, buffer, sizeof (buffer)); - ea_cell_table_set_row_label (cell_data, row, buffer); - description = ea_cell_table_get_row_label (cell_data, - row); - } - return description; -} - -static AtkObject* -table_interface_get_summary (AtkTable *table) -{ - /* FIXME: NOT IMPLEMENTED */ - return NULL; -} - -/* atkselection interface */ - -static void -atk_selection_interface_init (AtkSelectionIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->add_selection = selection_interface_add_selection; - iface->clear_selection = selection_interface_clear_selection; - iface->ref_selection = selection_interface_ref_selection; - iface->get_selection_count = selection_interface_get_selection_count; - iface->is_child_selected = selection_interface_is_child_selected; -} - -static gboolean -selection_interface_add_selection (AtkSelection *selection, gint i) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewMainItem *main_item; - EWeekView *week_view; - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (selection); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); - week_view = main_item->week_view; - - if (i < 0 || i > week_view->weeks_shown * 7 -1) - return FALSE; - - /*FIXME: multi-selection is needed */ - week_view->selection_start_day = i; - week_view->selection_end_day = i; - - gtk_widget_queue_draw (week_view->main_canvas); - return TRUE; -} - -static gboolean -selection_interface_clear_selection (AtkSelection *selection) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewMainItem *main_item; - EWeekView *week_view; - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (selection); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); - week_view = main_item->week_view; - - week_view->selection_start_day = -1; - week_view->selection_end_day = -1; - - gtk_widget_queue_draw (week_view->main_canvas); - - return TRUE; -} - -static AtkObject* -selection_interface_ref_selection (AtkSelection *selection, gint i) -{ - gint count; - GObject *g_obj; - EWeekView *week_view; - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (selection); - gint start_index; - - count = selection_interface_get_selection_count (selection); - if (i < 0 || i >=count) - return NULL; - - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (ea_main_item)); - week_view = E_WEEK_VIEW_MAIN_ITEM (g_obj)->week_view; - start_index = ea_week_view_main_item_get_child_index_at (ea_main_item, - week_view->selection_start_day / 7, - week_view->selection_start_day % 7); - - return ea_week_view_main_item_ref_child (ATK_OBJECT (selection), start_index + i); -} - -static gint -selection_interface_get_selection_count (AtkSelection *selection) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewMainItem *main_item; - EWeekView *week_view; - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (selection); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return 0; - - main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); - week_view = main_item->week_view; - - if (week_view->selection_start_day == -1 || - week_view->selection_end_day == -1) - return 0; - - return week_view->selection_end_day - week_view->selection_start_day + 1; -} - -static gboolean -selection_interface_is_child_selected (AtkSelection *selection, gint i) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EWeekViewMainItem *main_item; - EWeekView *week_view; - EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (selection); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); - week_view = main_item->week_view; - - if ((week_view->selection_start_day <= i)&&(week_view->selection_end_day >= i)) - return TRUE; - else - return FALSE; -} - diff --git a/calendar/gui/a11y/ea-week-view-main-item.h b/calendar/gui/a11y/ea-week-view-main-item.h deleted file mode 100644 index d9110160c4..0000000000 --- a/calendar/gui/a11y/ea-week-view-main-item.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * Yang Wu - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EA_WEEK_VIEW_MAIN_ITEM_H__ -#define __EA_WEEK_VIEW_MAIN_ITEM_H__ - -#include -#include "e-week-view-main-item.h" - -G_BEGIN_DECLS - -#define EA_TYPE_WEEK_VIEW_MAIN_ITEM (ea_week_view_main_item_get_type ()) -#define EA_WEEK_VIEW_MAIN_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_WEEK_VIEW_MAIN_ITEM, EaWeekViewMainItem)) -#define EA_WEEK_VIEW_MAIN_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_WEEK_VIEW_MAIN_ITEM, EaWeekViewMainItemClass)) -#define EA_IS_WEEK_VIEW_MAIN_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_WEEK_VIEW_MAIN_ITEM)) -#define EA_IS_WEEK_VIEW_MAIN_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_WEEK_VIEW_MAIN_ITEM)) -#define EA_WEEK_VIEW_MAIN_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_WEEK_VIEW_MAIN_ITEM, EaWeekViewMainItemClass)) - -typedef struct _EaWeekViewMainItem EaWeekViewMainItem; -typedef struct _EaWeekViewMainItemClass EaWeekViewMainItemClass; - -struct _EaWeekViewMainItem -{ - AtkGObjectAccessible parent; -}; - -GType ea_week_view_main_item_get_type (void); - -struct _EaWeekViewMainItemClass -{ - AtkGObjectAccessibleClass parent_class; -}; - -AtkObject* ea_week_view_main_item_new (GObject *obj); - -G_END_DECLS - -#endif /* __EA_WEEK_VIEW_MAIN_ITEM_H__ */ diff --git a/calendar/gui/a11y/ea-week-view.c b/calendar/gui/a11y/ea-week-view.c deleted file mode 100644 index 97a8dae25d..0000000000 --- a/calendar/gui/a11y/ea-week-view.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "ea-week-view.h" -#include "ea-cal-view-event.h" -#include "ea-calendar-helpers.h" -#include "ea-gnome-calendar.h" -#include "calendar-commands.h" -#include -#include - -static void ea_week_view_class_init (EaWeekViewClass *klass); - -static G_CONST_RETURN gchar * ea_week_view_get_name (AtkObject *accessible); -static G_CONST_RETURN gchar * ea_week_view_get_description (AtkObject *accessible); -static gint ea_week_view_get_n_children (AtkObject *obj); -static AtkObject* ea_week_view_ref_child (AtkObject *obj, - gint i); - -static gpointer parent_class = NULL; - -GType -ea_week_view_get_type (void) -{ - static GType type = 0; - AtkObjectFactory *factory; - GTypeQuery query; - GType derived_atk_type; - - if (!type) { - static GTypeInfo tinfo = { - sizeof (EaWeekViewClass), - (GBaseInitFunc) NULL, /* base init */ - (GBaseFinalizeFunc) NULL, /* base finalize */ - (GClassInitFunc) ea_week_view_class_init, /* class init */ - (GClassFinalizeFunc) NULL, /* class finalize */ - NULL, /* class data */ - sizeof (EaWeekView), /* instance size */ - 0, /* nb preallocs */ - (GInstanceInitFunc) NULL, /* instance init */ - NULL /* value table */ - }; - - /* - * Figure out the size of the class and instance - * we are run-time deriving from (EaCalView, in this case) - * - * Note: we must still use run-time deriving here, because - * our parent class EaCalView is run-time deriving. - */ - - factory = atk_registry_get_factory (atk_get_default_registry (), - e_calendar_view_get_type()); - derived_atk_type = atk_object_factory_get_accessible_type (factory); - g_type_query (derived_atk_type, &query); - - tinfo.class_size = query.class_size; - tinfo.instance_size = query.instance_size; - - type = g_type_register_static (derived_atk_type, - "EaWeekView", &tinfo, 0); - - } - - return type; -} - -static void -ea_week_view_class_init (EaWeekViewClass *klass) -{ - AtkObjectClass *class = ATK_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - class->get_name = ea_week_view_get_name; - class->get_description = ea_week_view_get_description; - - class->get_n_children = ea_week_view_get_n_children; - class->ref_child = ea_week_view_ref_child; -} - -AtkObject* -ea_week_view_new (GtkWidget *widget) -{ - GObject *object; - AtkObject *accessible; - - g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); - - object = g_object_new (EA_TYPE_WEEK_VIEW, NULL); - - accessible = ATK_OBJECT (object); - atk_object_initialize (accessible, widget); - -#ifdef ACC_DEBUG - printf ("EvoAcc: ea_week_view created %p\n", (gpointer)accessible); -#endif - - return accessible; -} - -static G_CONST_RETURN gchar * -ea_week_view_get_name (AtkObject *accessible) -{ - EWeekView *week_view; - GnomeCalendar *gcal; - const gchar *label_text; - GnomeCalendarViewType view_type; - gint n_events; - gchar *event_str, *name_str; - - g_return_val_if_fail (EA_IS_WEEK_VIEW (accessible), NULL); - - if (!GTK_ACCESSIBLE (accessible)->widget) - return NULL; - - week_view = E_WEEK_VIEW (GTK_ACCESSIBLE (accessible)->widget); - gcal = e_calendar_view_get_calendar (E_CALENDAR_VIEW (week_view)); - if (!GTK_WIDGET_VISIBLE (GTK_WIDGET (gcal))) - return NULL; - - label_text = ea_gnome_calendar_get_label_description (gcal); - - n_events = atk_object_get_n_accessible_children (accessible); - /* the child main item is always there */ - --n_events; - if (n_events >= 1) - event_str = g_strdup_printf (ngettext ("It has %d event.", "It has %d events.", n_events), n_events); - else - event_str = g_strdup (_("It has no events.")); - - view_type = gnome_calendar_get_view (gcal); - - if (view_type == GNOME_CAL_MONTH_VIEW) - name_str = g_strdup_printf (_("Month View: %s. %s"), - label_text, event_str); - - else - name_str = g_strdup_printf (_("Week View: %s. %s"), - label_text, event_str); - - ATK_OBJECT_CLASS (parent_class)->set_name (accessible, name_str); - g_free (name_str); - g_free (event_str); - - return accessible->name; -} - -static G_CONST_RETURN gchar * -ea_week_view_get_description (AtkObject *accessible) -{ - EWeekView *week_view; - - g_return_val_if_fail (EA_IS_WEEK_VIEW (accessible), NULL); - - if (!GTK_ACCESSIBLE (accessible)->widget) - return NULL; - week_view = E_WEEK_VIEW (GTK_ACCESSIBLE (accessible)->widget); - - if (accessible->description) - return accessible->description; - else { - GnomeCalendar *gcal; - GnomeCalendarViewType view_type; - - gcal = e_calendar_view_get_calendar (E_CALENDAR_VIEW (week_view)); - view_type = gnome_calendar_get_view (gcal); - - if (view_type == GNOME_CAL_MONTH_VIEW) - return _("calendar view for a month"); - else - return _("calendar view for one or more weeks"); - } -} - -static gint -ea_week_view_get_n_children (AtkObject *accessible) -{ - EWeekView *week_view; - gint i, count = 0; - gint event_index; - - g_return_val_if_fail (EA_IS_WEEK_VIEW (accessible), -1); - - if (!GTK_ACCESSIBLE (accessible)->widget) - return -1; - week_view = E_WEEK_VIEW (GTK_ACCESSIBLE (accessible)->widget); - - for (event_index = 0; event_index < week_view->events->len; - ++event_index) { - EWeekViewEvent *event; - EWeekViewEventSpan *span; - - /* If week_view->spans == NULL, there is no visible events. */ - if (!week_view->spans) - break; - - event = &g_array_index (week_view->events, - EWeekViewEvent, event_index); - if (!event) - continue; - span = &g_array_index (week_view->spans, EWeekViewEventSpan, - event->spans_index + 0); - - if (!span) - continue; - - /* at least one of the event spans is visible, count it */ - if (span->text_item) - ++count; - } - - /* add the number of visible jump buttons */ - for (i = 0; i < E_WEEK_VIEW_MAX_WEEKS * 7; i++) { - if (week_view->jump_buttons[i]->object.flags & GNOME_CANVAS_ITEM_VISIBLE) - ++count; - } - - /* "+1" for the main item */ - count++; - -#ifdef ACC_DEBUG - printf("AccDebug: week view %p has %d children\n", (gpointer)week_view, count); -#endif - return count; -} - -static AtkObject * -ea_week_view_ref_child (AtkObject *accessible, gint index) -{ - EWeekView *week_view; - gint child_num, max_count; - AtkObject *atk_object = NULL; - gint event_index; - gint jump_button = -1; - gint span_num = 0; - gint count = 0; - - g_return_val_if_fail (EA_IS_WEEK_VIEW (accessible), NULL); - - child_num = atk_object_get_n_accessible_children (accessible); - if (child_num <= 0 || index < 0 || index >= child_num) - return NULL; - - if (!GTK_ACCESSIBLE (accessible)->widget) - return NULL; - week_view = E_WEEK_VIEW (GTK_ACCESSIBLE (accessible)->widget); - max_count = week_view->events->len; - - if (index == 0) { - /* index == 0 is the main item */ - atk_object = atk_gobject_accessible_for_object (G_OBJECT (week_view->main_canvas_item)); - g_object_ref (atk_object); - } else - for (event_index = 0; event_index < max_count; ++event_index) { - EWeekViewEvent *event; - EWeekViewEventSpan *span; - gint current_day; - - event = &g_array_index (week_view->events, - EWeekViewEvent, event_index); - if (!event) - continue; - - span = &g_array_index (week_view->spans, EWeekViewEventSpan, - event->spans_index + span_num); - - if (!span) - continue; - - current_day = span->start_day; - if (span->text_item) - ++count; - else if (current_day != jump_button) { - /* we should go to the jump button */ - jump_button = current_day; - ++count; - } - else - continue; - - if (count == index) { - if (span->text_item) { - /* Not use atk_gobject_accessible_for_object for event - * text_item we need to do special thing here - */ - atk_object = ea_calendar_helpers_get_accessible_for (span->text_item); - } - else { - atk_object = ea_calendar_helpers_get_accessible_for (week_view->jump_buttons[current_day == -1 ? 0 : current_day]); - } - g_object_ref (atk_object); - break; - } - } - -#ifdef ACC_DEBUG - printf ("EvoAcc: ea_week_view_ref_child [%d]=%p\n", - index, (gpointer)atk_object); -#endif - return atk_object; -} diff --git a/calendar/gui/a11y/ea-week-view.h b/calendar/gui/a11y/ea-week-view.h deleted file mode 100644 index bb71c17e74..0000000000 --- a/calendar/gui/a11y/ea-week-view.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EA_WEEK_VIEW_H__ -#define __EA_WEEK_VIEW_H__ - -#include "ea-cal-view.h" -#include "e-week-view.h" - -G_BEGIN_DECLS - -#define EA_TYPE_WEEK_VIEW (ea_week_view_get_type ()) -#define EA_WEEK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_WEEK_VIEW, EaWeekView)) -#define EA_WEEK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_WEEK_VIEW, EaWeekViewClass)) -#define EA_IS_WEEK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_WEEK_VIEW)) -#define EA_IS_WEEK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_WEEK_VIEW)) -#define EA_WEEK_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_WEEK_VIEW, EaWeekViewClass)) - -typedef struct _EaWeekView EaWeekView; -typedef struct _EaWeekViewClass EaWeekViewClass; - -struct _EaWeekView -{ - EaCalView parent; -}; - -GType ea_week_view_get_type (void); - -struct _EaWeekViewClass -{ - EaCalViewClass parent_class; -}; - -AtkObject* ea_week_view_new (GtkWidget *widget); - -G_END_DECLS - - -#endif /* __EA_WEEK_VIEW_H__ */ diff --git a/calendar/gui/ea-cal-view-event.c b/calendar/gui/ea-cal-view-event.c new file mode 100644 index 0000000000..5da164323f --- /dev/null +++ b/calendar/gui/ea-cal-view-event.c @@ -0,0 +1,573 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "ea-cal-view-event.h" +#include "ea-calendar-helpers.h" +#include "ea-day-view.h" +#include "ea-week-view.h" +#include +#include + +static void ea_cal_view_event_class_init (EaCalViewEventClass *klass); +static void ea_cal_view_event_init (EaCalViewEvent *a11y); + +static void ea_cal_view_event_dispose (GObject *object); +static G_CONST_RETURN gchar * ea_cal_view_event_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar * ea_cal_view_event_get_description (AtkObject *accessible); +static AtkObject* ea_cal_view_event_get_parent (AtkObject *accessible); +static gint ea_cal_view_event_get_index_in_parent (AtkObject *accessible); +static AtkStateSet *ea_cal_view_event_ref_state_set (AtkObject *accessible); + +/* component interface */ +static void atk_component_interface_init (AtkComponentIface *iface); +static void ea_cal_view_get_extents (AtkComponent *component, + gint *x, gint *y, gint *width, gint *height, + AtkCoordType coord_type); +/* action interface */ +static void atk_action_interface_init (AtkActionIface *iface); +static gboolean ea_cal_view_event_do_action (AtkAction *action, gint i); +static gint ea_cal_view_event_get_n_actions (AtkAction *action); +static G_CONST_RETURN gchar * ea_cal_view_event_action_get_name (AtkAction *action, gint i); + + +#ifdef ACC_DEBUG +static gint n_ea_cal_view_event_created = 0, n_ea_cal_view_event_destroyed = 0; +static void ea_cal_view_finalize (GObject *object); +#endif + +static gpointer parent_class = NULL; + +GType +ea_cal_view_event_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaCalViewEventClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) ea_cal_view_event_class_init, /* class init */ + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (EaCalViewEvent), /* instance size */ + 0, /* nb preallocs */ + (GInstanceInitFunc) ea_cal_view_event_init, /* instance init */ + NULL /* value table */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) atk_component_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + static const GInterfaceInfo atk_action_info = { + (GInterfaceInitFunc) atk_action_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (atk object for E_TEXT, in this case) + */ + + factory = atk_registry_get_factory (atk_get_default_registry (), + E_TYPE_TEXT); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + /* we inherit the component, text and other interfaces from E_TEXT */ + type = g_type_register_static (derived_atk_type, + "EaCalViewEvent", &tinfo, 0); + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, + &atk_component_info); + g_type_add_interface_static (type, ATK_TYPE_ACTION, + &atk_action_info); + + + } + + return type; +} + +static void +ea_cal_view_event_class_init (EaCalViewEventClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); +#ifdef ACC_DEBUG + gobject_class->finalize = ea_cal_view_finalize; +#endif + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->dispose = ea_cal_view_event_dispose; + + class->get_name = ea_cal_view_event_get_name; + class->get_description = ea_cal_view_event_get_description; + class->get_parent = ea_cal_view_event_get_parent; + class->get_index_in_parent = ea_cal_view_event_get_index_in_parent; + class->ref_state_set = ea_cal_view_event_ref_state_set; + +} + +static void +ea_cal_view_event_init (EaCalViewEvent *a11y) +{ + a11y->state_set = atk_state_set_new (); + atk_state_set_add_state (a11y->state_set, ATK_STATE_TRANSIENT); + atk_state_set_add_state (a11y->state_set, ATK_STATE_ENABLED); + atk_state_set_add_state (a11y->state_set, ATK_STATE_SENSITIVE); + atk_state_set_add_state (a11y->state_set, ATK_STATE_SELECTABLE); + atk_state_set_add_state (a11y->state_set, ATK_STATE_SHOWING); + atk_state_set_add_state (a11y->state_set, ATK_STATE_FOCUSABLE); +} + +#ifdef ACC_DEBUG +static void ea_cal_view_finalize (GObject *object) +{ + G_OBJECT_CLASS (parent_class)->finalize (object); + + ++n_ea_cal_view_event_destroyed; + printf ("ACC_DEBUG: n_ea_cal_view_event_destroyed = %d\n", + n_ea_cal_view_event_destroyed); +} +#endif + +AtkObject* +ea_cal_view_event_new (GObject *obj) +{ + AtkObject *atk_obj = NULL; + GObject *target_obj; + ECalendarView *cal_view; + + g_return_val_if_fail (E_IS_TEXT (obj), NULL); + cal_view = ea_calendar_helpers_get_cal_view_from (GNOME_CANVAS_ITEM (obj)); + if (!cal_view) + return NULL; + + if (E_IS_WEEK_VIEW (cal_view)) { + gint event_num, span_num; + EWeekViewEvent *week_view_event; + EWeekViewEventSpan *event_span; + EWeekView *week_view = E_WEEK_VIEW (cal_view); + + /* for week view, we need to check if a atkobject exists for + * the first span of the same event + */ + if (!e_week_view_find_event_from_item (week_view, + GNOME_CANVAS_ITEM (obj), + &event_num, + &span_num)) + return NULL; + week_view_event = &g_array_index (week_view->events, + EWeekViewEvent, + event_num); + /* get the first span */ + event_span = &g_array_index (week_view->spans, + EWeekViewEventSpan, + week_view_event->spans_index); + target_obj = G_OBJECT (event_span->text_item); + atk_obj = g_object_get_data (target_obj, "accessible-object"); + + } + else + target_obj = obj; + + if (!atk_obj) { + static AtkRole event_role = ATK_ROLE_INVALID; + atk_obj = ATK_OBJECT (g_object_new (EA_TYPE_CAL_VIEW_EVENT, + NULL)); + atk_object_initialize (atk_obj, target_obj); + if (event_role == ATK_ROLE_INVALID) + event_role = atk_role_register ("Calendar Event"); + atk_obj->role = event_role; +#ifdef ACC_DEBUG + ++n_ea_cal_view_event_created; + printf ("ACC_DEBUG: n_ea_cal_view_event_created = %d\n", + n_ea_cal_view_event_created); +#endif + } + + /* the registered factory for E_TEXT is cannot create a EaCalViewEvent, + * we should save the EaCalViewEvent object in it. + */ + g_object_set_data (obj, "accessible-object", atk_obj); + + return atk_obj; +} + +static void +ea_cal_view_event_dispose (GObject *object) +{ + EaCalViewEvent *a11y = EA_CAL_VIEW_EVENT (object); + + if (a11y->state_set) { + g_object_unref (a11y->state_set); + a11y->state_set = NULL; + } + + if (G_OBJECT_CLASS(parent_class)->dispose) + G_OBJECT_CLASS(parent_class)->dispose (object); +} + +static G_CONST_RETURN gchar * +ea_cal_view_event_get_name (AtkObject *accessible) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarViewEvent *event; + gchar *name_string; + const gchar *alarm_string; + const gchar *recur_string; + const gchar *meeting_string; + gchar *summary_string; + const gchar *summary; + + + g_return_val_if_fail (EA_IS_CAL_VIEW_EVENT (accessible), NULL); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj || !E_IS_TEXT (g_obj)) + return NULL; + event = ea_calendar_helpers_get_cal_view_event_from (GNOME_CANVAS_ITEM(g_obj)); + + alarm_string = recur_string = meeting_string = ""; + if (event && event->comp_data) { + if (e_cal_util_component_has_alarms (event->comp_data->icalcomp)) + alarm_string = _("It has alarms."); + + if (e_cal_util_component_has_recurrences (event->comp_data->icalcomp)) + recur_string = _("It has recurrences."); + + if (e_cal_util_component_has_organizer (event->comp_data->icalcomp)) + meeting_string = _("It is a meeting."); + + } + + summary = icalcomponent_get_summary (event->comp_data->icalcomp); + if (summary) + summary_string = g_strdup_printf (_("Calendar Event: Summary is %s."), summary); + else + summary_string = g_strdup (_("Calendar Event: It has no summary.")); + + name_string = g_strdup_printf ("%s %s %s %s", summary_string, alarm_string, recur_string, meeting_string); + g_free (summary_string); + + ATK_OBJECT_CLASS (parent_class)->set_name (accessible, name_string); +#ifdef ACC_DEBUG + printf("EvoAcc: name for event accobj=%p, is %s\n", + (gpointer)accessible, new_name); +#endif + g_free (name_string); + return accessible->name; +} + +static G_CONST_RETURN gchar * +ea_cal_view_event_get_description (AtkObject *accessible) +{ + if (accessible->description) + return accessible->description; + + return _("calendar view event"); +} + +static AtkObject * +ea_cal_view_event_get_parent (AtkObject *accessible) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + GnomeCanvasItem *canvas_item; + ECalendarView *cal_view; + + g_return_val_if_fail (EA_IS_CAL_VIEW_EVENT (accessible), NULL); + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (g_obj == NULL) + /* Object is defunct */ + return NULL; + canvas_item = GNOME_CANVAS_ITEM (g_obj); + + cal_view = ea_calendar_helpers_get_cal_view_from (canvas_item); + + if (!cal_view) + return NULL; + + return gtk_widget_get_accessible (GTK_WIDGET (cal_view)); +} + +static gint +ea_cal_view_event_get_index_in_parent (AtkObject *accessible) +{ + GObject *g_obj; + GnomeCanvasItem *canvas_item; + ECalendarView *cal_view; + ECalendarViewEvent *cal_view_event; + + g_return_val_if_fail (EA_IS_CAL_VIEW_EVENT (accessible), -1); + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible)); + if (!g_obj) + /* defunct object*/ + return -1; + + canvas_item = GNOME_CANVAS_ITEM (g_obj); + cal_view = ea_calendar_helpers_get_cal_view_from (canvas_item); + if (!cal_view) + return -1; + + cal_view_event = ea_calendar_helpers_get_cal_view_event_from (canvas_item); + if (!cal_view_event) + return -1; + + if (E_IS_DAY_VIEW (cal_view)) { + gint day, event_num, num_before; + EDayViewEvent *day_view_event; + EDayView *day_view = E_DAY_VIEW (cal_view); + + /* the long event comes first in the order */ + for (event_num = day_view->long_events->len - 1; event_num >= 0; + --event_num) { + day_view_event = &g_array_index (day_view->long_events, + EDayViewEvent, event_num); + if (cal_view_event == (ECalendarViewEvent*)day_view_event) + return event_num; + + } + num_before = day_view->long_events->len; + + for (day = 0; day < day_view->days_shown; ++day) { + for (event_num = day_view->events[day]->len - 1; event_num >= 0; + --event_num) { + day_view_event = &g_array_index (day_view->events[day], + EDayViewEvent, event_num); + if (cal_view_event == (ECalendarViewEvent*)day_view_event) + return num_before + event_num; + } + num_before += day_view->events[day]->len; + } + } + else if (E_IS_WEEK_VIEW (cal_view)) { + AtkObject *atk_parent, *atk_child; + gint index = 0; + + atk_parent = atk_object_get_parent (accessible); + while ((atk_child = atk_object_ref_accessible_child (atk_parent, + index)) != NULL) { + if (atk_child == accessible) { + g_object_unref (atk_child); + return index; + } + g_object_unref (atk_child); + ++index; + } + } + else { + g_return_val_if_reached (-1); + } + return -1; +} + +static AtkStateSet * +ea_cal_view_event_ref_state_set (AtkObject *accessible) +{ + EaCalViewEvent *atk_event = EA_CAL_VIEW_EVENT (accessible); + + g_return_val_if_fail (atk_event->state_set, NULL); + + g_object_ref (atk_event->state_set); + + return atk_event->state_set; +} + +/* Atk Component Interface */ + +static void +atk_component_interface_init (AtkComponentIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->get_extents = ea_cal_view_get_extents; +} + +static void +ea_cal_view_get_extents (AtkComponent *component, + gint *x, + gint *y, + gint *width, + gint *height, + AtkCoordType coord_type) +{ + GObject *g_obj; + GnomeCanvasItem *canvas_item; + gint x_window, y_window; + gint scroll_x, scroll_y; + ECalendarView *cal_view; + gint item_x, item_y, item_w, item_h; + GtkWidget *canvas = NULL; + + g_return_if_fail (EA_IS_CAL_VIEW_EVENT (component)); + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(component)); + if (!g_obj) + /* defunct object*/ + return; + g_return_if_fail (E_IS_TEXT (g_obj)); + + canvas_item = GNOME_CANVAS_ITEM (g_obj); + cal_view = ea_calendar_helpers_get_cal_view_from (canvas_item); + if (!cal_view) + return; + + if (E_IS_DAY_VIEW (cal_view)) { + gint day, event_num; + + if (!e_day_view_find_event_from_item (E_DAY_VIEW (cal_view), + canvas_item, + &day, &event_num)) + return; + if (day == E_DAY_VIEW_LONG_EVENT) { + gint start_day, end_day; + if (!e_day_view_get_long_event_position (E_DAY_VIEW (cal_view), + event_num, + &start_day, + &end_day, + &item_x, + &item_y, + &item_w, + &item_h)) + return; + canvas = E_DAY_VIEW (cal_view)->top_canvas; + } + else { + if (!e_day_view_get_event_position (E_DAY_VIEW (cal_view), day, + event_num, + &item_x, &item_y, + &item_w, &item_h)) + + return; + canvas = E_DAY_VIEW (cal_view)->main_canvas; + } + } + else if (E_IS_WEEK_VIEW (cal_view)) { + gint event_num, span_num; + if (!e_week_view_find_event_from_item (E_WEEK_VIEW (cal_view), + canvas_item, &event_num, + &span_num)) + return; + + if (!e_week_view_get_span_position (E_WEEK_VIEW (cal_view), + event_num, span_num, + &item_x, &item_y, &item_w)) + return; + item_h = E_WEEK_VIEW_ICON_HEIGHT; + canvas = E_WEEK_VIEW (cal_view)->main_canvas; + } + else + return; + + if (!canvas) + return; + + gdk_window_get_origin (canvas->window, + &x_window, &y_window); + gnome_canvas_get_scroll_offsets (GNOME_CANVAS (canvas), &scroll_x, &scroll_y); + + *x = item_x + x_window - scroll_x; + *y = item_y + y_window - scroll_y; + *width = item_w; + *height = item_h; + + if (coord_type == ATK_XY_WINDOW) { + GdkWindow *window; + gint x_toplevel, y_toplevel; + + window = gdk_window_get_toplevel (GTK_WIDGET (cal_view)->window); + gdk_window_get_origin (window, &x_toplevel, &y_toplevel); + + *x -= x_toplevel; + *y -= y_toplevel; + } + +#ifdef ACC_DEBUG + printf ("Event Bounds (%d, %d, %d, %d)\n", *x, *y, *width, *height); +#endif +} + +#define CAL_VIEW_EVENT_ACTION_NUM 1 + +static const gchar * action_name [CAL_VIEW_EVENT_ACTION_NUM] = { + N_("Grab Focus") +}; + +static void +atk_action_interface_init (AtkActionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->do_action = ea_cal_view_event_do_action; + iface->get_n_actions = ea_cal_view_event_get_n_actions; + iface->get_name = ea_cal_view_event_action_get_name; +} + +static gboolean +ea_cal_view_event_do_action (AtkAction *action, gint i) +{ + AtkGObjectAccessible *atk_gobj; + AtkComponent *atk_comp; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (action); + + if (i == 0) { + atk_comp = (AtkComponent *)atk_gobj; + return atk_component_grab_focus (atk_comp); + } + + return FALSE; + +} + +static gint +ea_cal_view_event_get_n_actions (AtkAction *action) +{ + return CAL_VIEW_EVENT_ACTION_NUM; +} + +static G_CONST_RETURN gchar * +ea_cal_view_event_action_get_name (AtkAction *action, gint i) +{ + if (i >= 0 && i < CAL_VIEW_EVENT_ACTION_NUM) + return action_name [i]; + return NULL; +} + diff --git a/calendar/gui/ea-cal-view-event.h b/calendar/gui/ea-cal-view-event.h new file mode 100644 index 0000000000..548e42b4a7 --- /dev/null +++ b/calendar/gui/ea-cal-view-event.h @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_CAL_VIEW_EVENT_H__ +#define __EA_CAL_VIEW_EVENT_H__ + +#include + +G_BEGIN_DECLS + +#define EA_TYPE_CAL_VIEW_EVENT (ea_cal_view_event_get_type ()) +#define EA_CAL_VIEW_EVENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_CAL_VIEW_EVENT, EaCalViewEvent)) +#define EA_CAL_VIEW_EVENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_CAL_VIEW_EVENT, EaCalViewEventClass)) +#define EA_IS_CAL_VIEW_EVENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_CAL_VIEW_EVENT)) +#define EA_IS_CAL_VIEW_EVENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_CAL_VIEW_EVENT)) +#define EA_CAL_VIEW_EVENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_CAL_VIEW_EVENT, EaCalViewEventClass)) + +typedef struct _EaCalViewEvent EaCalViewEvent; +typedef struct _EaCalViewEventClass EaCalViewEventClass; + +struct _EaCalViewEvent +{ + AtkGObjectAccessible parent; + AtkStateSet *state_set; +}; + +GType ea_cal_view_event_get_type (void); + +struct _EaCalViewEventClass +{ + AtkGObjectAccessibleClass parent_class; +}; + +AtkObject *ea_cal_view_event_new (GObject *obj); + +G_END_DECLS + + +#endif /* __EA_CAL_VIEW_EVENT_H__ */ diff --git a/calendar/gui/ea-cal-view.c b/calendar/gui/ea-cal-view.c new file mode 100644 index 0000000000..952afcc791 --- /dev/null +++ b/calendar/gui/ea-cal-view.c @@ -0,0 +1,426 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "ea-cal-view.h" +#include "ea-calendar-helpers.h" +#include "e-day-view.h" +#include "e-week-view.h" +#include "calendar-commands.h" +#include "goto.h" +#include +#include + +static void ea_cal_view_class_init (EaCalViewClass *klass); + +static AtkObject* ea_cal_view_get_parent (AtkObject *accessible); +static void ea_cal_view_real_initialize (AtkObject *accessible, gpointer data); + +static void ea_cal_view_event_changed_cb (ECalendarView *cal_view, + ECalendarViewEvent *event, gpointer data); +static void ea_cal_view_event_added_cb (ECalendarView *cal_view, + ECalendarViewEvent *event, gpointer data); + +static gboolean idle_dates_changed (gpointer data); +static void ea_cal_view_dates_change_cb (GnomeCalendar *gcal, gpointer data); + +static void atk_action_interface_init (AtkActionIface *iface); +static gboolean action_interface_do_action (AtkAction *action, gint i); +static gint action_interface_get_n_actions (AtkAction *action); +static G_CONST_RETURN gchar * +action_interface_get_description(AtkAction *action, gint i); +static G_CONST_RETURN gchar * +action_interface_get_keybinding (AtkAction *action, gint i); +static G_CONST_RETURN gchar * +action_interface_action_get_name(AtkAction *action, gint i); + +static gpointer parent_class = NULL; + +GType +ea_cal_view_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaCalViewClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) ea_cal_view_class_init, /* class init */ + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (EaCalView), /* instance size */ + 0, /* nb preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + static const GInterfaceInfo atk_action_info = { + (GInterfaceInitFunc) atk_action_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (GailWidget, in this case) + */ + + factory = atk_registry_get_factory (atk_get_default_registry (), + GTK_TYPE_WIDGET); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + type = g_type_register_static (derived_atk_type, + "EaCalView", &tinfo, 0); + g_type_add_interface_static (type, ATK_TYPE_ACTION, + &atk_action_info); + } + + return type; +} + +static void +ea_cal_view_class_init (EaCalViewClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + class->get_parent = ea_cal_view_get_parent; + class->initialize = ea_cal_view_real_initialize; +} + +AtkObject* +ea_cal_view_new (GtkWidget *widget) +{ + GObject *object; + AtkObject *accessible; + + g_return_val_if_fail (E_IS_CALENDAR_VIEW (widget), NULL); + + object = g_object_new (EA_TYPE_CAL_VIEW, NULL); + + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, widget); + + return accessible; +} + +static void +ea_cal_view_real_initialize (AtkObject *accessible, gpointer data) +{ + ECalendarView *cal_view; + GnomeCalendar *gcal; + static AtkRole role = ATK_ROLE_INVALID; + + g_return_if_fail (EA_IS_CAL_VIEW (accessible)); + g_return_if_fail (E_IS_CALENDAR_VIEW (data)); + + ATK_OBJECT_CLASS (parent_class)->initialize (accessible, data); + if (role == ATK_ROLE_INVALID) + role = atk_role_register ("Calendar View"); + accessible->role = role; + cal_view = E_CALENDAR_VIEW (data); + + /* add listener for event_changed, event_added + * we don't need to listen on event_removed. When the e_text + * of the event is removed, the cal_view_event will go to the state + * of "defunct" (changed by weak ref callback of atkgobjectaccessible + */ + g_signal_connect (G_OBJECT(cal_view), "event_changed", + G_CALLBACK (ea_cal_view_event_changed_cb), NULL); + g_signal_connect (G_OBJECT(cal_view), "event_added", + G_CALLBACK (ea_cal_view_event_added_cb), NULL); + + /* listen for date changes of calendar */ + gcal = e_calendar_view_get_calendar (cal_view); + + if (gcal) + g_signal_connect (gcal, "dates_shown_changed", + G_CALLBACK (ea_cal_view_dates_change_cb), + accessible); +} + +static AtkObject* +ea_cal_view_get_parent (AtkObject *accessible) +{ + ECalendarView *cal_view; + GnomeCalendar *gnomeCalendar; + + g_return_val_if_fail (EA_IS_CAL_VIEW (accessible), NULL); + + if (!GTK_ACCESSIBLE (accessible)->widget) + return NULL; + cal_view = E_CALENDAR_VIEW (GTK_ACCESSIBLE (accessible)->widget); + + gnomeCalendar = e_calendar_view_get_calendar (cal_view); + + return gtk_widget_get_accessible (GTK_WIDGET(gnomeCalendar)); +} + +static void +ea_cal_view_event_changed_cb (ECalendarView *cal_view, ECalendarViewEvent *event, + gpointer data) +{ + AtkObject *atk_obj; + AtkObject *event_atk_obj = NULL; + + g_return_if_fail (E_IS_CALENDAR_VIEW (cal_view)); + + atk_obj = gtk_widget_get_accessible (GTK_WIDGET(cal_view)); + if (!EA_IS_CAL_VIEW (atk_obj)) + return; + + if ((E_IS_DAY_VIEW (cal_view)) && event && event->canvas_item) { + event_atk_obj = + ea_calendar_helpers_get_accessible_for (event->canvas_item); + } + else if ((E_IS_WEEK_VIEW (cal_view)) && event) { + EWeekViewEventSpan *span; + EWeekViewEvent *week_view_event = (EWeekViewEvent *)event; + EWeekView *week_view = E_WEEK_VIEW (cal_view); + /* get the first span of the event */ + span = &g_array_index (week_view->spans, EWeekViewEventSpan, + week_view_event->spans_index); + if (span && span->text_item) + event_atk_obj = ea_calendar_helpers_get_accessible_for (span->text_item); + } + if (event_atk_obj) { +#ifdef ACC_DEBUG + printf ("AccDebug: event=%p changed\n", (gpointer)event); +#endif + g_object_notify (G_OBJECT(event_atk_obj), "accessible-name"); + g_signal_emit_by_name (event_atk_obj, "visible_data_changed"); + } + +} + +static void +ea_cal_view_event_added_cb (ECalendarView *cal_view, ECalendarViewEvent *event, + gpointer data) +{ + AtkObject *atk_obj; + AtkObject *event_atk_obj = NULL; + gint index; + + g_return_if_fail (E_IS_CALENDAR_VIEW (cal_view)); + + atk_obj = gtk_widget_get_accessible (GTK_WIDGET(cal_view)); + if (!EA_IS_CAL_VIEW (atk_obj)) + return; + + if ((E_IS_DAY_VIEW (cal_view)) && event && event->canvas_item) { + event_atk_obj = + ea_calendar_helpers_get_accessible_for (event->canvas_item); + } + else if ((E_IS_WEEK_VIEW (cal_view)) && event) { + EWeekViewEventSpan *span; + EWeekViewEvent *week_view_event = (EWeekViewEvent *)event; + EWeekView *week_view = E_WEEK_VIEW (cal_view); + /* get the first span of the event */ + span = &g_array_index (week_view->spans, EWeekViewEventSpan, + week_view_event->spans_index); + if (span && span->text_item) + event_atk_obj = ea_calendar_helpers_get_accessible_for (span->text_item); + + } + if (event_atk_obj) { + index = atk_object_get_index_in_parent (event_atk_obj); + if (index < 0) + return; +#ifdef ACC_DEBUG + printf ("AccDebug: event=%p added\n", (gpointer)event); +#endif + g_signal_emit_by_name (atk_obj, "children_changed::add", + index, event_atk_obj, NULL); + } +} + +static gboolean +idle_dates_changed (gpointer data) +{ + AtkObject *ea_cal_view; + + g_return_val_if_fail (data, FALSE); + g_return_val_if_fail (EA_IS_CAL_VIEW (data), FALSE); + + ea_cal_view = ATK_OBJECT(data); + + if (ea_cal_view->name) { + g_free (ea_cal_view->name); + ea_cal_view->name = NULL; + } + g_object_notify (G_OBJECT (ea_cal_view), "accessible-name"); + g_signal_emit_by_name (ea_cal_view, "visible_data_changed"); + g_signal_emit_by_name (ea_cal_view, "children_changed", NULL, NULL, NULL); +#ifdef ACC_DEBUG + printf ("AccDebug: cal view date changed\n"); +#endif + + return FALSE; +} + +static void +ea_cal_view_dates_change_cb (GnomeCalendar *gcal, gpointer data) +{ + g_idle_add (idle_dates_changed, data); +} + +/* atk action interface */ + +#define CAL_VIEW_ACTION_NUM 5 + +static const gchar * action_name [CAL_VIEW_ACTION_NUM] = { + N_("New Appointment"), + N_("New All Day Event"), + N_("New Meeting"), + N_("Go to Today"), + N_("Go to Date") +}; + +static void +atk_action_interface_init (AtkActionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->do_action = action_interface_do_action; + iface->get_n_actions = action_interface_get_n_actions; + iface->get_description = action_interface_get_description; + iface->get_keybinding = action_interface_get_keybinding; + iface->get_name = action_interface_action_get_name; +} + +static gboolean +action_interface_do_action (AtkAction *action, gint index) +{ + GtkWidget *widget; + gboolean return_value = TRUE; + time_t dtstart, dtend; + ECalendarView *cal_view; + + widget = GTK_ACCESSIBLE (action)->widget; + if (widget == NULL) + /* + * State is defunct + */ + return FALSE; + + if (!GTK_WIDGET_IS_SENSITIVE (widget) || !GTK_WIDGET_VISIBLE (widget)) + return FALSE; + + cal_view = E_CALENDAR_VIEW (widget); + switch (index) { + case 0: + /* New Appointment */ + e_calendar_view_new_appointment (cal_view); + break; + case 1: + /* New All Day Event */ + e_calendar_view_get_selected_time_range (cal_view, + &dtstart, &dtend); + e_calendar_view_new_appointment_for (cal_view, + dtstart, dtend, TRUE, FALSE); + break; + case 2: + /* New Meeting */ + e_calendar_view_get_selected_time_range (cal_view, + &dtstart, &dtend); + e_calendar_view_new_appointment_for (cal_view, + dtstart, dtend, FALSE, TRUE); + break; + case 3: + /* Go to today */ + break; + calendar_goto_today (e_calendar_view_get_calendar (cal_view)); + case 4: + /* Go to date */ + goto_dialog (e_calendar_view_get_calendar (cal_view)); + break; + default: + return_value = FALSE; + break; + } + return return_value; +} + +static gint +action_interface_get_n_actions (AtkAction *action) +{ + return CAL_VIEW_ACTION_NUM; +} + +static G_CONST_RETURN gchar * +action_interface_get_description(AtkAction *action, gint index) +{ + return action_interface_action_get_name (action, index); +} + +static G_CONST_RETURN gchar * +action_interface_get_keybinding (AtkAction *action, gint index) +{ + GtkWidget *widget; + + widget = GTK_ACCESSIBLE (action)->widget; + if (widget == NULL) + /* + * State is defunct + */ + return NULL; + + if (!GTK_WIDGET_IS_SENSITIVE (widget) || !GTK_WIDGET_VISIBLE (widget)) + return NULL; + + switch (index) { + case 0: + /* New Appointment */ + return "fna;n"; + case 1: + /* New Event */ + return "fnd;d"; + case 2: + /* New Meeting */ + return "fne;e"; + case 3: + /* Go to today */ + return "vt;t"; + case 4: + /* Go to date */ + return "vd;g"; + default: + break; + } + return NULL; +} + +static G_CONST_RETURN gchar * +action_interface_action_get_name(AtkAction *action, gint i) +{ + if (i >= 0 && i < CAL_VIEW_ACTION_NUM) + return action_name [i]; + return NULL; +} diff --git a/calendar/gui/ea-cal-view.h b/calendar/gui/ea-cal-view.h new file mode 100644 index 0000000000..959f7816b5 --- /dev/null +++ b/calendar/gui/ea-cal-view.h @@ -0,0 +1,58 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_CAL_VIEW_H__ +#define __EA_CAL_VIEW_H__ + +#include +#include "e-calendar-view.h" + +G_BEGIN_DECLS + +#define EA_TYPE_CAL_VIEW (ea_cal_view_get_type ()) +#define EA_CAL_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_CAL_VIEW, EaCalView)) +#define EA_CAL_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_CAL_VIEW, EaCalViewClass)) +#define EA_IS_CAL_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_CAL_VIEW)) +#define EA_IS_CAL_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_CAL_VIEW)) +#define EA_CAL_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_CAL_VIEW, EaCalViewClass)) + +typedef struct _EaCalView EaCalView; +typedef struct _EaCalViewClass EaCalViewClass; + +struct _EaCalView +{ + GtkAccessible parent; +}; + +GType ea_cal_view_get_type (void); + +struct _EaCalViewClass +{ + GtkAccessibleClass parent_class; +}; + +AtkObject* ea_cal_view_new (GtkWidget *widget); + +G_END_DECLS + +#endif /* __EA_CAL_VIEW_H__ */ diff --git a/calendar/gui/ea-calendar-helpers.c b/calendar/gui/ea-calendar-helpers.c new file mode 100644 index 0000000000..f07cdfa086 --- /dev/null +++ b/calendar/gui/ea-calendar-helpers.c @@ -0,0 +1,156 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "ea-calendar-helpers.h" +#include "ea-cal-view-event.h" +#include "ea-jump-button.h" +#include "e-day-view.h" +#include "e-week-view.h" + +#include +#include + +/** + * ea_calendar_helpers_get_accessible_for + * @canvas_item: the canvas item for a event or a jump button + * @returns: the atk object for the canvas_item + * + **/ +AtkObject * +ea_calendar_helpers_get_accessible_for (GnomeCanvasItem *canvas_item) +{ + AtkObject *atk_obj = NULL; + GObject *g_obj; + + g_return_val_if_fail ((E_IS_TEXT (canvas_item)) || (GNOME_IS_CANVAS_ITEM (canvas_item)), NULL);; + + g_obj = G_OBJECT (canvas_item); + /* we cannot use atk_gobject_accessible_for_object here, + * EaDayViewEvent/EaWeekViewEvent cannot be created by the + * registered facotry of E_TEXT + */ + atk_obj = g_object_get_data (g_obj, "accessible-object"); + if (!atk_obj) { + if (E_IS_TEXT (canvas_item)) { + atk_obj = ea_cal_view_event_new (g_obj); + } + else if (GNOME_IS_CANVAS_PIXBUF(canvas_item)) { + atk_obj = ea_jump_button_new (g_obj); + } + else + return NULL; + } + return atk_obj; +} + +/** + * ea_calendar_helpers_get_view_widget_from: + * @canvas_item: the canvas item for a event or a jump button + * @returns: the cal view widget if exists + * + * Get the cal view widget contains the canvas_item. + * + **/ +ECalendarView * +ea_calendar_helpers_get_cal_view_from (GnomeCanvasItem *canvas_item) +{ + GnomeCanvas *canvas; + GtkWidget *view_widget = NULL; + + g_return_val_if_fail (canvas_item, NULL); + g_return_val_if_fail ((E_IS_TEXT (canvas_item)) || (GNOME_IS_CANVAS_ITEM (canvas_item)), NULL); + + /* canvas_item is the e_text for the event */ + /* canvas_item->canvas is the ECanvas for day view */ + /* parent of canvas_item->canvas is the EDayView or EWeekView widget */ + canvas = canvas_item->canvas; + view_widget = gtk_widget_get_parent (GTK_WIDGET(canvas)); + if (!view_widget || !E_IS_CALENDAR_VIEW (view_widget)) + return NULL; + + return E_CALENDAR_VIEW (view_widget); +} + +/** + * ea_calendar_helpers_get_cal_view_event_from + * @canvas_item: the cavas_item (e_text) for the event + * @returns: the ECalendarViewEvent + * + * Get the ECalendarViewEvent for the canvas_item. + * + **/ +ECalendarViewEvent * +ea_calendar_helpers_get_cal_view_event_from (GnomeCanvasItem *canvas_item) +{ + ECalendarView *cal_view; + gboolean event_found; + ECalendarViewEvent *cal_view_event; + + g_return_val_if_fail (E_IS_TEXT (canvas_item), NULL); + + cal_view = ea_calendar_helpers_get_cal_view_from (canvas_item); + + if (!cal_view) + return NULL; + + if (E_IS_DAY_VIEW (cal_view)) { + gint event_day, event_num; + EDayViewEvent *day_view_event; + EDayView *day_view = E_DAY_VIEW (cal_view); + event_found = e_day_view_find_event_from_item (day_view, canvas_item, + &event_day, &event_num); + if (!event_found) + return NULL; + if (event_day == E_DAY_VIEW_LONG_EVENT) { + /* a long event */ + day_view_event = &g_array_index (day_view->long_events, + EDayViewEvent, event_num); + } + else { + /* a main canvas event */ + day_view_event = &g_array_index (day_view->events[event_day], + EDayViewEvent, event_num); + } + cal_view_event = (ECalendarViewEvent *) day_view_event; + } + else if (E_IS_WEEK_VIEW (cal_view)) { + gint event_num, span_num; + EWeekViewEvent *week_view_event; + EWeekView *week_view = E_WEEK_VIEW (cal_view); + event_found = e_week_view_find_event_from_item (week_view, + canvas_item, + &event_num, + &span_num); + if (!event_found) + return NULL; + + week_view_event = &g_array_index (week_view->events, EWeekViewEvent, + event_num); + + cal_view_event = (ECalendarViewEvent *)week_view_event; + } + else { + g_return_val_if_reached (NULL); + } + return cal_view_event; +} diff --git a/calendar/gui/ea-calendar-helpers.h b/calendar/gui/ea-calendar-helpers.h new file mode 100644 index 0000000000..a4045cd7af --- /dev/null +++ b/calendar/gui/ea-calendar-helpers.h @@ -0,0 +1,41 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/* Evolution Accessibility + */ + +#ifndef _EA_CALENDAR_HELPERS_H__ +#define _EA_CALENDAR_HELPERS_H__ + +#include "ea-cal-view.h" + +AtkObject * +ea_calendar_helpers_get_accessible_for (GnomeCanvasItem *canvas_item); + +ECalendarView * +ea_calendar_helpers_get_cal_view_from (GnomeCanvasItem *canvas_item); + +ECalendarViewEvent * +ea_calendar_helpers_get_cal_view_event_from (GnomeCanvasItem *canvas_item); + +#endif /* _EA_CALENDAR_HELPERS_H__ */ diff --git a/calendar/gui/ea-calendar.c b/calendar/gui/ea-calendar.c new file mode 100644 index 0000000000..d09efae4d2 --- /dev/null +++ b/calendar/gui/ea-calendar.c @@ -0,0 +1,204 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include +#include +#include "ea-calendar-helpers.h" +#include "a11y/ea-factory.h" +#include "ea-calendar.h" + +#include "calendar/ea-cal-view.h" +#include "calendar/ea-cal-view-event.h" +#include "calendar/ea-day-view.h" +#include "calendar/ea-day-view-main-item.h" +#include "calendar/ea-week-view.h" +#include "calendar/ea-week-view-main-item.h" +#include "calendar/ea-gnome-calendar.h" + + +EA_FACTORY (EA_TYPE_CAL_VIEW, ea_cal_view, ea_cal_view_new) +EA_FACTORY (EA_TYPE_DAY_VIEW, ea_day_view, ea_day_view_new) +EA_FACTORY_GOBJECT (EA_TYPE_DAY_VIEW_MAIN_ITEM, ea_day_view_main_item, ea_day_view_main_item_new) +EA_FACTORY (EA_TYPE_WEEK_VIEW, ea_week_view, ea_week_view_new) +EA_FACTORY_GOBJECT (EA_TYPE_WEEK_VIEW_MAIN_ITEM, ea_week_view_main_item, ea_week_view_main_item_new) +EA_FACTORY (EA_TYPE_GNOME_CALENDAR, ea_gnome_calendar, ea_gnome_calendar_new) + +static gboolean ea_calendar_focus_watcher (GSignalInvocationHint *ihint, + guint n_param_values, + const GValue *param_values, + gpointer data); + +static gpointer e_text_type, pixbuf_type, e_day_view_type, e_week_view_type; +static gpointer e_day_view_main_item_type, e_week_view_main_item_type; + +void +gnome_calendar_a11y_init (void) +{ + /* we only add focus watcher when accessibility is enabled + */ + if (atk_get_root ()) { + EA_SET_FACTORY (gnome_calendar_get_type(), ea_gnome_calendar); + + /* force loading some types */ + e_text_type = g_type_class_ref (E_TYPE_TEXT); + pixbuf_type = g_type_class_ref (GNOME_TYPE_CANVAS_PIXBUF); + e_day_view_type = g_type_class_ref (e_day_view_get_type ()); + e_week_view_type = g_type_class_ref (e_week_view_get_type ()); + e_day_view_main_item_type = g_type_class_ref (e_day_view_main_item_get_type ()); + e_week_view_main_item_type = g_type_class_ref (e_week_view_main_item_get_type ()); + + g_signal_add_emission_hook (g_signal_lookup ("event", E_TYPE_TEXT), + 0, ea_calendar_focus_watcher, + NULL, (GDestroyNotify) NULL); + g_signal_add_emission_hook (g_signal_lookup ("event", GNOME_TYPE_CANVAS_PIXBUF), + 0, ea_calendar_focus_watcher, + NULL, (GDestroyNotify) NULL); + g_signal_add_emission_hook (g_signal_lookup ("event-after", + e_day_view_get_type()), + 0, ea_calendar_focus_watcher, + NULL, (GDestroyNotify) NULL); + g_signal_add_emission_hook (g_signal_lookup ("event", + e_day_view_main_item_get_type()), + 0, ea_calendar_focus_watcher, + NULL, (GDestroyNotify) NULL); + g_signal_add_emission_hook (g_signal_lookup ("event-after", + e_week_view_get_type()), + 0, ea_calendar_focus_watcher, + NULL, (GDestroyNotify) NULL); + g_signal_add_emission_hook (g_signal_lookup ("event", + e_week_view_main_item_get_type()), + 0, ea_calendar_focus_watcher, + NULL, (GDestroyNotify) NULL); + + } +} + +void +e_cal_view_a11y_init (void) +{ + EA_SET_FACTORY (e_calendar_view_get_type(), ea_cal_view); +} + +void +e_day_view_a11y_init (void) +{ + EA_SET_FACTORY (e_day_view_get_type(), ea_day_view); +} + +void +e_day_view_main_item_a11y_init (void) +{ + EA_SET_FACTORY (e_day_view_main_item_get_type (), ea_day_view_main_item); +} + +void +e_week_view_a11y_init (void) +{ + EA_SET_FACTORY (e_week_view_get_type(), ea_week_view); +} + +void +e_week_view_main_item_a11y_init (void) +{ + EA_SET_FACTORY (e_week_view_main_item_get_type (), ea_week_view_main_item); +} + +static gboolean +ea_calendar_focus_watcher (GSignalInvocationHint *ihint, + guint n_param_values, + const GValue *param_values, + gpointer data) +{ + GObject *object; + GdkEvent *event; + AtkObject *ea_event = NULL; + + object = g_value_get_object (param_values + 0); + event = g_value_get_boxed (param_values + 1); + + if ((E_IS_TEXT (object)) || (GNOME_IS_CANVAS_PIXBUF (object))) { + /* "event" signal on canvas item + */ + GnomeCanvasItem *canvas_item; + + canvas_item = GNOME_CANVAS_ITEM (object); + if (event->type == GDK_FOCUS_CHANGE) { + if (event->focus_change.in) { + ea_event = + ea_calendar_helpers_get_accessible_for (canvas_item); + if (!ea_event) + /* not canvas item we want */ + return TRUE; + + } + atk_focus_tracker_notify (ea_event); + } + } + else if (E_IS_DAY_VIEW (object)) { + EDayView *day_view = E_DAY_VIEW (object); + if (event->type == GDK_FOCUS_CHANGE) { + if (event->focus_change.in) { + /* give main item chance to emit focus */ + gnome_canvas_item_grab_focus (day_view->main_canvas_item); + } + } + } + else if (E_IS_DAY_VIEW_MAIN_ITEM (object)) { + if (event->type == GDK_FOCUS_CHANGE) { + if (event->focus_change.in) { + /* we should emit focus on main item */ + ea_event = atk_gobject_accessible_for_object (object); + } + else + /* focus out */ + ea_event = NULL; +#ifdef ACC_DEBUG + printf ("EvoAcc: focus notify on day main item %p\n", (gpointer)object); +#endif + atk_focus_tracker_notify (ea_event); + } + } else if (E_IS_WEEK_VIEW (object)) { + EWeekView *week_view = E_WEEK_VIEW (object); + if (event->type == GDK_FOCUS_CHANGE) { + if (event->focus_change.in) { + /* give main item chance to emit focus */ + gnome_canvas_item_grab_focus (week_view->main_canvas_item); + } + } + } + else if (E_IS_WEEK_VIEW_MAIN_ITEM (object)) { + if (event->type == GDK_FOCUS_CHANGE) { + if (event->focus_change.in) { + /* we should emit focus on main item */ + ea_event = atk_gobject_accessible_for_object (object); + } + else + /* focus out */ + ea_event = NULL; +#ifdef ACC_DEBUG + printf ("EvoAcc: focus notify on week main item %p\n", (gpointer)object); +#endif + atk_focus_tracker_notify (ea_event); + } + } + return TRUE; +} diff --git a/calendar/gui/ea-calendar.h b/calendar/gui/ea-calendar.h new file mode 100644 index 0000000000..b2238ffdbc --- /dev/null +++ b/calendar/gui/ea-calendar.h @@ -0,0 +1,37 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/* Evolution Accessibility +*/ + +#ifndef _EA_CALENDAR_H__ +#define _EA_CALENDAR_H__ + +void gnome_calendar_a11y_init (void); +void e_cal_view_a11y_init (void); +void e_day_view_a11y_init (void); +void e_day_view_main_item_a11y_init (void); +void e_week_view_a11y_init (void); +void e_week_view_main_item_a11y_init (void); + +#endif /* _EA_CALENDAR_H__ */ diff --git a/calendar/gui/ea-day-view-cell.c b/calendar/gui/ea-day-view-cell.c new file mode 100644 index 0000000000..fa491e87ea --- /dev/null +++ b/calendar/gui/ea-day-view-cell.c @@ -0,0 +1,396 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "ea-day-view-cell.h" +#include "ea-day-view-main-item.h" +#include "ea-day-view.h" +#include "a11y/ea-factory.h" + +/* EDayViewCell */ + +static void e_day_view_cell_class_init (EDayViewCellClass *class); + +EA_FACTORY_GOBJECT (EA_TYPE_DAY_VIEW_CELL, ea_day_view_cell, ea_day_view_cell_new) + +GType +e_day_view_cell_get_type (void) +{ + static GType type = 0; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EDayViewCellClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) e_day_view_cell_class_init, /* class init */ + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (EDayViewCell), /* instance size */ + 0, /* nb preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + type = g_type_register_static (G_TYPE_OBJECT, + "EDayViewCell", &tinfo, 0); + } + + return type; +} + +static void +e_day_view_cell_class_init (EDayViewCellClass *class) +{ + EA_SET_FACTORY (e_day_view_cell_get_type (), ea_day_view_cell); +} + +EDayViewCell * +e_day_view_cell_new (EDayView *day_view, gint row, gint column) +{ + GObject *object; + EDayViewCell *cell; + + g_return_val_if_fail (E_IS_DAY_VIEW (day_view), NULL); + + object = g_object_new (E_TYPE_DAY_VIEW_CELL, NULL); + cell = E_DAY_VIEW_CELL (object); + cell->day_view = day_view; + cell->row = row; + cell->column = column; + +#ifdef ACC_DEBUG + printf ("EvoAcc: e_day_view_cell created %p\n", (gpointer)cell); +#endif + + return cell; +} + +/* EaDayViewCell */ + +static void ea_day_view_cell_class_init (EaDayViewCellClass *klass); + +static G_CONST_RETURN gchar * ea_day_view_cell_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar * ea_day_view_cell_get_description (AtkObject *accessible); +static AtkStateSet* ea_day_view_cell_ref_state_set (AtkObject *obj); +static AtkObject * ea_day_view_cell_get_parent (AtkObject *accessible); +static gint ea_day_view_cell_get_index_in_parent (AtkObject *accessible); + +/* component interface */ +static void atk_component_interface_init (AtkComponentIface *iface); +static void component_interface_get_extents (AtkComponent *component, + gint *x, gint *y, + gint *width, gint *height, + AtkCoordType coord_type); +static gboolean component_interface_grab_focus (AtkComponent *component); + +static gpointer parent_class = NULL; + +#ifdef ACC_DEBUG +static gint n_ea_day_view_cell_created = 0, n_ea_day_view_cell_destroyed = 0; +static void ea_day_view_cell_finalize (GObject *object); +#endif + +GType +ea_day_view_cell_get_type (void) +{ + static GType type = 0; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaDayViewCellClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) ea_day_view_cell_class_init, /* class init */ + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (EaDayViewCell), /* instance size */ + 0, /* nb preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) atk_component_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + type = g_type_register_static (ATK_TYPE_GOBJECT_ACCESSIBLE, + "EaDayViewCell", &tinfo, 0); + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, + &atk_component_info); + } + + return type; +} + +static void +ea_day_view_cell_class_init (EaDayViewCellClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + +#ifdef ACC_DEBUG + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = ea_day_view_cell_finalize; +#endif + + parent_class = g_type_class_peek_parent (klass); + + class->get_name = ea_day_view_cell_get_name; + class->get_description = ea_day_view_cell_get_description; + class->ref_state_set = ea_day_view_cell_ref_state_set; + + class->get_parent = ea_day_view_cell_get_parent; + class->get_index_in_parent = ea_day_view_cell_get_index_in_parent; +} + +AtkObject* +ea_day_view_cell_new (GObject *obj) +{ + gpointer object; + AtkObject *atk_object; + + g_return_val_if_fail (E_IS_DAY_VIEW_CELL (obj), NULL); + + object = g_object_new (EA_TYPE_DAY_VIEW_CELL, NULL); + atk_object = ATK_OBJECT (object); + atk_object_initialize (atk_object, obj); + atk_object->role = ATK_ROLE_UNKNOWN; + +#ifdef ACC_DEBUG + ++n_ea_day_view_cell_created; + printf ("ACC_DEBUG: n_ea_day_view_cell_created = %d\n", + n_ea_day_view_cell_created); +#endif + return atk_object; +} + +#ifdef ACC_DEBUG +static void ea_day_view_cell_finalize (GObject *object) +{ + G_OBJECT_CLASS (parent_class)->finalize (object); + + ++n_ea_day_view_cell_destroyed; + printf ("ACC_DEBUG: n_ea_day_view_cell_destroyed = %d\n", + n_ea_day_view_cell_destroyed); +} +#endif + +static G_CONST_RETURN gchar * +ea_day_view_cell_get_name (AtkObject *accessible) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewCell *cell; + + g_return_val_if_fail (EA_IS_DAY_VIEW_CELL (accessible), NULL); + + if (!accessible->name) { + AtkObject *ea_main_item; + GnomeCanvasItem *main_item; + gchar *new_name = g_strdup (""); + const gchar *row_label, *column_label; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + cell = E_DAY_VIEW_CELL (g_obj); + main_item = cell->day_view->main_canvas_item; + ea_main_item = atk_gobject_accessible_for_object (G_OBJECT (main_item)); + column_label = atk_table_get_column_description (ATK_TABLE (ea_main_item), + cell->column); + row_label = atk_table_get_row_description (ATK_TABLE (ea_main_item), + cell->row); + new_name = g_strconcat (column_label, " ", row_label, NULL); + ATK_OBJECT_CLASS (parent_class)->set_name (accessible, new_name); + g_free (new_name); + } + return accessible->name; +} + +static G_CONST_RETURN gchar * +ea_day_view_cell_get_description (AtkObject *accessible) +{ + return ea_day_view_cell_get_name (accessible); +} + +static AtkStateSet* +ea_day_view_cell_ref_state_set (AtkObject *obj) +{ + AtkStateSet *state_set; + GObject *g_obj; + AtkObject *parent; + gint x, y, width, height; + gint parent_x, parent_y, parent_width, parent_height; + + state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (obj); + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(obj)); + if (!g_obj) + return state_set; + + atk_state_set_add_state (state_set, ATK_STATE_SELECTABLE); + + parent = atk_object_get_parent (obj); + atk_component_get_extents (ATK_COMPONENT (obj), &x, &y, + &width, &height, ATK_XY_WINDOW); + atk_component_get_extents (ATK_COMPONENT (parent), &parent_x, &parent_y, + &parent_width, &parent_height, ATK_XY_WINDOW); + + + if (x + width < parent_x || x > parent_x + parent_width || + y + height < parent_y || y > parent_y + parent_height) + /* the cell is out of the main canvas */ + ; + else + atk_state_set_add_state (state_set, ATK_STATE_VISIBLE); + + return state_set; +} + +static AtkObject * +ea_day_view_cell_get_parent (AtkObject *accessible) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewCell *cell; + + g_return_val_if_fail (EA_IS_DAY_VIEW_CELL (accessible), NULL); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + cell = E_DAY_VIEW_CELL (g_obj); + return atk_gobject_accessible_for_object (G_OBJECT (cell->day_view->main_canvas_item)); +} + +static gint +ea_day_view_cell_get_index_in_parent (AtkObject *accessible) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewCell *cell; + AtkObject *parent; + + g_return_val_if_fail (EA_IS_DAY_VIEW_CELL (accessible), -1); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + cell = E_DAY_VIEW_CELL (g_obj); + parent = atk_object_get_parent (accessible); + return atk_table_get_index_at (ATK_TABLE (parent), + cell->row, cell->column); +} + +/* Atk Component Interface */ + +static void +atk_component_interface_init (AtkComponentIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->get_extents = component_interface_get_extents; + iface->grab_focus = component_interface_grab_focus; +} + +static void +component_interface_get_extents (AtkComponent *component, + gint *x, gint *y, gint *width, gint *height, + AtkCoordType coord_type) +{ + GObject *g_obj; + AtkObject *atk_obj; + EDayViewCell *cell; + EDayView *day_view; + GtkWidget *main_canvas; + gint day_view_width, day_view_height; + gint scroll_x, scroll_y; + + *x = *y = *width = *height = 0; + + g_return_if_fail (EA_IS_DAY_VIEW_CELL (component)); + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(component)); + if (!g_obj) + /* defunct object*/ + return; + + cell = E_DAY_VIEW_CELL (g_obj); + day_view = cell->day_view; + main_canvas = cell->day_view->main_canvas; + + atk_obj = atk_gobject_accessible_for_object (G_OBJECT (main_canvas)); + atk_component_get_extents (ATK_COMPONENT (atk_obj), + x, y, + &day_view_width, &day_view_height, + coord_type); + gnome_canvas_get_scroll_offsets (GNOME_CANVAS (day_view->main_canvas), + &scroll_x, &scroll_y); + *x += day_view->day_offsets[cell->column] - scroll_x; + *y += day_view->row_height * cell->row + - scroll_y; + *width = day_view->day_widths[cell->column]; + *height = day_view->row_height; +} + +static gboolean +component_interface_grab_focus (AtkComponent *comp) +{ + GObject *g_obj; + EDayViewCell *cell; + EDayView *day_view; + GtkWidget *toplevel; + + g_return_val_if_fail (EA_IS_DAY_VIEW_CELL (comp), FALSE); + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (comp)); + if (!g_obj) + return FALSE; + + cell = E_DAY_VIEW_CELL (g_obj); + day_view = cell->day_view; + + day_view->selection_start_day = cell->column; + day_view->selection_end_day = cell->column; + day_view->selection_start_row = cell->row; + day_view->selection_end_row = cell->row; + + e_day_view_ensure_rows_visible (day_view, + day_view->selection_start_row, + day_view->selection_end_row); + e_day_view_update_calendar_selection_time (day_view); + gtk_widget_queue_draw (day_view->main_canvas); + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (day_view)); + if (GTK_WIDGET_TOPLEVEL (toplevel)) + gtk_window_present (GTK_WINDOW (toplevel)); + + return TRUE; +} + diff --git a/calendar/gui/ea-day-view-cell.h b/calendar/gui/ea-day-view-cell.h new file mode 100644 index 0000000000..669fb1abae --- /dev/null +++ b/calendar/gui/ea-day-view-cell.h @@ -0,0 +1,85 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_DAY_VIEW_CELL_H__ +#define __EA_DAY_VIEW_CELL_H__ + +#include +#include "e-day-view.h" + +G_BEGIN_DECLS + +#define E_TYPE_DAY_VIEW_CELL (e_day_view_cell_get_type ()) +#define E_DAY_VIEW_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_DAY_VIEW_CELL, EDayViewCell)) +#define E_DAY_VIEW_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_DAY_VIEW_CELL, EDayViewCellClass)) +#define E_IS_DAY_VIEW_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_DAY_VIEW_CELL)) +#define E_IS_DAY_VIEW_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_DAY_VIEW_CELL)) +#define E_DAY_VIEW_CELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_DAY_VIEW_CELL, EDayViewCellClass)) + +typedef struct _EDayViewCell EDayViewCell; +typedef struct _EDayViewCellClass EDayViewCellClass; + +struct _EDayViewCell +{ + GObject parent; + EDayView *day_view; + gint row; + gint column; +}; + +GType e_day_view_cell_get_type (void); + +struct _EDayViewCellClass +{ + GObjectClass parent_class; +}; + +EDayViewCell * e_day_view_cell_new (EDayView *day_view, gint row, gint column); + +#define EA_TYPE_DAY_VIEW_CELL (ea_day_view_cell_get_type ()) +#define EA_DAY_VIEW_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_DAY_VIEW_CELL, EaDayViewCell)) +#define EA_DAY_VIEW_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_DAY_VIEW_CELL, EaDayViewCellClass)) +#define EA_IS_DAY_VIEW_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_DAY_VIEW_CELL)) +#define EA_IS_DAY_VIEW_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_DAY_VIEW_CELL)) +#define EA_DAY_VIEW_CELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_DAY_VIEW_CELL, EaDayViewCellClass)) + +typedef struct _EaDayViewCell EaDayViewCell; +typedef struct _EaDayViewCellClass EaDayViewCellClass; + +struct _EaDayViewCell +{ + AtkGObjectAccessible parent; +}; + +GType ea_day_view_cell_get_type (void); + +struct _EaDayViewCellClass +{ + AtkGObjectAccessibleClass parent_class; +}; + +AtkObject* ea_day_view_cell_new (GObject *gobj); + +G_END_DECLS + +#endif /* __EA_DAY_VIEW_CELL_H__ */ diff --git a/calendar/gui/ea-day-view-main-item.c b/calendar/gui/ea-day-view-main-item.c new file mode 100644 index 0000000000..3bfd56f0b3 --- /dev/null +++ b/calendar/gui/ea-day-view-main-item.c @@ -0,0 +1,1289 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "ea-day-view-main-item.h" +#include "e-day-view-top-item.h" +#include "ea-day-view.h" +#include "ea-day-view-cell.h" +#include "ea-cell-table.h" +#include + +/* EaDayViewMainItem */ +static void ea_day_view_main_item_class_init (EaDayViewMainItemClass *klass); + +static void ea_day_view_main_item_finalize (GObject *object); +static G_CONST_RETURN gchar * ea_day_view_main_item_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar * ea_day_view_main_item_get_description (AtkObject *accessible); + +static gint ea_day_view_main_item_get_n_children (AtkObject *obj); +static AtkObject* ea_day_view_main_item_ref_child (AtkObject *obj, + gint i); +static AtkObject * ea_day_view_main_item_get_parent (AtkObject *accessible); +static gint ea_day_view_main_item_get_index_in_parent (AtkObject *accessible); + +/* callbacks */ +static void ea_day_view_main_item_dates_change_cb (GnomeCalendar *gcal, gpointer data); +static void ea_day_view_main_item_time_change_cb (EDayView *day_view, gpointer data); + +/* component interface */ +static void atk_component_interface_init (AtkComponentIface *iface); +static void component_interface_get_extents (AtkComponent *component, + gint *x, gint *y, + gint *width, gint *height, + AtkCoordType coord_type); +/* atk table interface */ +static void atk_table_interface_init (AtkTableIface *iface); +static gint table_interface_get_index_at (AtkTable *table, + gint row, + gint column); +static gint table_interface_get_column_at_index (AtkTable *table, + gint index); +static gint table_interface_get_row_at_index (AtkTable *table, + gint index); +static AtkObject* table_interface_ref_at (AtkTable *table, + gint row, + gint column); +static gint table_interface_get_n_rows (AtkTable *table); +static gint table_interface_get_n_columns (AtkTable *table); +static gint table_interface_get_column_extent_at (AtkTable *table, + gint row, + gint column); +static gint table_interface_get_row_extent_at (AtkTable *table, + gint row, + gint column); + +static gboolean table_interface_is_row_selected (AtkTable *table, + gint row); +static gboolean table_interface_is_column_selected (AtkTable *table, + gint row); +static gboolean table_interface_is_selected (AtkTable *table, + gint row, + gint column); +static gint table_interface_get_selected_rows (AtkTable *table, + gint **rows_selected); +static gint table_interface_get_selected_columns (AtkTable *table, + gint **columns_selected); +static gboolean table_interface_add_row_selection (AtkTable *table, gint row); +static gboolean table_interface_remove_row_selection (AtkTable *table, + gint row); +static gboolean table_interface_add_column_selection (AtkTable *table, + gint column); +static gboolean table_interface_remove_column_selection (AtkTable *table, + gint column); +static AtkObject* table_interface_get_row_header (AtkTable *table, gint row); +static AtkObject* table_interface_get_column_header (AtkTable *table, + gint in_col); +static AtkObject* table_interface_get_caption (AtkTable *table); + +static G_CONST_RETURN gchar * +table_interface_get_column_description (AtkTable *table, gint in_col); + +static G_CONST_RETURN gchar * +table_interface_get_row_description (AtkTable *table, gint row); + +static AtkObject* table_interface_get_summary (AtkTable *table); + +/* atk selection interface */ +static void atk_selection_interface_init (AtkSelectionIface *iface); +static gboolean selection_interface_add_selection (AtkSelection *selection, + gint i); +static gboolean selection_interface_clear_selection (AtkSelection *selection); +static AtkObject* selection_interface_ref_selection (AtkSelection *selection, + gint i); +static gint selection_interface_get_selection_count (AtkSelection *selection); +static gboolean selection_interface_is_child_selected (AtkSelection *selection, + gint i); + +/* helpers */ +static EaCellTable * +ea_day_view_main_item_get_cell_data (EaDayViewMainItem *ea_main_item); + +static void +ea_day_view_main_item_destory_cell_data (EaDayViewMainItem *ea_main_item); + +static gint +ea_day_view_main_item_get_child_index_at (EaDayViewMainItem *ea_main_item, + gint row, gint column); +static gint +ea_day_view_main_item_get_row_at_index (EaDayViewMainItem *ea_main_item, + gint index); +static gint +ea_day_view_main_item_get_column_at_index (EaDayViewMainItem *ea_main_item, + gint index); +static gint +ea_day_view_main_item_get_row_label (EaDayViewMainItem *ea_main_item, + gint row, gchar *buffer, + gint buffer_size); + +#ifdef ACC_DEBUG +static gint n_ea_day_view_main_item_created = 0; +static gint n_ea_day_view_main_item_destroyed = 0; +#endif + +static gpointer parent_class = NULL; + +GType +ea_day_view_main_item_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaDayViewMainItemClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) ea_day_view_main_item_class_init, + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (EaDayViewMainItem), /* instance size */ + 0, /* nb preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) atk_component_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + static const GInterfaceInfo atk_table_info = { + (GInterfaceInitFunc) atk_table_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + static const GInterfaceInfo atk_selection_info = { + (GInterfaceInitFunc) atk_selection_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (GailCanvasItem, in this case) + * + */ + + factory = atk_registry_get_factory (atk_get_default_registry (), + e_day_view_main_item_get_type()); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + type = g_type_register_static (derived_atk_type, + "EaDayViewMainItem", &tinfo, 0); + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, + &atk_component_info); + g_type_add_interface_static (type, ATK_TYPE_TABLE, + &atk_table_info); + g_type_add_interface_static (type, ATK_TYPE_SELECTION, + &atk_selection_info); + } + + return type; +} + +static void +ea_day_view_main_item_class_init (EaDayViewMainItemClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + gobject_class->finalize = ea_day_view_main_item_finalize; + parent_class = g_type_class_peek_parent (klass); + + class->get_name = ea_day_view_main_item_get_name; + class->get_description = ea_day_view_main_item_get_description; + + class->get_n_children = ea_day_view_main_item_get_n_children; + class->ref_child = ea_day_view_main_item_ref_child; + class->get_parent = ea_day_view_main_item_get_parent; + class->get_index_in_parent = ea_day_view_main_item_get_index_in_parent; +} + +AtkObject* +ea_day_view_main_item_new (GObject *obj) +{ + AtkObject *accessible; + GnomeCalendar *gcal; + EDayViewMainItem *main_item; + + g_return_val_if_fail (E_IS_DAY_VIEW_MAIN_ITEM (obj), NULL); + + accessible = ATK_OBJECT (g_object_new (EA_TYPE_DAY_VIEW_MAIN_ITEM, + NULL)); + + atk_object_initialize (accessible, obj); + accessible->role = ATK_ROLE_TABLE; + +#ifdef ACC_DEBUG + ++n_ea_day_view_main_item_created; + printf ("ACC_DEBUG: n_ea_day_view_main_item_created = %d\n", + n_ea_day_view_main_item_created); +#endif + main_item = E_DAY_VIEW_MAIN_ITEM (obj); + g_signal_connect (main_item->day_view, "selected_time_changed", + G_CALLBACK (ea_day_view_main_item_time_change_cb), + accessible); + + /* listen for date changes of calendar */ + gcal = e_calendar_view_get_calendar (E_CALENDAR_VIEW (main_item->day_view)); + if (gcal) + g_signal_connect (gcal, "dates_shown_changed", + G_CALLBACK (ea_day_view_main_item_dates_change_cb), + accessible); + + return accessible; +} + +static void +ea_day_view_main_item_finalize (GObject *object) +{ + EaDayViewMainItem *ea_main_item; + + g_return_if_fail (EA_IS_DAY_VIEW_MAIN_ITEM (object)); + + ea_main_item = EA_DAY_VIEW_MAIN_ITEM (object); + + /* Free the allocated cell data */ + ea_day_view_main_item_destory_cell_data (ea_main_item); + + G_OBJECT_CLASS (parent_class)->finalize (object); +#ifdef ACC_DEBUG + ++n_ea_day_view_main_item_destroyed; + printf ("ACC_DEBUG: n_ea_day_view_main_item_destroyed = %d\n", + n_ea_day_view_main_item_destroyed); +#endif +} + +static G_CONST_RETURN gchar * +ea_day_view_main_item_get_name (AtkObject *accessible) +{ + AtkObject *parent; + g_return_val_if_fail (EA_IS_DAY_VIEW_MAIN_ITEM (accessible), NULL); + parent = atk_object_get_parent (accessible); + + if (!parent) + return NULL; + + return atk_object_get_name (parent); +} + +static G_CONST_RETURN gchar * +ea_day_view_main_item_get_description (AtkObject *accessible) +{ + return _("a table to view and select the current time range"); +} + +static gint +ea_day_view_main_item_get_n_children (AtkObject *accessible) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + + g_return_val_if_fail (EA_IS_DAY_VIEW_MAIN_ITEM (accessible), -1); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + return day_view->rows * day_view->days_shown; +} + +static AtkObject * +ea_day_view_main_item_ref_child (AtkObject *accessible, gint index) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + gint n_children; + EDayViewCell *cell; + EaCellTable *cell_data; + EaDayViewMainItem *ea_main_item; + + g_return_val_if_fail (EA_IS_DAY_VIEW_MAIN_ITEM (accessible), NULL); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + n_children = ea_day_view_main_item_get_n_children (accessible); + if (index < 0 || index >= n_children) + return NULL; + + ea_main_item = EA_DAY_VIEW_MAIN_ITEM (accessible); + cell_data = ea_day_view_main_item_get_cell_data (ea_main_item); + if (!cell_data) + return NULL; + + cell = ea_cell_table_get_cell_at_index (cell_data, index); + if (!cell) { + gint row, column; + + row = ea_day_view_main_item_get_row_at_index (ea_main_item, index); + column = ea_day_view_main_item_get_column_at_index (ea_main_item, index); + cell = e_day_view_cell_new (day_view, row, column); + ea_cell_table_set_cell_at_index (cell_data, index, cell); + g_object_unref (cell); + } + return g_object_ref (atk_gobject_accessible_for_object (G_OBJECT(cell))); +} + +static AtkObject * +ea_day_view_main_item_get_parent (AtkObject *accessible) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + + g_return_val_if_fail (EA_IS_DAY_VIEW_MAIN_ITEM (accessible), NULL); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + return gtk_widget_get_accessible (GTK_WIDGET (main_item->day_view)); +} + +static gint +ea_day_view_main_item_get_index_in_parent (AtkObject *accessible) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + + g_return_val_if_fail (EA_IS_DAY_VIEW_MAIN_ITEM (accessible), -1); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + /* always the first child of ea-day-view */ + return 0; +} + +/* callbacks */ + +static void +ea_day_view_main_item_dates_change_cb (GnomeCalendar *gcal, gpointer data) +{ + EaDayViewMainItem *ea_main_item; + + g_return_if_fail (GNOME_IS_CALENDAR (gcal)); + g_return_if_fail (data); + g_return_if_fail (EA_IS_DAY_VIEW_MAIN_ITEM (data)); + + ea_main_item = EA_DAY_VIEW_MAIN_ITEM (data); + +#ifdef ACC_DEBUG + printf ("EvoAcc: ea_day_view_main_item update cb\n"); +#endif + + ea_day_view_main_item_destory_cell_data (ea_main_item); +} + +static void +ea_day_view_main_item_time_change_cb (EDayView *day_view, gpointer data) +{ + EaDayViewMainItem *ea_main_item; + AtkObject *item_cell = NULL; + + g_return_if_fail (E_IS_DAY_VIEW (day_view)); + g_return_if_fail (data); + g_return_if_fail (EA_IS_DAY_VIEW_MAIN_ITEM (data)); + + ea_main_item = EA_DAY_VIEW_MAIN_ITEM (data); + +#ifdef ACC_DEBUG + printf ("EvoAcc: ea_day_view_main_item time changed cb\n"); +#endif + /* only deal with the first selected child, for now */ + item_cell = atk_selection_ref_selection (ATK_SELECTION (ea_main_item), + 0); + if (item_cell) { + AtkStateSet *state_set; + state_set = atk_object_ref_state_set (item_cell); + atk_state_set_add_state (state_set, ATK_STATE_FOCUSED); + g_object_unref (state_set); + + g_signal_emit_by_name (ea_main_item, + "active-descendant-changed", + item_cell); + g_signal_emit_by_name (data, "selection_changed"); + + atk_focus_tracker_notify (item_cell); + g_object_unref (item_cell); + } + +} + +/* helpers */ + +static gint +ea_day_view_main_item_get_child_index_at (EaDayViewMainItem *ea_main_item, + gint row, gint column) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + + g_return_val_if_fail (ea_main_item, -1); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + if (row >= 0 && row < day_view->rows && + column >= 0 && column < day_view->days_shown) + return column * day_view->rows + row; + return -1; +} + +static gint +ea_day_view_main_item_get_row_at_index (EaDayViewMainItem *ea_main_item, + gint index) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + gint n_children; + + g_return_val_if_fail (ea_main_item, -1); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + n_children = ea_day_view_main_item_get_n_children (ATK_OBJECT (ea_main_item)); + if (index >= 0 && index < n_children) + return index % day_view->rows; + return -1; +} + +static gint +ea_day_view_main_item_get_column_at_index (EaDayViewMainItem *ea_main_item, + gint index) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + gint n_children; + + g_return_val_if_fail (ea_main_item, -1); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + n_children = ea_day_view_main_item_get_n_children (ATK_OBJECT (ea_main_item)); + if (index >= 0 && index < n_children) + return index / day_view->rows; + return -1; +} + +static gint +ea_day_view_main_item_get_row_label (EaDayViewMainItem *ea_main_item, + gint row, gchar *buffer, gint buffer_size) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + const gchar *suffix; + gint hour, minute, suffix_width; + + g_return_val_if_fail (ea_main_item, 0); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return 0; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + hour = day_view->first_hour_shown; + minute = day_view->first_minute_shown; + minute += row * day_view->mins_per_row; + hour = (hour + minute / 60) % 24; + minute %= 60; + + e_day_view_convert_time_to_display (day_view, hour, &hour, + &suffix, &suffix_width); + return g_snprintf (buffer, buffer_size, "%i:%02i %s", + hour, minute, suffix); +} + +static EaCellTable * +ea_day_view_main_item_get_cell_data (EaDayViewMainItem *ea_main_item) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + EaCellTable *cell_data; + + g_return_val_if_fail (ea_main_item, NULL); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + cell_data = g_object_get_data (G_OBJECT(ea_main_item), + "ea-day-view-cell-table"); + if (!cell_data) { + cell_data = ea_cell_table_create (day_view->rows, + day_view->days_shown, TRUE); + g_object_set_data (G_OBJECT(ea_main_item), + "ea-day-view-cell-table", cell_data); + } + return cell_data; +} + +static void +ea_day_view_main_item_destory_cell_data (EaDayViewMainItem *ea_main_item) +{ + EaCellTable *cell_data; + + g_return_if_fail (ea_main_item); + + cell_data = g_object_get_data (G_OBJECT(ea_main_item), + "ea-day-view-cell-table"); + if (cell_data) { + g_object_set_data (G_OBJECT(ea_main_item), + "ea-day-view-cell-table", NULL); + ea_cell_table_destroy (cell_data); + } +} + +/* Atk Component Interface */ + +static void +atk_component_interface_init (AtkComponentIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->get_extents = component_interface_get_extents; +} + +static void +component_interface_get_extents (AtkComponent *component, + gint *x, gint *y, gint *width, gint *height, + AtkCoordType coord_type) +{ + GObject *g_obj; + AtkObject *ea_canvas; + EDayViewMainItem *main_item; + EDayView *day_view; + + *x = *y = *width = *height = 0; + + g_return_if_fail (EA_IS_DAY_VIEW_MAIN_ITEM (component)); + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(component)); + if (!g_obj) + /* defunct object*/ + return; + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + ea_canvas = gtk_widget_get_accessible (day_view->main_canvas); + atk_component_get_extents (ATK_COMPONENT (ea_canvas), x, y, + width, height, coord_type); +} + +/* atk table interface */ + +static void +atk_table_interface_init (AtkTableIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->ref_at = table_interface_ref_at; + + iface->get_n_rows = table_interface_get_n_rows; + iface->get_n_columns = table_interface_get_n_columns; + iface->get_index_at = table_interface_get_index_at; + iface->get_column_at_index = table_interface_get_column_at_index; + iface->get_row_at_index = table_interface_get_row_at_index; + iface->get_column_extent_at = table_interface_get_column_extent_at; + iface->get_row_extent_at = table_interface_get_row_extent_at; + + iface->is_selected = table_interface_is_selected; + iface->get_selected_rows = table_interface_get_selected_rows; + iface->get_selected_columns = table_interface_get_selected_columns; + iface->is_row_selected = table_interface_is_row_selected; + iface->is_column_selected = table_interface_is_column_selected; + iface->add_row_selection = table_interface_add_row_selection; + iface->remove_row_selection = table_interface_remove_row_selection; + iface->add_column_selection = table_interface_add_column_selection; + iface->remove_column_selection = table_interface_remove_column_selection; + + iface->get_row_header = table_interface_get_row_header; + iface->get_column_header = table_interface_get_column_header; + iface->get_caption = table_interface_get_caption; + iface->get_summary = table_interface_get_summary; + iface->get_row_description = table_interface_get_row_description; + iface->get_column_description = table_interface_get_column_description; +} + +static AtkObject* +table_interface_ref_at (AtkTable *table, + gint row, + gint column) +{ + gint index; + + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); + index = ea_day_view_main_item_get_child_index_at (ea_main_item, + row, column); + return ea_day_view_main_item_ref_child (ATK_OBJECT (ea_main_item), index); +} + +static gint +table_interface_get_n_rows (AtkTable *table) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + return day_view->rows; +} + +static gint +table_interface_get_n_columns (AtkTable *table) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + return day_view->days_shown; +} + +static gint +table_interface_get_index_at (AtkTable *table, + gint row, + gint column) +{ + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); + return ea_day_view_main_item_get_child_index_at (ea_main_item, + row, column); +} + +static gint +table_interface_get_column_at_index (AtkTable *table, + gint index) +{ + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); + return ea_day_view_main_item_get_column_at_index (ea_main_item, index); +} + +static gint +table_interface_get_row_at_index (AtkTable *table, + gint index) +{ + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); + return ea_day_view_main_item_get_row_at_index (ea_main_item, index); +} + +static gint +table_interface_get_column_extent_at (AtkTable *table, + gint row, + gint column) +{ + gint index; + gint width = 0, height = 0; + AtkObject *child; + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); + + index = ea_day_view_main_item_get_child_index_at (ea_main_item, + row, column); + child = atk_object_ref_accessible_child (ATK_OBJECT (ea_main_item), + index); + if (child) + atk_component_get_size (ATK_COMPONENT (child), + &width, &height); + + return width; +} + +static gint +table_interface_get_row_extent_at (AtkTable *table, + gint row, + gint column) +{ + gint index; + gint width = 0, height = 0; + AtkObject *child; + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); + + index = ea_day_view_main_item_get_child_index_at (ea_main_item, + row, column); + child = atk_object_ref_accessible_child (ATK_OBJECT (ea_main_item), + index); + if (child) + atk_component_get_size (ATK_COMPONENT (child), + &width, &height); + + return height; +} + +static gboolean +table_interface_is_row_selected (AtkTable *table, + gint row) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + if (day_view->selection_start_day == -1) + /* no selection */ + return FALSE; + if (day_view->selection_start_day != day_view->selection_end_day) + /* all row is selected */ + return TRUE; + if (row >= day_view->selection_start_row && + row <= day_view->selection_end_row) + return TRUE; + return FALSE; +} + +static gboolean +table_interface_is_selected (AtkTable *table, + gint row, + gint column) +{ + return table_interface_is_row_selected (table, row) && + table_interface_is_column_selected (table, column); +} + +static gboolean +table_interface_is_column_selected (AtkTable *table, + gint column) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + if (column >= day_view->selection_start_day && + column <= day_view->selection_end_day) + return TRUE; + return FALSE; +} + +static gint +table_interface_get_selected_rows (AtkTable *table, + gint **rows_selected) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); + gint start_row = -1, n_rows = 0; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + if (day_view->selection_start_day == -1) + return 0; + + if (day_view->selection_start_day != day_view->selection_end_day) { + /* all the rows should be selected */ + n_rows = day_view->rows; + start_row = 0; + } + else if (day_view->selection_start_row != -1) { + start_row = day_view->selection_start_row; + n_rows = day_view->selection_end_row - start_row + 1; + } + if (n_rows > 0 && start_row != -1 && rows_selected) { + gint index; + + *rows_selected = (gint *) g_malloc (n_rows * sizeof (gint)); + for (index = 0; index < n_rows; ++index) + (*rows_selected)[index] = start_row + index; + } + return n_rows; +} + +static gint +table_interface_get_selected_columns (AtkTable *table, + gint **columns_selected) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); + gint start_column = -1, n_columns = 0; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + if (day_view->selection_start_day == -1) + return 0; + + start_column = day_view->selection_start_day; + n_columns = day_view->selection_end_day - start_column + 1; + if (n_columns > 0 && start_column != -1 && columns_selected) { + gint index; + + *columns_selected = (gint *) g_malloc (n_columns * sizeof (gint)); + for (index = 0; index < n_columns; ++index) + (*columns_selected)[index] = start_column + index; + } + return n_columns; +} + +static gboolean +table_interface_add_row_selection (AtkTable *table, + gint row) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + /* FIXME: we need multi-selection */ + + day_view->selection_start_day = 0; + day_view->selection_end_day = 0; + day_view->selection_start_row = row; + day_view->selection_end_row = row; + + e_day_view_ensure_rows_visible (day_view, + day_view->selection_start_row, + day_view->selection_end_row); + e_day_view_update_calendar_selection_time (day_view); + gtk_widget_queue_draw (day_view->main_canvas); + return TRUE; +} + +static gboolean +table_interface_remove_row_selection (AtkTable *table, + gint row) +{ + return FALSE; +} + +static gboolean +table_interface_add_column_selection (AtkTable *table, + gint column) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + /* FIXME: we need multi-selection */ + + day_view->selection_start_day = column; + day_view->selection_end_day = column; + day_view->selection_start_row = 0; + day_view->selection_end_row = day_view->rows; + + e_day_view_update_calendar_selection_time (day_view); + gtk_widget_queue_draw (day_view->main_canvas); + return TRUE; +} + +static gboolean +table_interface_remove_column_selection (AtkTable *table, + gint column) +{ + /* FIXME: NOT IMPLEMENTED */ + return FALSE; +} + +static AtkObject* +table_interface_get_row_header (AtkTable *table, + gint row) +{ + /* FIXME: NOT IMPLEMENTED */ + return NULL; +} + +static AtkObject* +table_interface_get_column_header (AtkTable *table, + gint in_col) +{ + /* FIXME: NOT IMPLEMENTED */ + return NULL; +} + +static AtkObject* +table_interface_get_caption (AtkTable *table) +{ + /* FIXME: NOT IMPLEMENTED */ + return NULL; +} + +static G_CONST_RETURN gchar * +table_interface_get_column_description (AtkTable *table, + gint in_col) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); + const gchar *description; + EaCellTable *cell_data; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + if (in_col < 0 || in_col >= day_view->days_shown) + return NULL; + cell_data = ea_day_view_main_item_get_cell_data (ea_main_item); + if (!cell_data) + return NULL; + + description = ea_cell_table_get_column_label (cell_data, in_col); + if (!description) { + gchar buffer[128]; + e_day_view_top_item_get_day_label (day_view, in_col, buffer, 128); + ea_cell_table_set_column_label (cell_data, in_col, buffer); + description = ea_cell_table_get_column_label (cell_data, in_col); + } + return description; +} + +static G_CONST_RETURN gchar * +table_interface_get_row_description (AtkTable *table, + gint row) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (table); + const gchar *description; + EaCellTable *cell_data; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + if (row < 0 || row >= 12 * 24) + return NULL; + cell_data = ea_day_view_main_item_get_cell_data (ea_main_item); + if (!cell_data) + return NULL; + + description = ea_cell_table_get_row_label (cell_data, row); + if (!description) { + gchar buffer[128]; + ea_day_view_main_item_get_row_label (ea_main_item, row, buffer, sizeof (buffer)); + ea_cell_table_set_row_label (cell_data, row, buffer); + description = ea_cell_table_get_row_label (cell_data, + row); + } + return description; +} + +static AtkObject* +table_interface_get_summary (AtkTable *table) +{ + /* FIXME: NOT IMPLEMENTED */ + return NULL; +} + +/* atkselection interface */ + +static void +atk_selection_interface_init (AtkSelectionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->add_selection = selection_interface_add_selection; + iface->clear_selection = selection_interface_clear_selection; + iface->ref_selection = selection_interface_ref_selection; + iface->get_selection_count = selection_interface_get_selection_count; + iface->is_child_selected = selection_interface_is_child_selected; +} + +static gboolean +selection_interface_add_selection (AtkSelection *selection, gint i) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (selection); + gint column, row; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + row = ea_day_view_main_item_get_row_at_index (ea_main_item, i); + column = ea_day_view_main_item_get_column_at_index (ea_main_item, i); + + if (row == -1 || column == -1) + return FALSE; + + /*FIXME: multi-selection is needed */ + day_view->selection_start_day = column; + day_view->selection_end_day = column; + day_view->selection_start_row = row; + day_view->selection_end_row = row; + + e_day_view_ensure_rows_visible (day_view, + day_view->selection_start_row, + day_view->selection_end_row); + e_day_view_update_calendar_selection_time (day_view); + gtk_widget_queue_draw (day_view->main_canvas); + return TRUE; +} + +static gboolean +selection_interface_clear_selection (AtkSelection *selection) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (selection); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + day_view->selection_start_row = -1; + day_view->selection_start_day = -1; + day_view->selection_end_row = -1; + day_view->selection_end_day = -1; + + e_day_view_update_calendar_selection_time (day_view); + gtk_widget_queue_draw (day_view->main_canvas); + + return TRUE; +} + +static AtkObject* +selection_interface_ref_selection (AtkSelection *selection, gint i) +{ + gint count; + GObject *g_obj; + EDayView *day_view; + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (selection); + gint start_index; + + count = selection_interface_get_selection_count (selection); + if (i < 0 || i >=count) + return NULL; + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (ea_main_item)); + day_view = E_DAY_VIEW_MAIN_ITEM (g_obj)->day_view; + start_index = ea_day_view_main_item_get_child_index_at (ea_main_item, + day_view->selection_start_row, + day_view->selection_start_day); + + return ea_day_view_main_item_ref_child (ATK_OBJECT (selection), start_index + i); +} + +static gint +selection_interface_get_selection_count (AtkSelection *selection) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (selection); + gint start_index, end_index; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return 0; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + if (day_view->selection_start_day == -1 || + day_view->selection_start_row == -1) + return 0; + start_index = ea_day_view_main_item_get_child_index_at (ea_main_item, + day_view->selection_start_row, + day_view->selection_start_day); + end_index = ea_day_view_main_item_get_child_index_at (ea_main_item, + day_view->selection_end_row, + day_view->selection_end_day); + + return end_index - start_index + 1; +} + +static gboolean +selection_interface_is_child_selected (AtkSelection *selection, gint i) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EDayViewMainItem *main_item; + EDayView *day_view; + EaDayViewMainItem* ea_main_item = EA_DAY_VIEW_MAIN_ITEM (selection); + gint column, row; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + main_item = E_DAY_VIEW_MAIN_ITEM (g_obj); + day_view = main_item->day_view; + + row = ea_day_view_main_item_get_row_at_index (ea_main_item, i); + column = ea_day_view_main_item_get_column_at_index (ea_main_item, i); + + if (column < day_view->selection_start_day || + column > day_view->selection_end_day) + return FALSE; + + if ((column == day_view->selection_start_day || + column == day_view->selection_end_day) && + (row < day_view->selection_start_row || + row > day_view->selection_end_row)) + return FALSE; + + /* if comes here, the cell is selected */ + return TRUE; +} diff --git a/calendar/gui/ea-day-view-main-item.h b/calendar/gui/ea-day-view-main-item.h new file mode 100644 index 0000000000..c782e6acc8 --- /dev/null +++ b/calendar/gui/ea-day-view-main-item.h @@ -0,0 +1,58 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_DAY_VIEW_MAIN_ITEM_H__ +#define __EA_DAY_VIEW_MAIN_ITEM_H__ + +#include +#include "e-day-view-main-item.h" + +G_BEGIN_DECLS + +#define EA_TYPE_DAY_VIEW_MAIN_ITEM (ea_day_view_main_item_get_type ()) +#define EA_DAY_VIEW_MAIN_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_DAY_VIEW_MAIN_ITEM, EaDayViewMainItem)) +#define EA_DAY_VIEW_MAIN_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_DAY_VIEW_MAIN_ITEM, EaDayViewMainItemClass)) +#define EA_IS_DAY_VIEW_MAIN_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_DAY_VIEW_MAIN_ITEM)) +#define EA_IS_DAY_VIEW_MAIN_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_DAY_VIEW_MAIN_ITEM)) +#define EA_DAY_VIEW_MAIN_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_DAY_VIEW_MAIN_ITEM, EaDayViewMainItemClass)) + +typedef struct _EaDayViewMainItem EaDayViewMainItem; +typedef struct _EaDayViewMainItemClass EaDayViewMainItemClass; + +struct _EaDayViewMainItem +{ + AtkGObjectAccessible parent; +}; + +GType ea_day_view_main_item_get_type (void); + +struct _EaDayViewMainItemClass +{ + AtkGObjectAccessibleClass parent_class; +}; + +AtkObject* ea_day_view_main_item_new (GObject *obj); + +G_END_DECLS + +#endif /* __EA_DAY_VIEW_MAIN_ITEM_H__ */ diff --git a/calendar/gui/ea-day-view.c b/calendar/gui/ea-day-view.c new file mode 100644 index 0000000000..9eb3e343f3 --- /dev/null +++ b/calendar/gui/ea-day-view.c @@ -0,0 +1,277 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "ea-day-view.h" +#include "ea-cal-view-event.h" + +#include "ea-calendar-helpers.h" +#include "ea-gnome-calendar.h" +#include "calendar-commands.h" +#include +#include + +static void ea_day_view_class_init (EaDayViewClass *klass); + +static G_CONST_RETURN gchar * ea_day_view_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar * ea_day_view_get_description (AtkObject *accessible); +static gint ea_day_view_get_n_children (AtkObject *obj); +static AtkObject* ea_day_view_ref_child (AtkObject *obj, + gint i); +static gpointer parent_class = NULL; + +GType +ea_day_view_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaDayViewClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) ea_day_view_class_init, /* class init */ + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (EaDayView), /* instance size */ + 0, /* nb preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (EaCalView, in this case) + * + * Note: we must still use run-time deriving here, because + * our parent class EaCalView is run-time deriving. + */ + + factory = atk_registry_get_factory (atk_get_default_registry (), + e_calendar_view_get_type()); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + type = g_type_register_static (derived_atk_type, + "EaDayView", &tinfo, 0); + } + + return type; +} + +static void +ea_day_view_class_init (EaDayViewClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + class->get_name = ea_day_view_get_name; + class->get_description = ea_day_view_get_description; + + class->get_n_children = ea_day_view_get_n_children; + class->ref_child = ea_day_view_ref_child; +} + +AtkObject* +ea_day_view_new (GtkWidget *widget) +{ + GObject *object; + AtkObject *accessible; + + g_return_val_if_fail (E_IS_DAY_VIEW (widget), NULL); + + object = g_object_new (EA_TYPE_DAY_VIEW, NULL); + + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, widget); + +#ifdef ACC_DEBUG + printf ("EvoAcc: ea_day_view created %p\n", (gpointer)accessible); +#endif + + return accessible; +} + +static G_CONST_RETURN gchar * +ea_day_view_get_name (AtkObject *accessible) +{ + EDayView *day_view; + GnomeCalendar *gcal; + const gchar *label_text; + GnomeCalendarViewType view_type; + gint n_events; + gchar *event_str, *name_str; + + g_return_val_if_fail (EA_IS_DAY_VIEW (accessible), NULL); + + if (!GTK_ACCESSIBLE (accessible)->widget) + return NULL; + + day_view = E_DAY_VIEW (GTK_ACCESSIBLE (accessible)->widget); + gcal = e_calendar_view_get_calendar (E_CALENDAR_VIEW (day_view)); + if (!GTK_WIDGET_VISIBLE (GTK_WIDGET (gcal))) + return NULL; + + label_text = ea_gnome_calendar_get_label_description (gcal); + + n_events = atk_object_get_n_accessible_children (accessible); + /* the child main item is always there */ + --n_events; + if (n_events >= 1) + /* To translators: Here, "It" is either like "Work Week View: July + 10th - July 14th, 2006." or "Day View: Thursday July 13th, 2006." */ + event_str = g_strdup_printf (ngettext ("It has %d event.", "It has %d events.", n_events), n_events); + else + /* To translators: Here, "It" is either like "Work Week View: July + 10th - July 14th, 2006." or "Day View: Thursday July 13th, 2006." */ + event_str = g_strdup (_("It has no events.")); + + view_type = gnome_calendar_get_view (gcal); + if (view_type == GNOME_CAL_WORK_WEEK_VIEW) + /* To translators: First %s is the week, for example "July 10th - + July 14th, 2006". Second %s is the number of events in this work + week, for example "It has %d event/events." or "It has no events." */ + name_str = g_strdup_printf (_("Work Week View: %s. %s"), + label_text, event_str); + else + /* To translators: First %s is the day, for example "Thursday July + 13th, 2006". Second %s is the number of events on this day, for + example "It has %d event/events." or "It has no events." */ + name_str = g_strdup_printf (_("Day View: %s. %s"), + label_text, event_str); + + ATK_OBJECT_CLASS (parent_class)->set_name (accessible, name_str); + g_free (name_str); + g_free (event_str); + + return accessible->name; +} + +static G_CONST_RETURN gchar * +ea_day_view_get_description (AtkObject *accessible) +{ + EDayView *day_view; + + g_return_val_if_fail (EA_IS_DAY_VIEW (accessible), NULL); + + if (!GTK_ACCESSIBLE (accessible)->widget) + return NULL; + day_view = E_DAY_VIEW (GTK_ACCESSIBLE (accessible)->widget); + + if (accessible->description) + return accessible->description; + else { + GnomeCalendar *gcal; + GnomeCalendarViewType view_type; + + gcal = e_calendar_view_get_calendar (E_CALENDAR_VIEW (day_view)); + view_type = gnome_calendar_get_view (gcal); + + if (view_type == GNOME_CAL_WORK_WEEK_VIEW) + return _("calendar view for a work week"); + else + return _("calendar view for one or more days"); + } +} + +static gint +ea_day_view_get_n_children (AtkObject *accessible) +{ + EDayView *day_view; + gint day; + gint child_num = 0; + + g_return_val_if_fail (EA_IS_DAY_VIEW (accessible), -1); + + if (!GTK_ACCESSIBLE (accessible)->widget) + return -1; + + day_view = E_DAY_VIEW (GTK_ACCESSIBLE (accessible)->widget); + + child_num += day_view->long_events->len; + + for (day = 0; day < day_view->days_shown; day++) { + child_num += day_view->events[day]->len; + } + + /* "+1" for the main item */ + return child_num + 1; +} + +static AtkObject * +ea_day_view_ref_child (AtkObject *accessible, gint index) +{ + EDayView *day_view; + gint child_num; + gint day; + AtkObject *atk_object = NULL; + EDayViewEvent *event = NULL; + + g_return_val_if_fail (EA_IS_DAY_VIEW (accessible), NULL); + + child_num = atk_object_get_n_accessible_children (accessible); + if (child_num <= 0 || index < 0 || index >= child_num) + return NULL; + + if (!GTK_ACCESSIBLE (accessible)->widget) + return NULL; + day_view = E_DAY_VIEW (GTK_ACCESSIBLE (accessible)->widget); + + if (index == 0) { + /* index == 0 is the main item */ + atk_object = atk_gobject_accessible_for_object (G_OBJECT (day_view->main_canvas_item)); + g_object_ref (atk_object); + } + else { + --index; + /* a long event */ + if (index < day_view->long_events->len) { + event = &g_array_index (day_view->long_events, + EDayViewEvent, index); + } + else { + index -= day_view->long_events->len; + day = 0; + while (index >= day_view->events[day]->len) { + index -= day_view->events[day]->len; + ++day; + } + + event = &g_array_index (day_view->events[day], + EDayViewEvent, index); + } + if (event && event->canvas_item) { + /* Not use atk_gobject_accessible_for_object here, + * we need to do special thing here + */ + atk_object = ea_calendar_helpers_get_accessible_for (event->canvas_item); + g_object_ref (atk_object); + } + } + return atk_object; +} diff --git a/calendar/gui/ea-day-view.h b/calendar/gui/ea-day-view.h new file mode 100644 index 0000000000..33399f6600 --- /dev/null +++ b/calendar/gui/ea-day-view.h @@ -0,0 +1,57 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_DAY_VIEW_H__ +#define __EA_DAY_VIEW_H__ + +#include "ea-cal-view.h" +#include "e-day-view.h" + +G_BEGIN_DECLS + +#define EA_TYPE_DAY_VIEW (ea_day_view_get_type ()) +#define EA_DAY_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_DAY_VIEW, EaDayView)) +#define EA_DAY_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_DAY_VIEW, EaDayViewClass)) +#define EA_IS_DAY_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_DAY_VIEW)) +#define EA_IS_DAY_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_DAY_VIEW)) +#define EA_DAY_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_DAY_VIEW, EaDayViewClass)) + +typedef struct _EaDayView EaDayView; +typedef struct _EaDayViewClass EaDayViewClass; + +struct _EaDayView +{ + EaCalView parent; +}; + +GType ea_day_view_get_type (void); + +struct _EaDayViewClass +{ + EaCalViewClass parent_class; +}; + +AtkObject* ea_day_view_new (GtkWidget *widget); + +G_END_DECLS + +#endif /* __EA_DAY_VIEW_H__ */ diff --git a/calendar/gui/ea-gnome-calendar.c b/calendar/gui/ea-gnome-calendar.c new file mode 100644 index 0000000000..e5d9654c1a --- /dev/null +++ b/calendar/gui/ea-gnome-calendar.c @@ -0,0 +1,351 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "ea-gnome-calendar.h" +#include "calendar-commands.h" +#include +#include +#include +#include +#include + +static void ea_gnome_calendar_class_init (EaGnomeCalendarClass *klass); + +static G_CONST_RETURN gchar * ea_gnome_calendar_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar * ea_gnome_calendar_get_description (AtkObject *accessible); +static gint ea_gnome_calendar_get_n_children (AtkObject* obj); +static AtkObject * ea_gnome_calendar_ref_child (AtkObject *obj, gint i); + +static void ea_gcal_switch_view_cb (GtkNotebook *widget, GtkNotebookPage *page, + guint index, gpointer data); +static void ea_gcal_dates_change_cb (GnomeCalendar *gcal, gpointer data); + +static gpointer parent_class = NULL; + +GType +ea_gnome_calendar_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaGnomeCalendarClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) ea_gnome_calendar_class_init, /* class init */ + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (EaGnomeCalendar), /* instance size */ + 0, /* nb preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (GailWidget, in this case) + */ + + factory = atk_registry_get_factory (atk_get_default_registry (), + GTK_TYPE_WIDGET); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + type = g_type_register_static (derived_atk_type, + "EaGnomeCalendar", &tinfo, 0); + + } + + return type; +} + +static void +ea_gnome_calendar_class_init (EaGnomeCalendarClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + class->get_name = ea_gnome_calendar_get_name; + class->get_description = ea_gnome_calendar_get_description; + + class->get_n_children = ea_gnome_calendar_get_n_children; + class->ref_child = ea_gnome_calendar_ref_child; +} + +AtkObject* +ea_gnome_calendar_new (GtkWidget *widget) +{ + GObject *object; + AtkObject *accessible; + GnomeCalendar *gcal; + GtkWidget *notebook; + + g_return_val_if_fail (GNOME_IS_CALENDAR (widget), NULL); + + object = g_object_new (EA_TYPE_GNOME_CALENDAR, NULL); + + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, widget); + + accessible->role = ATK_ROLE_FILLER; + + gcal = GNOME_CALENDAR (widget); + + /* listen on view type change + */ + g_signal_connect (widget, "dates_shown_changed", + G_CALLBACK (ea_gcal_dates_change_cb), + accessible); + notebook = gnome_calendar_get_view_notebook_widget (gcal); + if (notebook) { + g_signal_connect (notebook, "switch_page", + G_CALLBACK (ea_gcal_switch_view_cb), + accessible); + } + +#ifdef ACC_DEBUG + printf ("EvoAcc: ea-gnome-calendar created: %p\n", (gpointer)accessible); +#endif + + return accessible; +} + +const gchar * +ea_gnome_calendar_get_label_description (GnomeCalendar *gcal) +{ + icaltimezone *zone; + struct icaltimetype start_tt, end_tt; + time_t start_time, end_time; + struct tm start_tm, end_tm; + static gchar buffer[512]; + gchar end_buffer[256]; + GnomeCalendarViewType view; + + gnome_calendar_get_visible_time_range (gcal, &start_time, &end_time); + zone = gnome_calendar_get_timezone (gcal); + + start_tt = icaltime_from_timet_with_zone (start_time, FALSE, zone); + start_tm.tm_year = start_tt.year - 1900; + start_tm.tm_mon = start_tt.month - 1; + start_tm.tm_mday = start_tt.day; + start_tm.tm_hour = start_tt.hour; + start_tm.tm_min = start_tt.minute; + start_tm.tm_sec = start_tt.second; + start_tm.tm_isdst = -1; + start_tm.tm_wday = time_day_of_week (start_tt.day, start_tt.month - 1, + start_tt.year); + + /* Take one off end_time so we don't get an extra day. */ + end_tt = icaltime_from_timet_with_zone (end_time - 1, FALSE, zone); + end_tm.tm_year = end_tt.year - 1900; + end_tm.tm_mon = end_tt.month - 1; + end_tm.tm_mday = end_tt.day; + end_tm.tm_hour = end_tt.hour; + end_tm.tm_min = end_tt.minute; + end_tm.tm_sec = end_tt.second; + end_tm.tm_isdst = -1; + end_tm.tm_wday = time_day_of_week (end_tt.day, end_tt.month - 1, + end_tt.year); + + view = gnome_calendar_get_view (gcal); + + switch (view) { + case GNOME_CAL_DAY_VIEW: + case GNOME_CAL_WORK_WEEK_VIEW: + case GNOME_CAL_WEEK_VIEW: + if (start_tm.tm_year == end_tm.tm_year + && start_tm.tm_mon == end_tm.tm_mon + && start_tm.tm_mday == end_tm.tm_mday) { + e_utf8_strftime (buffer, sizeof (buffer), + _("%A %d %b %Y"), &start_tm); + } else if (start_tm.tm_year == end_tm.tm_year) { + e_utf8_strftime (buffer, sizeof (buffer), + _("%a %d %b"), &start_tm); + e_utf8_strftime (end_buffer, sizeof (end_buffer), + _("%a %d %b %Y"), &end_tm); + strcat (buffer, " - "); + strcat (buffer, end_buffer); + } else { + e_utf8_strftime (buffer, sizeof (buffer), + _("%a %d %b %Y"), &start_tm); + e_utf8_strftime (end_buffer, sizeof (end_buffer), + _("%a %d %b %Y"), &end_tm); + strcat (buffer, " - "); + strcat (buffer, end_buffer); + } + break; + case GNOME_CAL_MONTH_VIEW: + case GNOME_CAL_LIST_VIEW: + if (start_tm.tm_year == end_tm.tm_year) { + if (start_tm.tm_mon == end_tm.tm_mon) { + if (start_tm.tm_mday == end_tm.tm_mday) { + buffer [0] = '\0'; + } else { + e_utf8_strftime (buffer, sizeof (buffer), + "%d", &start_tm); + strcat (buffer, " - "); + } + e_utf8_strftime (end_buffer, sizeof (end_buffer), + _("%d %b %Y"), &end_tm); + strcat (buffer, end_buffer); + } else { + e_utf8_strftime (buffer, sizeof (buffer), + _("%d %b"), &start_tm); + e_utf8_strftime (end_buffer, sizeof (end_buffer), + _("%d %b %Y"), &end_tm); + strcat (buffer, " - "); + strcat (buffer, end_buffer); + } + } else { + e_utf8_strftime (buffer, sizeof (buffer), + _("%d %b %Y"), &start_tm); + e_utf8_strftime (end_buffer, sizeof (end_buffer), + _("%d %b %Y"), &end_tm); + strcat (buffer, " - "); + strcat (buffer, end_buffer); + } + break; + default: + g_return_val_if_reached (NULL); + } + return buffer; +} + +static G_CONST_RETURN gchar * +ea_gnome_calendar_get_name (AtkObject *accessible) +{ + if (accessible->name) + return accessible->name; + return _("Gnome Calendar"); +} + +static G_CONST_RETURN gchar * +ea_gnome_calendar_get_description (AtkObject *accessible) +{ + if (accessible->description) + return accessible->description; + return _("Gnome Calendar"); +} + +static gint +ea_gnome_calendar_get_n_children (AtkObject* obj) +{ + g_return_val_if_fail (EA_IS_GNOME_CALENDAR (obj), 0); + + if (!GTK_ACCESSIBLE (obj)->widget) + return -1; + return 4; +} + +static AtkObject * +ea_gnome_calendar_ref_child (AtkObject *obj, gint i) +{ + AtkObject * child = NULL; + GnomeCalendar * calendarWidget; + GtkWidget *childWidget; + + g_return_val_if_fail (EA_IS_GNOME_CALENDAR (obj), NULL); + /* valid child index range is [0-3] */ + if (i < 0 || i >3 ) + return NULL; + + if (!GTK_ACCESSIBLE (obj)->widget) + return NULL; + calendarWidget = GNOME_CALENDAR (GTK_ACCESSIBLE (obj)->widget); + + switch (i) { + case 0: + /* for the search bar */ + childWidget = gnome_calendar_get_search_bar_widget (calendarWidget); + child = gtk_widget_get_accessible (childWidget); + atk_object_set_parent (child, obj); + atk_object_set_name (child, _("search bar")); + atk_object_set_description (child, _("evolution calendar search bar")); + break; + case 1: + /* for the day/week view */ + childWidget = gnome_calendar_get_current_view_widget (calendarWidget); + child = gtk_widget_get_accessible (childWidget); + atk_object_set_parent (child, obj); + break; + case 2: + /* for calendar */ + childWidget = gnome_calendar_get_e_calendar_widget (calendarWidget); + child = gtk_widget_get_accessible (childWidget); + break; + case 3: + /* for todo list */ + childWidget = GTK_WIDGET (gnome_calendar_get_task_pad (calendarWidget)); + child = gtk_widget_get_accessible (childWidget); + break; + default: + break; + } + if (child) + g_object_ref(child); + return child; +} + +static void +ea_gcal_switch_view_cb (GtkNotebook *widget, GtkNotebookPage *page, + guint index, gpointer data) +{ + GtkWidget *new_widget; + + new_widget = gtk_notebook_get_nth_page (widget, index); + + /* views are always the second child in gnome calendar + */ + if (new_widget) + g_signal_emit_by_name (G_OBJECT(data), "children_changed::add", + 1, gtk_widget_get_accessible (new_widget), NULL); + +#ifdef ACC_DEBUG + printf ("AccDebug: view switch to widget %p (index=%d) \n", + (gpointer)new_widget, index); +#endif +} + +static void +ea_gcal_dates_change_cb (GnomeCalendar *gcal, gpointer data) +{ + const gchar *new_name; + + g_return_if_fail (GNOME_IS_CALENDAR (gcal)); + g_return_if_fail (data); + g_return_if_fail (EA_IS_GNOME_CALENDAR (data)); + + new_name = ea_gnome_calendar_get_label_description (gcal); + atk_object_set_name (ATK_OBJECT(data), new_name); + g_signal_emit_by_name (data, "visible_data_changed"); + +#ifdef ACC_DEBUG + printf ("AccDebug: calendar dates changed, label=%s\n", new_name); +#endif +} diff --git a/calendar/gui/ea-gnome-calendar.h b/calendar/gui/ea-gnome-calendar.h new file mode 100644 index 0000000000..b0d2cf71d2 --- /dev/null +++ b/calendar/gui/ea-gnome-calendar.h @@ -0,0 +1,60 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_GNOME_CALENDAR_H__ +#define __EA_GNOME_CALENDAR_H__ + +#include +#include "gnome-cal.h" + +G_BEGIN_DECLS + +#define EA_TYPE_GNOME_CALENDAR (ea_gnome_calendar_get_type ()) +#define EA_GNOME_CALENDAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_GNOME_CALENDAR, EaGnomeCalendar)) +#define EA_GNOME_CALENDAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_GNOME_CALENDAR, EaGnomeCalendarClass)) +#define EA_IS_GNOME_CALENDAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_GNOME_CALENDAR)) +#define EA_IS_GNOME_CALENDAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_GNOME_CALENDAR)) +#define EA_GNOME_CALENDAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_GNOME_CALENDAR, EaGnomeCalendarClass)) + +typedef struct _EaGnomeCalendar EaGnomeCalendar; +typedef struct _EaGnomeCalendarClass EaGnomeCalendarClass; + +struct _EaGnomeCalendar +{ + GtkAccessible parent; +}; + +GType ea_gnome_calendar_get_type (void); + +struct _EaGnomeCalendarClass +{ + GtkAccessibleClass parent_class; +}; + +AtkObject* ea_gnome_calendar_new (GtkWidget *widget); + +const gchar * ea_gnome_calendar_get_label_description (GnomeCalendar *gcal); + +G_END_DECLS + + +#endif /* __EA_GNOME_CALENDAR_H__ */ diff --git a/calendar/gui/ea-jump-button.c b/calendar/gui/ea-jump-button.c new file mode 100644 index 0000000000..eb24bea42c --- /dev/null +++ b/calendar/gui/ea-jump-button.c @@ -0,0 +1,224 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Yang Wu + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "ea-jump-button.h" +#include "ea-calendar-helpers.h" +#include "ea-week-view.h" +#include "e-week-view.h" +#include +#include + +static void ea_jump_button_class_init (EaJumpButtonClass *klass); + +static G_CONST_RETURN gchar * ea_jump_button_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar * ea_jump_button_get_description (AtkObject *accessible); + +/* action interface */ +static void atk_action_interface_init (AtkActionIface *iface); +static gboolean jump_button_do_action (AtkAction *action, + gint i); +static gint jump_button_get_n_actions (AtkAction *action); +static G_CONST_RETURN gchar * jump_button_get_keybinding (AtkAction *action, + gint i); + +static gpointer parent_class = NULL; + +GType +ea_jump_button_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaJumpButtonClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) ea_jump_button_class_init, /* class init */ + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (EaJumpButton), /* instance size */ + 0, /* nb preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + static const GInterfaceInfo atk_action_info = + { + (GInterfaceInitFunc) atk_action_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (atk object for GNOME_TYPE_CANVAS_ITEM, in this case) + */ + + factory = atk_registry_get_factory (atk_get_default_registry (), + GNOME_TYPE_CANVAS_ITEM); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + /* we inherit the component and other interfaces from GNOME_TYPE_CANVAS_ITEM */ + type = g_type_register_static (derived_atk_type, + "EaJumpButton", &tinfo, 0); + + g_type_add_interface_static (type, ATK_TYPE_ACTION, + &atk_action_info); + } + + return type; +} + +static void +ea_jump_button_class_init (EaJumpButtonClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + class->get_name = ea_jump_button_get_name; + class->get_description = ea_jump_button_get_description; +} + +AtkObject* +ea_jump_button_new (GObject *obj) +{ + AtkObject *atk_obj = NULL; + GObject *target_obj; + + g_return_val_if_fail (GNOME_IS_CANVAS_ITEM (obj), NULL); + + target_obj = obj; + atk_obj = g_object_get_data (target_obj, "accessible-object"); + + if (!atk_obj) { + static AtkRole event_role = ATK_ROLE_INVALID; + atk_obj = ATK_OBJECT (g_object_new (EA_TYPE_JUMP_BUTTON, + NULL)); + atk_object_initialize (atk_obj, target_obj); + if (event_role == ATK_ROLE_INVALID) + event_role = atk_role_register ("Jump Button"); + atk_obj->role = event_role; + } + + /* the registered factory for GNOME_TYPE_CANVAS_ITEM is cannot create a EaJumpbutton, + * we should save the EaJumpbutton object in it. + */ + g_object_set_data (obj, "accessible-object", atk_obj); + + return atk_obj; +} + +static G_CONST_RETURN gchar * +ea_jump_button_get_name (AtkObject *accessible) +{ + g_return_val_if_fail (EA_IS_JUMP_BUTTON (accessible), NULL); + + if (accessible->name) + return accessible->name; + return _("Jump button"); +} + +static G_CONST_RETURN gchar * +ea_jump_button_get_description (AtkObject *accessible) +{ + if (accessible->description) + return accessible->description; + + return _("Click here, you can find more events."); +} + +static void +atk_action_interface_init (AtkActionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->do_action = jump_button_do_action; + iface->get_n_actions = jump_button_get_n_actions; + iface->get_keybinding = jump_button_get_keybinding; +} + +static gboolean +jump_button_do_action (AtkAction *action, + gint i) +{ + gboolean return_value = TRUE; + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + GnomeCanvasItem *item; + ECalendarView *cal_view; + EWeekView *week_view; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (action); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + item = GNOME_CANVAS_ITEM (g_obj); + cal_view = ea_calendar_helpers_get_cal_view_from (GNOME_CANVAS_ITEM (item)); + week_view = E_WEEK_VIEW (cal_view); + + switch (i) + { + case 0: + e_week_view_jump_to_button_item (week_view, GNOME_CANVAS_ITEM (item)); + break; + default: + return_value = FALSE; + break; + } + return return_value; +} + +static gint +jump_button_get_n_actions (AtkAction *action) +{ + return 1; +} + +static G_CONST_RETURN gchar * +jump_button_get_keybinding (AtkAction *action, + gint i) +{ + const gchar *return_value = NULL; + + switch (i) + { + case 0: + { + return_value = "space or enter"; + break; + } + default: + break; + } + return return_value; +} diff --git a/calendar/gui/ea-jump-button.h b/calendar/gui/ea-jump-button.h new file mode 100644 index 0000000000..cd3b6e26bb --- /dev/null +++ b/calendar/gui/ea-jump-button.h @@ -0,0 +1,58 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Yang Wu + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_JUMP_BUTTON_H__ +#define __EA_JUMP_BUTTON_H__ + +#include + +G_BEGIN_DECLS + +#define EA_TYPE_JUMP_BUTTON (ea_jump_button_get_type ()) +#define EA_JUMP_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_JUMP_BUTTON, EaJumpButton)) +#define EA_JUMP_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_JUMP_BUTTON, EaJumpButtonClass)) +#define EA_IS_JUMP_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_JUMP_BUTTON)) +#define EA_IS_JUMP_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_JUMP_BUTTON)) +#define EA_JUMP_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_JUMP_BUTTON, EaJumpButtonClass)) + +typedef struct _EaJumpButton EaJumpButton; +typedef struct _EaJumpButtonClass EaJumpButtonClass; + +struct _EaJumpButton +{ + AtkGObjectAccessible parent; +}; + +GType ea_jump_button_get_type (void); + +struct _EaJumpButtonClass +{ + AtkGObjectAccessibleClass parent_class; +}; + +AtkObject *ea_jump_button_new (GObject *obj); + +G_END_DECLS + + +#endif /* __EA_JUMP_BUTTON_H__ */ diff --git a/calendar/gui/ea-week-view-cell.c b/calendar/gui/ea-week-view-cell.c new file mode 100644 index 0000000000..e724592ec8 --- /dev/null +++ b/calendar/gui/ea-week-view-cell.c @@ -0,0 +1,478 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * Yang Wu + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "ea-week-view-cell.h" +#include "ea-week-view-main-item.h" +#include "a11y/ea-factory.h" + +/* EWeekViewCell */ + +static void e_week_view_cell_class_init (EWeekViewCellClass *class); + +EA_FACTORY_GOBJECT (EA_TYPE_WEEK_VIEW_CELL, ea_week_view_cell, ea_week_view_cell_new) + +GType +e_week_view_cell_get_type (void) +{ + static GType type = 0; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EWeekViewCellClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) e_week_view_cell_class_init, /* class init */ + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (EWeekViewCell), /* instance size */ + 0, /* nb preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + type = g_type_register_static (G_TYPE_OBJECT, + "EWeekViewCell", &tinfo, 0); + } + + return type; +} + +static void +e_week_view_cell_class_init (EWeekViewCellClass *class) +{ + EA_SET_FACTORY (e_week_view_cell_get_type (), ea_week_view_cell); +} + +EWeekViewCell * +e_week_view_cell_new (EWeekView *week_view, gint row, gint column) +{ + GObject *object; + EWeekViewCell *cell; + + g_return_val_if_fail (E_IS_WEEK_VIEW (week_view), NULL); + + object = g_object_new (E_TYPE_WEEK_VIEW_CELL, NULL); + cell = E_WEEK_VIEW_CELL (object); + cell->week_view = week_view; + cell->row = row; + cell->column = column; + +#ifdef ACC_DEBUG + printf ("EvoAcc: e_week_view_cell created %p\n", (gpointer)cell); +#endif + + return cell; +} + +/* EaWeekViewCell */ + +static void ea_week_view_cell_class_init (EaWeekViewCellClass *klass); + +static G_CONST_RETURN gchar * ea_week_view_cell_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar * ea_week_view_cell_get_description (AtkObject *accessible); +static AtkStateSet* ea_week_view_cell_ref_state_set (AtkObject *obj); +static AtkObject * ea_week_view_cell_get_parent (AtkObject *accessible); +static gint ea_week_view_cell_get_index_in_parent (AtkObject *accessible); + +/* component interface */ +static void atk_component_interface_init (AtkComponentIface *iface); +static void component_interface_get_extents (AtkComponent *component, + gint *x, gint *y, + gint *width, gint *height, + AtkCoordType coord_type); +static gboolean component_interface_grab_focus (AtkComponent *component); + +static gpointer parent_class = NULL; + +#ifdef ACC_DEBUG +static gint n_ea_week_view_cell_created = 0, n_ea_week_view_cell_destroyed = 0; +static void ea_week_view_cell_finalize (GObject *object); +#endif + +GType +ea_week_view_cell_get_type (void) +{ + static GType type = 0; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaWeekViewCellClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) ea_week_view_cell_class_init, /* class init */ + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (EaWeekViewCell), /* instance size */ + 0, /* nb preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) atk_component_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + type = g_type_register_static (ATK_TYPE_GOBJECT_ACCESSIBLE, + "EaWeekViewCell", &tinfo, 0); + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, + &atk_component_info); + + } + + return type; +} + +static void +ea_week_view_cell_class_init (EaWeekViewCellClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + +#ifdef ACC_DEBUG + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = ea_week_view_cell_finalize; +#endif + + parent_class = g_type_class_peek_parent (klass); + + class->get_name = ea_week_view_cell_get_name; + class->get_description = ea_week_view_cell_get_description; + class->ref_state_set = ea_week_view_cell_ref_state_set; + + class->get_parent = ea_week_view_cell_get_parent; + class->get_index_in_parent = ea_week_view_cell_get_index_in_parent; + +} + +AtkObject* +ea_week_view_cell_new (GObject *obj) +{ + gpointer object; + AtkObject *atk_object; + + g_return_val_if_fail (E_IS_WEEK_VIEW_CELL (obj), NULL); + object = g_object_new (EA_TYPE_WEEK_VIEW_CELL, NULL); + atk_object = ATK_OBJECT (object); + atk_object_initialize (atk_object, obj); + atk_object->role = ATK_ROLE_UNKNOWN; + +#ifdef ACC_DEBUG + ++n_ea_week_view_cell_created; + printf ("ACC_DEBUG: n_ea_week_view_cell_created = %d\n", + n_ea_week_view_cell_created); +#endif + return atk_object; +} + +#ifdef ACC_DEBUG +static void ea_week_view_cell_finalize (GObject *object) +{ + G_OBJECT_CLASS (parent_class)->finalize (object); + + ++n_ea_week_view_cell_destroyed; + printf ("ACC_DEBUG: n_ea_week_view_cell_destroyed = %d\n", + n_ea_week_view_cell_destroyed); +} +#endif + +static G_CONST_RETURN gchar * +ea_week_view_cell_get_name (AtkObject *accessible) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewCell *cell; + + g_return_val_if_fail (EA_IS_WEEK_VIEW_CELL (accessible), NULL); + + if (!accessible->name) { + AtkObject *ea_main_item; + GnomeCanvasItem *main_item; + gchar *new_name = g_strdup (""); + const gchar *row_label, *column_label; + gint new_column, new_row; + gint start_day; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + cell = E_WEEK_VIEW_CELL (g_obj); + main_item = cell->week_view->main_canvas_item; + ea_main_item = atk_gobject_accessible_for_object (G_OBJECT (main_item)); + + start_day = cell->week_view->display_start_day; + if (cell->column + start_day >= 7) { + new_column = cell->column + start_day - 7; + new_row = cell->row + 1; + } else { + new_column = cell->column + start_day; + new_row = cell->row; + } + + column_label = atk_table_get_column_description (ATK_TABLE (ea_main_item), + new_column); + row_label = atk_table_get_row_description (ATK_TABLE (ea_main_item), + new_row); + new_name = g_strconcat (column_label, " ", row_label, NULL); + ATK_OBJECT_CLASS (parent_class)->set_name (accessible, new_name); + g_free (new_name); + } + return accessible->name; +} + +static G_CONST_RETURN gchar * +ea_week_view_cell_get_description (AtkObject *accessible) +{ + return ea_week_view_cell_get_name (accessible); +} + +static AtkStateSet* +ea_week_view_cell_ref_state_set (AtkObject *obj) +{ + AtkStateSet *state_set; + GObject *g_obj; + AtkObject *parent; + gint x, y, width, height; + gint parent_x, parent_y, parent_width, parent_height; + + state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (obj); + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(obj)); + if (!g_obj) + return state_set; + + atk_state_set_add_state (state_set, ATK_STATE_SELECTABLE); + + parent = atk_object_get_parent (obj); + atk_component_get_extents (ATK_COMPONENT (obj), &x, &y, + &width, &height, ATK_XY_WINDOW); + atk_component_get_extents (ATK_COMPONENT (parent), &parent_x, &parent_y, + &parent_width, &parent_height, ATK_XY_WINDOW); + + + if (x + width < parent_x || x > parent_x + parent_width || + y + height < parent_y || y > parent_y + parent_height) + /* the cell is out of the main canvas */ + ; + else + atk_state_set_add_state (state_set, ATK_STATE_VISIBLE); + + return state_set; +} + +static AtkObject * +ea_week_view_cell_get_parent (AtkObject *accessible) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewCell *cell; + + g_return_val_if_fail (EA_IS_WEEK_VIEW_CELL (accessible), NULL); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + cell = E_WEEK_VIEW_CELL (g_obj); + return atk_gobject_accessible_for_object (G_OBJECT (cell->week_view->main_canvas_item)); +} + +static gint +ea_week_view_cell_get_index_in_parent (AtkObject *accessible) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewCell *cell; + AtkObject *parent; + + g_return_val_if_fail (EA_IS_WEEK_VIEW_CELL (accessible), -1); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + cell = E_WEEK_VIEW_CELL (g_obj); + parent = atk_object_get_parent (accessible); + return atk_table_get_index_at (ATK_TABLE (parent), + cell->row, cell->column); +} + +/* Atk Component Interface */ + +static void +atk_component_interface_init (AtkComponentIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->get_extents = component_interface_get_extents; + iface->grab_focus = component_interface_grab_focus; +} + +static void +component_interface_get_extents (AtkComponent *component, + gint *x, gint *y, gint *width, gint *height, + AtkCoordType coord_type) +{ + GObject *g_obj; + AtkObject *atk_obj; + EWeekViewCell *cell; + EWeekView *week_view; + GtkWidget *main_canvas; + gint week_view_width, week_view_height; + gint scroll_x, scroll_y; + gint start_day; + + *x = *y = *width = *height = 0; + + g_return_if_fail (EA_IS_WEEK_VIEW_CELL (component)); + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(component)); + if (!g_obj) + /* defunct object*/ + return; + + cell = E_WEEK_VIEW_CELL (g_obj); + week_view = cell->week_view; + main_canvas = cell->week_view->main_canvas; + + atk_obj = atk_gobject_accessible_for_object (G_OBJECT (main_canvas)); + atk_component_get_extents (ATK_COMPONENT (atk_obj), + x, y, + &week_view_width, &week_view_height, + coord_type); + gnome_canvas_get_scroll_offsets (GNOME_CANVAS (week_view->main_canvas), + &scroll_x, &scroll_y); + start_day = week_view->display_start_day; + if (week_view->multi_week_view) { + if (week_view->compress_weekend && (cell->column == (5 - start_day))) { + *height = week_view->row_heights[cell->row*2]; + *width = week_view->col_widths[cell->column]; + *x += week_view->col_offsets[cell->column] - scroll_x; + *y += week_view->row_offsets[cell->row*2]- scroll_y; + } else if (week_view->compress_weekend && (cell->column == (6 - start_day))) { + *height = week_view->row_heights[cell->row*2]; + *width = week_view->col_widths[cell->column - 1]; + *x += week_view->col_offsets[cell->column - 1]- scroll_x; + *y += week_view->row_offsets[cell->row*2 + 1]- scroll_y; + } else if (week_view->compress_weekend && (cell->column > (6 - start_day))){ + *height = week_view->row_heights[cell->row*2]*2; + *width = week_view->col_widths[cell->column - 1]; + *x += week_view->col_offsets[cell->column - 1] - scroll_x; + *y += week_view->row_offsets[cell->row*2]- scroll_y; + } else { + *height = week_view->row_heights[cell->row*2]*2; + *width = week_view->col_widths[cell->column]; + *x += week_view->col_offsets[cell->column] - scroll_x; + *y += week_view->row_offsets[cell->row*2]- scroll_y; + } + } else { + if (start_day < 3) { + if (cell->column < 3) { + *height = week_view->row_heights[cell->column*2]*2; + *width = week_view->col_widths[0]; + *x += week_view->col_offsets[0] - scroll_x; + *y += week_view->row_offsets[cell->column*2]- scroll_y; + } else { + if (cell->column == 5 - start_day) { + *height = week_view->row_heights[(cell->column - 3)*2]; + *width = week_view->col_widths[1]; + *x += week_view->col_offsets[1] - scroll_x; + *y += week_view->row_offsets[(cell->column - 3)*2]- scroll_y; + } else if (cell->column == 6 - start_day) { + *height = week_view->row_heights[(cell->column - 4)*2]; + *width = week_view->col_widths[1]; + *x += week_view->col_offsets[1] - scroll_x; + *y += week_view->row_offsets[(cell->column - 3)*2 - 1]- scroll_y; + } else if (cell->column > 6 - start_day) { + *height = week_view->row_heights[(cell->column - 4)*2]*2; + *width = week_view->col_widths[1]; + *x += week_view->col_offsets[1] - scroll_x; + *y += week_view->row_offsets[(cell->column - 4)*2]- scroll_y; + } else { + *height = week_view->row_heights[(cell->column - 3)*2]*2; + *width = week_view->col_widths[1]; + *x += week_view->col_offsets[1] - scroll_x; + *y += week_view->row_offsets[(cell->column - 3)*2]- scroll_y; + } + } + } else if (cell->column < 4) { + if (cell->column == 5 - start_day) { + *height = week_view->row_heights[cell->column*2]; + *width = week_view->col_widths[0]; + *x += week_view->col_offsets[0] - scroll_x; + *y += week_view->row_offsets[cell->column*2]- scroll_y; + } else if (cell->column == 6 - start_day) { + *height = week_view->row_heights[(cell->column - 1)*2]; + *width = week_view->col_widths[0]; + *x += week_view->col_offsets[0] - scroll_x; + *y += week_view->row_offsets[cell->column*2 - 1]- scroll_y; + } else if (cell->column > 6 - start_day) { + *height = week_view->row_heights[(cell->column - 1)*2]*2; + *width = week_view->col_widths[0]; + *x += week_view->col_offsets[0] - scroll_x; + *y += week_view->row_offsets[(cell->column - 1)*2]- scroll_y; + } else { + *height = week_view->row_heights[(cell->column)*2]*2; + *width = week_view->col_widths[0]; + *x += week_view->col_offsets[0] - scroll_x; + *y += week_view->row_offsets[cell->column*2]- scroll_y; + } + } else { + *height = week_view->row_heights[(cell->column - 4)*2]*2; + *width = week_view->col_widths[1]; + *x += week_view->col_offsets[1] - scroll_x; + *y += week_view->row_offsets[(cell->column - 4)*2]- scroll_y; + } + } +} + +static gboolean +component_interface_grab_focus (AtkComponent *comp) +{ + GObject *g_obj; + EWeekViewCell *cell; + EWeekView *week_view; + GtkWidget *toplevel; + + g_return_val_if_fail (EA_IS_WEEK_VIEW_CELL (comp), FALSE); + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (comp)); + if (!g_obj) + return FALSE; + + cell = E_WEEK_VIEW_CELL (g_obj); + week_view = cell->week_view; + + week_view->selection_start_day = cell->row * 7 + cell->column; + week_view->selection_end_day = cell->row * 7 + cell->column; + gtk_widget_queue_draw (week_view->main_canvas); + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (week_view)); + if (GTK_WIDGET_TOPLEVEL (toplevel)) + gtk_window_present (GTK_WINDOW (toplevel)); + + return TRUE; +} diff --git a/calendar/gui/ea-week-view-cell.h b/calendar/gui/ea-week-view-cell.h new file mode 100644 index 0000000000..1524e9d3a8 --- /dev/null +++ b/calendar/gui/ea-week-view-cell.h @@ -0,0 +1,85 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * Yang Wu + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_WEEK_VIEW_CELL_H__ +#define __EA_WEEK_VIEW_CELL_H__ + +#include +#include "e-week-view.h" + +G_BEGIN_DECLS + +#define E_TYPE_WEEK_VIEW_CELL (e_week_view_cell_get_type ()) +#define E_WEEK_VIEW_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_WEEK_VIEW_CELL, EWeekViewCell)) +#define E_WEEK_VIEW_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_WEEK_VIEW_CELL, EWeekViewCellClass)) +#define E_IS_WEEK_VIEW_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_WEEK_VIEW_CELL)) +#define E_IS_WEEK_VIEW_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_WEEK_VIEW_CELL)) +#define E_WEEK_VIEW_CELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_WEEK_VIEW_CELL, EWeekViewCellClass)) + +typedef struct _EWeekViewCell EWeekViewCell; +typedef struct _EWeekViewCellClass EWeekViewCellClass; + +struct _EWeekViewCell +{ + GObject parent; + EWeekView *week_view; + gint row; + gint column; +}; + +GType e_week_view_cell_get_type (void); + +struct _EWeekViewCellClass +{ + GObjectClass parent_class; +}; + +EWeekViewCell * e_week_view_cell_new (EWeekView *week_view, gint row, gint column); + +#define EA_TYPE_WEEK_VIEW_CELL (ea_week_view_cell_get_type ()) +#define EA_WEEK_VIEW_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_WEEK_VIEW_CELL, EaWeekViewCell)) +#define EA_WEEK_VIEW_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_WEEK_VIEW_CELL, EaWeekViewCellClass)) +#define EA_IS_WEEK_VIEW_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_WEEK_VIEW_CELL)) +#define EA_IS_WEEK_VIEW_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_WEEK_VIEW_CELL)) +#define EA_WEEK_VIEW_CELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_WEEK_VIEW_CELL, EaWeekViewCellClass)) + +typedef struct _EaWeekViewCell EaWeekViewCell; +typedef struct _EaWeekViewCellClass EaWeekViewCellClass; + +struct _EaWeekViewCell +{ + AtkGObjectAccessible parent; +}; + +GType ea_week_view_cell_get_type (void); + +struct _EaWeekViewCellClass +{ + AtkGObjectAccessibleClass parent_class; +}; + +AtkObject* ea_week_view_cell_new (GObject *gobj); + +G_END_DECLS + +#endif /* __EA_WEEK_VIEW_CELL_H__ */ diff --git a/calendar/gui/ea-week-view-main-item.c b/calendar/gui/ea-week-view-main-item.c new file mode 100644 index 0000000000..74f4695a69 --- /dev/null +++ b/calendar/gui/ea-week-view-main-item.c @@ -0,0 +1,1247 @@ +/* + * Evolution Accessibility: ea-week-view-main-item.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "ea-week-view-main-item.h" +#include "ea-week-view.h" +#include "ea-week-view-cell.h" +#include "ea-cell-table.h" +#include + +/* EaWeekViewMainItem */ +static void ea_week_view_main_item_class_init (EaWeekViewMainItemClass *klass); + +static void ea_week_view_main_item_finalize (GObject *object); +static G_CONST_RETURN gchar * ea_week_view_main_item_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar * ea_week_view_main_item_get_description (AtkObject *accessible); + +static gint ea_week_view_main_item_get_n_children (AtkObject *obj); +static AtkObject* ea_week_view_main_item_ref_child (AtkObject *obj, + gint i); +static AtkObject * ea_week_view_main_item_get_parent (AtkObject *accessible); +static gint ea_week_view_main_item_get_index_in_parent (AtkObject *accessible); + +/* callbacks */ +static void ea_week_view_main_item_dates_change_cb (GnomeCalendar *gcal, gpointer data); +static void ea_week_view_main_item_time_change_cb (EWeekView *week_view, gpointer data); + +/* component interface */ +static void atk_component_interface_init (AtkComponentIface *iface); +static void component_interface_get_extents (AtkComponent *component, + gint *x, gint *y, + gint *width, gint *height, + AtkCoordType coord_type); + +/* atk table interface */ +static void atk_table_interface_init (AtkTableIface *iface); +static gint table_interface_get_index_at (AtkTable *table, + gint row, + gint column); +static gint table_interface_get_column_at_index (AtkTable *table, + gint index); +static gint table_interface_get_row_at_index (AtkTable *table, + gint index); +static AtkObject* table_interface_ref_at (AtkTable *table, + gint row, + gint column); +static gint table_interface_get_n_rows (AtkTable *table); +static gint table_interface_get_n_columns (AtkTable *table); +static gint table_interface_get_column_extent_at (AtkTable *table, + gint row, + gint column); +static gint table_interface_get_row_extent_at (AtkTable *table, + gint row, + gint column); + +static gboolean table_interface_is_row_selected (AtkTable *table, + gint row); +static gboolean table_interface_is_column_selected (AtkTable *table, + gint row); +static gboolean table_interface_is_selected (AtkTable *table, + gint row, + gint column); +static gint table_interface_get_selected_rows (AtkTable *table, + gint **rows_selected); +static gint table_interface_get_selected_columns (AtkTable *table, + gint **columns_selected); +static gboolean table_interface_add_row_selection (AtkTable *table, gint row); +static gboolean table_interface_remove_row_selection (AtkTable *table, + gint row); +static gboolean table_interface_add_column_selection (AtkTable *table, + gint column); +static gboolean table_interface_remove_column_selection (AtkTable *table, + gint column); +static AtkObject* table_interface_get_row_header (AtkTable *table, gint row); +static AtkObject* table_interface_get_column_header (AtkTable *table, + gint in_col); +static AtkObject* table_interface_get_caption (AtkTable *table); + +static G_CONST_RETURN gchar * +table_interface_get_column_description (AtkTable *table, gint in_col); + +static G_CONST_RETURN gchar * +table_interface_get_row_description (AtkTable *table, gint row); + +static AtkObject* table_interface_get_summary (AtkTable *table); + +/* atk selection interface */ +static void atk_selection_interface_init (AtkSelectionIface *iface); +static gboolean selection_interface_add_selection (AtkSelection *selection, + gint i); +static gboolean selection_interface_clear_selection (AtkSelection *selection); +static AtkObject* selection_interface_ref_selection (AtkSelection *selection, + gint i); +static gint selection_interface_get_selection_count (AtkSelection *selection); +static gboolean selection_interface_is_child_selected (AtkSelection *selection, + gint i); + +/* helpers */ +static EaCellTable * +ea_week_view_main_item_get_cell_data (EaWeekViewMainItem *ea_main_item); + +static void +ea_week_view_main_item_destory_cell_data (EaWeekViewMainItem *ea_main_item); + +static gint +ea_week_view_main_item_get_child_index_at (EaWeekViewMainItem *ea_main_item, + gint row, gint column); +static gint +ea_week_view_main_item_get_row_at_index (EaWeekViewMainItem *ea_main_item, + gint index); +static gint +ea_week_view_main_item_get_column_at_index (EaWeekViewMainItem *ea_main_item, + gint index); +static gint +ea_week_view_main_item_get_row_label (EaWeekViewMainItem *ea_main_item, + gint row, gchar *buffer, + gint buffer_size); + +#ifdef ACC_DEBUG +static gint n_ea_week_view_main_item_created = 0; +static gint n_ea_week_view_main_item_destroyed = 0; +#endif + +static gpointer parent_class = NULL; + +GType +ea_week_view_main_item_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaWeekViewMainItemClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) ea_week_view_main_item_class_init, + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (EaWeekViewMainItem), /* instance size */ + 0, /* nb preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) atk_component_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + static const GInterfaceInfo atk_table_info = { + (GInterfaceInitFunc) atk_table_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + static const GInterfaceInfo atk_selection_info = { + (GInterfaceInitFunc) atk_selection_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (GailCanvasItem, in this case) + * + */ + + factory = atk_registry_get_factory (atk_get_default_registry (), + e_week_view_main_item_get_type()); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + type = g_type_register_static (derived_atk_type, + "EaWeekViewMainItem", &tinfo, 0); + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, + &atk_component_info); + g_type_add_interface_static (type, ATK_TYPE_TABLE, + &atk_table_info); + g_type_add_interface_static (type, ATK_TYPE_SELECTION, + &atk_selection_info); + } + + return type; +} + +static void +ea_week_view_main_item_class_init (EaWeekViewMainItemClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + gobject_class->finalize = ea_week_view_main_item_finalize; + parent_class = g_type_class_peek_parent (klass); + + class->get_name = ea_week_view_main_item_get_name; + class->get_description = ea_week_view_main_item_get_description; + + class->get_n_children = ea_week_view_main_item_get_n_children; + class->ref_child = ea_week_view_main_item_ref_child; + class->get_parent = ea_week_view_main_item_get_parent; + class->get_index_in_parent = ea_week_view_main_item_get_index_in_parent; +} + +AtkObject* +ea_week_view_main_item_new (GObject *obj) +{ + AtkObject *accessible; + GnomeCalendar *gcal; + EWeekViewMainItem *main_item; + + g_return_val_if_fail (E_IS_WEEK_VIEW_MAIN_ITEM (obj), NULL); + + accessible = ATK_OBJECT (g_object_new (EA_TYPE_WEEK_VIEW_MAIN_ITEM, + NULL)); + + atk_object_initialize (accessible, obj); + accessible->role = ATK_ROLE_TABLE; + +#ifdef ACC_DEBUG + ++n_ea_week_view_main_item_created; + printf ("ACC_DEBUG: n_ea_week_view_main_item_created = %d\n", + n_ea_week_view_main_item_created); +#endif + main_item = E_WEEK_VIEW_MAIN_ITEM (obj); + g_signal_connect (main_item->week_view, "selected_time_changed", + G_CALLBACK (ea_week_view_main_item_time_change_cb), + accessible); + + /* listen for date changes of calendar */ + gcal = e_calendar_view_get_calendar (E_CALENDAR_VIEW (main_item->week_view)); + if (gcal) + g_signal_connect (gcal, "dates_shown_changed", + G_CALLBACK (ea_week_view_main_item_dates_change_cb), + accessible); + + return accessible; +} + +static void +ea_week_view_main_item_finalize (GObject *object) +{ + EaWeekViewMainItem *ea_main_item; + + g_return_if_fail (EA_IS_WEEK_VIEW_MAIN_ITEM (object)); + + ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (object); + + /* Free the allocated cell data */ + ea_week_view_main_item_destory_cell_data (ea_main_item); + + G_OBJECT_CLASS (parent_class)->finalize (object); +#ifdef ACC_DEBUG + ++n_ea_week_view_main_item_destroyed; + printf ("ACC_DEBUG: n_ea_week_view_main_item_destroyed = %d\n", + n_ea_week_view_main_item_destroyed); +#endif +} + +static G_CONST_RETURN gchar * +ea_week_view_main_item_get_name (AtkObject *accessible) +{ + AtkObject *parent; + g_return_val_if_fail (EA_IS_WEEK_VIEW_MAIN_ITEM (accessible), NULL); + parent = atk_object_get_parent (accessible); + return atk_object_get_name (parent); + +} + +static G_CONST_RETURN gchar * +ea_week_view_main_item_get_description (AtkObject *accessible) +{ + return _("a table to view and select the current time range"); +} + +static gint +ea_week_view_main_item_get_n_children (AtkObject *accessible) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewMainItem *main_item; + EWeekView *week_view; + + g_return_val_if_fail (EA_IS_WEEK_VIEW_MAIN_ITEM (accessible), -1); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); + week_view = main_item->week_view; + + if (week_view->multi_week_view) + return 7 * week_view->weeks_shown; + else + return 7; +} + +static AtkObject * +ea_week_view_main_item_ref_child (AtkObject *accessible, gint index) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewMainItem *main_item; + EWeekView *week_view; + gint n_children; + EWeekViewCell *cell; + EaCellTable *cell_data; + EaWeekViewMainItem *ea_main_item; + + g_return_val_if_fail (EA_IS_WEEK_VIEW_MAIN_ITEM (accessible), NULL); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); + week_view = main_item->week_view; + + n_children = ea_week_view_main_item_get_n_children (accessible); + if (index < 0 || index >= n_children) + return NULL; + + ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (accessible); + cell_data = ea_week_view_main_item_get_cell_data (ea_main_item); + if (!cell_data) + return NULL; + cell = ea_cell_table_get_cell_at_index (cell_data, index); + if (!cell) { + gint row, column; + + row = ea_week_view_main_item_get_row_at_index (ea_main_item, index); + column = ea_week_view_main_item_get_column_at_index (ea_main_item, index); + cell = e_week_view_cell_new (week_view, row, column); + ea_cell_table_set_cell_at_index (cell_data, index, cell); + g_object_unref (cell); + } + + return g_object_ref (atk_gobject_accessible_for_object (G_OBJECT(cell))); +} + +static AtkObject * +ea_week_view_main_item_get_parent (AtkObject *accessible) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewMainItem *main_item; + + g_return_val_if_fail (EA_IS_WEEK_VIEW_MAIN_ITEM (accessible), NULL); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); + return gtk_widget_get_accessible (GTK_WIDGET (main_item->week_view)); +} + +static gint +ea_week_view_main_item_get_index_in_parent (AtkObject *accessible) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + + g_return_val_if_fail (EA_IS_WEEK_VIEW_MAIN_ITEM (accessible), -1); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + /* always the first child of ea-week-view */ + return 0; +} + +/* callbacks */ + +static void +ea_week_view_main_item_dates_change_cb (GnomeCalendar *gcal, gpointer data) +{ + EaWeekViewMainItem *ea_main_item; + + g_return_if_fail (GNOME_IS_CALENDAR (gcal)); + g_return_if_fail (data); + g_return_if_fail (EA_IS_WEEK_VIEW_MAIN_ITEM (data)); + + ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (data); + +#ifdef ACC_DEBUG + printf ("EvoAcc: ea_week_view_main_item update cb\n"); +#endif + + ea_week_view_main_item_destory_cell_data (ea_main_item); +} + +static void +ea_week_view_main_item_time_change_cb (EWeekView *week_view, gpointer data) +{ + EaWeekViewMainItem *ea_main_item; + AtkObject *item_cell = NULL; + + g_return_if_fail (E_IS_WEEK_VIEW (week_view)); + g_return_if_fail (data); + g_return_if_fail (EA_IS_WEEK_VIEW_MAIN_ITEM (data)); + + ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (data); + +#ifdef ACC_DEBUG + printf ("EvoAcc: ea_week_view_main_item time changed cb\n"); +#endif + /* only deal with the first selected child, for now */ + item_cell = atk_selection_ref_selection (ATK_SELECTION (ea_main_item), + 0); + if (item_cell) { + AtkStateSet *state_set; + state_set = atk_object_ref_state_set (item_cell); + atk_state_set_add_state (state_set, ATK_STATE_FOCUSED); + g_object_unref (state_set); + + g_signal_emit_by_name (ea_main_item, + "active-descendant-changed", + item_cell); + g_signal_emit_by_name (data, "selection_changed"); + atk_focus_tracker_notify (item_cell); + g_object_unref (item_cell); + } +} + +/* helpers */ + +static gint +ea_week_view_main_item_get_child_index_at (EaWeekViewMainItem *ea_main_item, + gint row, gint column) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewMainItem *main_item; + EWeekView *week_view; + + g_return_val_if_fail (ea_main_item, -1); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); + week_view = main_item->week_view; + + if (row >= 0 && row < week_view->weeks_shown && + column >= 0 && column < 7) + return row * 7 + column; + + return -1; +} + +static gint +ea_week_view_main_item_get_row_at_index (EaWeekViewMainItem *ea_main_item, + gint index) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + gint n_children; + + g_return_val_if_fail (ea_main_item, -1); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + n_children = ea_week_view_main_item_get_n_children (ATK_OBJECT (ea_main_item)); + if (index >= 0 && index < n_children) + return index / 7; + return -1; +} + +static gint +ea_week_view_main_item_get_column_at_index (EaWeekViewMainItem *ea_main_item, + gint index) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + gint n_children; + + g_return_val_if_fail (ea_main_item, -1); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + n_children = ea_week_view_main_item_get_n_children (ATK_OBJECT (ea_main_item)); + if (index >= 0 && index < n_children) + return index % 7; + return -1; +} + +static gint +ea_week_view_main_item_get_row_label (EaWeekViewMainItem *ea_main_item, + gint row, gchar *buffer, gint buffer_size) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + + g_return_val_if_fail (ea_main_item, 0); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return 0; + + return g_snprintf (buffer, buffer_size, "the %i week", + row + 1); + +} + +static EaCellTable * +ea_week_view_main_item_get_cell_data (EaWeekViewMainItem *ea_main_item) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewMainItem *main_item; + EWeekView *week_view; + EaCellTable *cell_data; + + g_return_val_if_fail (ea_main_item, NULL); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); + week_view = main_item->week_view; + + cell_data = g_object_get_data (G_OBJECT(ea_main_item), + "ea-week-view-cell-table"); + if (!cell_data) { + cell_data = ea_cell_table_create (week_view->weeks_shown, 7, TRUE); + g_object_set_data (G_OBJECT(ea_main_item), + "ea-week-view-cell-table", cell_data); + } + return cell_data; +} + +static void +ea_week_view_main_item_destory_cell_data (EaWeekViewMainItem *ea_main_item) +{ + EaCellTable *cell_data; + + g_return_if_fail (ea_main_item); + + cell_data = g_object_get_data (G_OBJECT(ea_main_item), + "ea-week-view-cell-table"); + if (cell_data) { + g_object_set_data (G_OBJECT(ea_main_item), + "ea-week-view-cell-table", NULL); + ea_cell_table_destroy (cell_data); + } +} + +/* Atk Component Interface */ + +static void +atk_component_interface_init (AtkComponentIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->get_extents = component_interface_get_extents; +} + +static void +component_interface_get_extents (AtkComponent *component, + gint *x, gint *y, gint *width, gint *height, + AtkCoordType coord_type) +{ + GObject *g_obj; + AtkObject *ea_canvas; + EWeekViewMainItem *main_item; + EWeekView *week_view; + + *x = *y = *width = *height = 0; + + g_return_if_fail (EA_IS_WEEK_VIEW_MAIN_ITEM (component)); + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(component)); + if (!g_obj) + /* defunct object*/ + return; + main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); + week_view = main_item->week_view; + + ea_canvas = gtk_widget_get_accessible (week_view->main_canvas); + atk_component_get_extents (ATK_COMPONENT (ea_canvas), x, y, + width, height, coord_type); +} + +/* atk table interface */ + +static void +atk_table_interface_init (AtkTableIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->ref_at = table_interface_ref_at; + + iface->get_n_rows = table_interface_get_n_rows; + iface->get_n_columns = table_interface_get_n_columns; + iface->get_index_at = table_interface_get_index_at; + iface->get_column_at_index = table_interface_get_column_at_index; + iface->get_row_at_index = table_interface_get_row_at_index; + iface->get_column_extent_at = table_interface_get_column_extent_at; + iface->get_row_extent_at = table_interface_get_row_extent_at; + + iface->is_selected = table_interface_is_selected; + iface->get_selected_rows = table_interface_get_selected_rows; + iface->get_selected_columns = table_interface_get_selected_columns; + iface->is_row_selected = table_interface_is_row_selected; + iface->is_column_selected = table_interface_is_column_selected; + iface->add_row_selection = table_interface_add_row_selection; + iface->remove_row_selection = table_interface_remove_row_selection; + iface->add_column_selection = table_interface_add_column_selection; + iface->remove_column_selection = table_interface_remove_column_selection; + + iface->get_row_header = table_interface_get_row_header; + iface->get_column_header = table_interface_get_column_header; + iface->get_caption = table_interface_get_caption; + iface->get_summary = table_interface_get_summary; + iface->get_row_description = table_interface_get_row_description; + iface->get_column_description = table_interface_get_column_description; +} + +static AtkObject* +table_interface_ref_at (AtkTable *table, + gint row, + gint column) +{ + gint index; + + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); + index = ea_week_view_main_item_get_child_index_at (ea_main_item, + row, column); + return ea_week_view_main_item_ref_child (ATK_OBJECT (ea_main_item), index); +} + +static gint +table_interface_get_n_rows (AtkTable *table) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewMainItem *main_item; + EWeekView *week_view; + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); + week_view = main_item->week_view; + + return week_view->weeks_shown; +} + +static gint +table_interface_get_n_columns (AtkTable *table) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + return 7; +} + +static gint +table_interface_get_index_at (AtkTable *table, + gint row, + gint column) +{ + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); + return ea_week_view_main_item_get_child_index_at (ea_main_item, + row, column); +} + +static gint +table_interface_get_column_at_index (AtkTable *table, + gint index) +{ + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); + return ea_week_view_main_item_get_column_at_index (ea_main_item, index); +} + +static gint +table_interface_get_row_at_index (AtkTable *table, + gint index) +{ + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); + return ea_week_view_main_item_get_row_at_index (ea_main_item, index); +} + +static gint +table_interface_get_column_extent_at (AtkTable *table, + gint row, + gint column) +{ + gint index; + gint width = 0, height = 0; + AtkObject *child; + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); + + index = ea_week_view_main_item_get_child_index_at (ea_main_item, + row, column); + child = atk_object_ref_accessible_child (ATK_OBJECT (ea_main_item), + index); + if (child) + atk_component_get_size (ATK_COMPONENT (child), + &width, &height); + + return width; +} + +static gint +table_interface_get_row_extent_at (AtkTable *table, + gint row, + gint column) +{ + gint index; + gint width = 0, height = 0; + AtkObject *child; + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); + + index = ea_week_view_main_item_get_child_index_at (ea_main_item, + row, column); + child = atk_object_ref_accessible_child (ATK_OBJECT (ea_main_item), + index); + if (child) + atk_component_get_size (ATK_COMPONENT (child), + &width, &height); + + return height; +} + +static gboolean +table_interface_is_row_selected (AtkTable *table, + gint row) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewMainItem *main_item; + EWeekView *week_view; + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); + week_view = main_item->week_view; + + if (week_view->selection_start_day == -1) + /* no selection */ + return FALSE; + if ((row < 0)&&(row + 1 > week_view->weeks_shown )) + return FALSE; + if (((week_view->selection_start_day < row*7)&&(week_view->selection_end_dayselection_start_day > row*7+6)&&(week_view->selection_end_day > row*7+6))) + return FALSE; + else + return TRUE; +} + +static gboolean +table_interface_is_selected (AtkTable *table, + gint row, + gint column) +{ + return table_interface_is_row_selected (table, row) && table_interface_is_column_selected(table, column); +} + +static gboolean +table_interface_is_column_selected (AtkTable *table, + gint column) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewMainItem *main_item; + EWeekView *week_view; + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); + week_view = main_item->week_view; + + if ((column <0)||(column >6)) + return FALSE; + else { + gint i; + for (i=0;iweeks_shown;i++) + if ((column + i*7>= week_view->selection_start_day ) && + (column + i*7<= week_view->selection_end_day)) + return TRUE; + return FALSE; + } +} + +static gint +table_interface_get_selected_rows (AtkTable *table, + gint **rows_selected) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewMainItem *main_item; + EWeekView *week_view; + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); + gint start_row = -1, n_rows = 0; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); + week_view = main_item->week_view; + + if (week_view->selection_start_day == -1) + return 0; + + start_row = week_view->selection_start_day; + n_rows = week_view->selection_end_day - start_row + 1; + + if (n_rows > 0 && start_row != -1 && rows_selected) { + gint index; + + *rows_selected = (gint *) g_malloc (n_rows * sizeof (gint)); + for (index = 0; index < n_rows; ++index) + (*rows_selected)[index] = start_row + index; + } + return n_rows; +} + +static gint +table_interface_get_selected_columns (AtkTable *table, + gint **columns_selected) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewMainItem *main_item; + EWeekView *week_view; + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); + gint start_column = -1, n_columns = 0; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); + week_view = main_item->week_view; + + if (week_view->selection_start_day == -1) + return 0; + if (week_view->selection_end_day - week_view->selection_start_day >= 6 ) { + start_column = 0; + n_columns =7; + } else { + start_column = week_view->selection_start_day % 7; + n_columns = (week_view->selection_end_day % 7) - start_column + 1; + } + if (n_columns > 0 && start_column != -1 && columns_selected) { + gint index; + + *columns_selected = (gint *) g_malloc (n_columns * sizeof (gint)); + for (index = 0; index < n_columns; ++index) + (*columns_selected)[index] = start_column + index; + } + return n_columns; +} + +static gboolean +table_interface_add_row_selection (AtkTable *table, + gint row) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewMainItem *main_item; + EWeekView *week_view; + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); + week_view = main_item->week_view; + + /* FIXME: we need multi-selection */ + + week_view->selection_start_day = row * 7; + week_view->selection_end_day = row *7 + 6; + + gtk_widget_queue_draw (week_view->main_canvas); + return TRUE; +} + +static gboolean +table_interface_remove_row_selection (AtkTable *table, + gint row) +{ + return FALSE; +} + +static gboolean +table_interface_add_column_selection (AtkTable *table, + gint column) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewMainItem *main_item; + EWeekView *week_view; + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); + week_view = main_item->week_view; + + /* FIXME: we need multi-selection */ + + week_view->selection_start_day = column; + week_view->selection_end_day = (week_view->weeks_shown - 1)*7+column; + + gtk_widget_queue_draw (week_view->main_canvas); + return TRUE; +} + +static gboolean +table_interface_remove_column_selection (AtkTable *table, + gint column) +{ + /* FIXME: NOT IMPLEMENTED */ + return FALSE; +} + +static AtkObject* +table_interface_get_row_header (AtkTable *table, + gint row) +{ + /* FIXME: NOT IMPLEMENTED */ + return NULL; +} + +static AtkObject* +table_interface_get_column_header (AtkTable *table, + gint in_col) +{ + /* FIXME: NOT IMPLEMENTED */ + return NULL; +} + +static AtkObject* +table_interface_get_caption (AtkTable *table) +{ + /* FIXME: NOT IMPLEMENTED */ + return NULL; +} + +static G_CONST_RETURN gchar * +table_interface_get_column_description (AtkTable *table, + gint in_col) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); + const gchar *description; + EaCellTable *cell_data; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + if (in_col < 0 || in_col > 6) + return NULL; + cell_data = ea_week_view_main_item_get_cell_data (ea_main_item); + if (!cell_data) + return NULL; + + description = ea_cell_table_get_column_label (cell_data, in_col); + if (!description) { + gchar buffer[128]; + + switch (in_col) { + case 0: + g_snprintf(buffer,128,"Monday"); + break; + case 1: + g_snprintf(buffer,128,"Tuesday"); + break; + case 2: + g_snprintf(buffer,128,"Wednesday"); + break; + case 3: + g_snprintf(buffer,128,"Thursday"); + break; + case 4: + g_snprintf(buffer,128,"Friday"); + break; + case 5: + g_snprintf(buffer,128,"Saturday"); + break; + case 6: + g_snprintf(buffer,128,"Sunday"); + break; + default: + break; + } + + ea_cell_table_set_column_label (cell_data, in_col, buffer); + description = ea_cell_table_get_column_label (cell_data, in_col); + } + return description; +} + +static G_CONST_RETURN gchar * +table_interface_get_row_description (AtkTable *table, + gint row) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewMainItem *main_item; + EWeekView *week_view; + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (table); + const gchar *description; + EaCellTable *cell_data; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); + week_view = main_item->week_view; + + if (row < 0 || row >= week_view->weeks_shown) + return NULL; + cell_data = ea_week_view_main_item_get_cell_data (ea_main_item); + if (!cell_data) + return NULL; + + description = ea_cell_table_get_row_label (cell_data, row); + if (!description) { + gchar buffer[128]; + ea_week_view_main_item_get_row_label (ea_main_item, row, buffer, sizeof (buffer)); + ea_cell_table_set_row_label (cell_data, row, buffer); + description = ea_cell_table_get_row_label (cell_data, + row); + } + return description; +} + +static AtkObject* +table_interface_get_summary (AtkTable *table) +{ + /* FIXME: NOT IMPLEMENTED */ + return NULL; +} + +/* atkselection interface */ + +static void +atk_selection_interface_init (AtkSelectionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->add_selection = selection_interface_add_selection; + iface->clear_selection = selection_interface_clear_selection; + iface->ref_selection = selection_interface_ref_selection; + iface->get_selection_count = selection_interface_get_selection_count; + iface->is_child_selected = selection_interface_is_child_selected; +} + +static gboolean +selection_interface_add_selection (AtkSelection *selection, gint i) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewMainItem *main_item; + EWeekView *week_view; + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (selection); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); + week_view = main_item->week_view; + + if (i < 0 || i > week_view->weeks_shown * 7 -1) + return FALSE; + + /*FIXME: multi-selection is needed */ + week_view->selection_start_day = i; + week_view->selection_end_day = i; + + gtk_widget_queue_draw (week_view->main_canvas); + return TRUE; +} + +static gboolean +selection_interface_clear_selection (AtkSelection *selection) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewMainItem *main_item; + EWeekView *week_view; + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (selection); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); + week_view = main_item->week_view; + + week_view->selection_start_day = -1; + week_view->selection_end_day = -1; + + gtk_widget_queue_draw (week_view->main_canvas); + + return TRUE; +} + +static AtkObject* +selection_interface_ref_selection (AtkSelection *selection, gint i) +{ + gint count; + GObject *g_obj; + EWeekView *week_view; + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (selection); + gint start_index; + + count = selection_interface_get_selection_count (selection); + if (i < 0 || i >=count) + return NULL; + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (ea_main_item)); + week_view = E_WEEK_VIEW_MAIN_ITEM (g_obj)->week_view; + start_index = ea_week_view_main_item_get_child_index_at (ea_main_item, + week_view->selection_start_day / 7, + week_view->selection_start_day % 7); + + return ea_week_view_main_item_ref_child (ATK_OBJECT (selection), start_index + i); +} + +static gint +selection_interface_get_selection_count (AtkSelection *selection) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewMainItem *main_item; + EWeekView *week_view; + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (selection); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return 0; + + main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); + week_view = main_item->week_view; + + if (week_view->selection_start_day == -1 || + week_view->selection_end_day == -1) + return 0; + + return week_view->selection_end_day - week_view->selection_start_day + 1; +} + +static gboolean +selection_interface_is_child_selected (AtkSelection *selection, gint i) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EWeekViewMainItem *main_item; + EWeekView *week_view; + EaWeekViewMainItem* ea_main_item = EA_WEEK_VIEW_MAIN_ITEM (selection); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_main_item); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + main_item = E_WEEK_VIEW_MAIN_ITEM (g_obj); + week_view = main_item->week_view; + + if ((week_view->selection_start_day <= i)&&(week_view->selection_end_day >= i)) + return TRUE; + else + return FALSE; +} + diff --git a/calendar/gui/ea-week-view-main-item.h b/calendar/gui/ea-week-view-main-item.h new file mode 100644 index 0000000000..d9110160c4 --- /dev/null +++ b/calendar/gui/ea-week-view-main-item.h @@ -0,0 +1,59 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * Yang Wu + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_WEEK_VIEW_MAIN_ITEM_H__ +#define __EA_WEEK_VIEW_MAIN_ITEM_H__ + +#include +#include "e-week-view-main-item.h" + +G_BEGIN_DECLS + +#define EA_TYPE_WEEK_VIEW_MAIN_ITEM (ea_week_view_main_item_get_type ()) +#define EA_WEEK_VIEW_MAIN_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_WEEK_VIEW_MAIN_ITEM, EaWeekViewMainItem)) +#define EA_WEEK_VIEW_MAIN_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_WEEK_VIEW_MAIN_ITEM, EaWeekViewMainItemClass)) +#define EA_IS_WEEK_VIEW_MAIN_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_WEEK_VIEW_MAIN_ITEM)) +#define EA_IS_WEEK_VIEW_MAIN_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_WEEK_VIEW_MAIN_ITEM)) +#define EA_WEEK_VIEW_MAIN_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_WEEK_VIEW_MAIN_ITEM, EaWeekViewMainItemClass)) + +typedef struct _EaWeekViewMainItem EaWeekViewMainItem; +typedef struct _EaWeekViewMainItemClass EaWeekViewMainItemClass; + +struct _EaWeekViewMainItem +{ + AtkGObjectAccessible parent; +}; + +GType ea_week_view_main_item_get_type (void); + +struct _EaWeekViewMainItemClass +{ + AtkGObjectAccessibleClass parent_class; +}; + +AtkObject* ea_week_view_main_item_new (GObject *obj); + +G_END_DECLS + +#endif /* __EA_WEEK_VIEW_MAIN_ITEM_H__ */ diff --git a/calendar/gui/ea-week-view.c b/calendar/gui/ea-week-view.c new file mode 100644 index 0000000000..97a8dae25d --- /dev/null +++ b/calendar/gui/ea-week-view.c @@ -0,0 +1,321 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "ea-week-view.h" +#include "ea-cal-view-event.h" +#include "ea-calendar-helpers.h" +#include "ea-gnome-calendar.h" +#include "calendar-commands.h" +#include +#include + +static void ea_week_view_class_init (EaWeekViewClass *klass); + +static G_CONST_RETURN gchar * ea_week_view_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar * ea_week_view_get_description (AtkObject *accessible); +static gint ea_week_view_get_n_children (AtkObject *obj); +static AtkObject* ea_week_view_ref_child (AtkObject *obj, + gint i); + +static gpointer parent_class = NULL; + +GType +ea_week_view_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaWeekViewClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) ea_week_view_class_init, /* class init */ + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (EaWeekView), /* instance size */ + 0, /* nb preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (EaCalView, in this case) + * + * Note: we must still use run-time deriving here, because + * our parent class EaCalView is run-time deriving. + */ + + factory = atk_registry_get_factory (atk_get_default_registry (), + e_calendar_view_get_type()); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + type = g_type_register_static (derived_atk_type, + "EaWeekView", &tinfo, 0); + + } + + return type; +} + +static void +ea_week_view_class_init (EaWeekViewClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + class->get_name = ea_week_view_get_name; + class->get_description = ea_week_view_get_description; + + class->get_n_children = ea_week_view_get_n_children; + class->ref_child = ea_week_view_ref_child; +} + +AtkObject* +ea_week_view_new (GtkWidget *widget) +{ + GObject *object; + AtkObject *accessible; + + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + + object = g_object_new (EA_TYPE_WEEK_VIEW, NULL); + + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, widget); + +#ifdef ACC_DEBUG + printf ("EvoAcc: ea_week_view created %p\n", (gpointer)accessible); +#endif + + return accessible; +} + +static G_CONST_RETURN gchar * +ea_week_view_get_name (AtkObject *accessible) +{ + EWeekView *week_view; + GnomeCalendar *gcal; + const gchar *label_text; + GnomeCalendarViewType view_type; + gint n_events; + gchar *event_str, *name_str; + + g_return_val_if_fail (EA_IS_WEEK_VIEW (accessible), NULL); + + if (!GTK_ACCESSIBLE (accessible)->widget) + return NULL; + + week_view = E_WEEK_VIEW (GTK_ACCESSIBLE (accessible)->widget); + gcal = e_calendar_view_get_calendar (E_CALENDAR_VIEW (week_view)); + if (!GTK_WIDGET_VISIBLE (GTK_WIDGET (gcal))) + return NULL; + + label_text = ea_gnome_calendar_get_label_description (gcal); + + n_events = atk_object_get_n_accessible_children (accessible); + /* the child main item is always there */ + --n_events; + if (n_events >= 1) + event_str = g_strdup_printf (ngettext ("It has %d event.", "It has %d events.", n_events), n_events); + else + event_str = g_strdup (_("It has no events.")); + + view_type = gnome_calendar_get_view (gcal); + + if (view_type == GNOME_CAL_MONTH_VIEW) + name_str = g_strdup_printf (_("Month View: %s. %s"), + label_text, event_str); + + else + name_str = g_strdup_printf (_("Week View: %s. %s"), + label_text, event_str); + + ATK_OBJECT_CLASS (parent_class)->set_name (accessible, name_str); + g_free (name_str); + g_free (event_str); + + return accessible->name; +} + +static G_CONST_RETURN gchar * +ea_week_view_get_description (AtkObject *accessible) +{ + EWeekView *week_view; + + g_return_val_if_fail (EA_IS_WEEK_VIEW (accessible), NULL); + + if (!GTK_ACCESSIBLE (accessible)->widget) + return NULL; + week_view = E_WEEK_VIEW (GTK_ACCESSIBLE (accessible)->widget); + + if (accessible->description) + return accessible->description; + else { + GnomeCalendar *gcal; + GnomeCalendarViewType view_type; + + gcal = e_calendar_view_get_calendar (E_CALENDAR_VIEW (week_view)); + view_type = gnome_calendar_get_view (gcal); + + if (view_type == GNOME_CAL_MONTH_VIEW) + return _("calendar view for a month"); + else + return _("calendar view for one or more weeks"); + } +} + +static gint +ea_week_view_get_n_children (AtkObject *accessible) +{ + EWeekView *week_view; + gint i, count = 0; + gint event_index; + + g_return_val_if_fail (EA_IS_WEEK_VIEW (accessible), -1); + + if (!GTK_ACCESSIBLE (accessible)->widget) + return -1; + week_view = E_WEEK_VIEW (GTK_ACCESSIBLE (accessible)->widget); + + for (event_index = 0; event_index < week_view->events->len; + ++event_index) { + EWeekViewEvent *event; + EWeekViewEventSpan *span; + + /* If week_view->spans == NULL, there is no visible events. */ + if (!week_view->spans) + break; + + event = &g_array_index (week_view->events, + EWeekViewEvent, event_index); + if (!event) + continue; + span = &g_array_index (week_view->spans, EWeekViewEventSpan, + event->spans_index + 0); + + if (!span) + continue; + + /* at least one of the event spans is visible, count it */ + if (span->text_item) + ++count; + } + + /* add the number of visible jump buttons */ + for (i = 0; i < E_WEEK_VIEW_MAX_WEEKS * 7; i++) { + if (week_view->jump_buttons[i]->object.flags & GNOME_CANVAS_ITEM_VISIBLE) + ++count; + } + + /* "+1" for the main item */ + count++; + +#ifdef ACC_DEBUG + printf("AccDebug: week view %p has %d children\n", (gpointer)week_view, count); +#endif + return count; +} + +static AtkObject * +ea_week_view_ref_child (AtkObject *accessible, gint index) +{ + EWeekView *week_view; + gint child_num, max_count; + AtkObject *atk_object = NULL; + gint event_index; + gint jump_button = -1; + gint span_num = 0; + gint count = 0; + + g_return_val_if_fail (EA_IS_WEEK_VIEW (accessible), NULL); + + child_num = atk_object_get_n_accessible_children (accessible); + if (child_num <= 0 || index < 0 || index >= child_num) + return NULL; + + if (!GTK_ACCESSIBLE (accessible)->widget) + return NULL; + week_view = E_WEEK_VIEW (GTK_ACCESSIBLE (accessible)->widget); + max_count = week_view->events->len; + + if (index == 0) { + /* index == 0 is the main item */ + atk_object = atk_gobject_accessible_for_object (G_OBJECT (week_view->main_canvas_item)); + g_object_ref (atk_object); + } else + for (event_index = 0; event_index < max_count; ++event_index) { + EWeekViewEvent *event; + EWeekViewEventSpan *span; + gint current_day; + + event = &g_array_index (week_view->events, + EWeekViewEvent, event_index); + if (!event) + continue; + + span = &g_array_index (week_view->spans, EWeekViewEventSpan, + event->spans_index + span_num); + + if (!span) + continue; + + current_day = span->start_day; + if (span->text_item) + ++count; + else if (current_day != jump_button) { + /* we should go to the jump button */ + jump_button = current_day; + ++count; + } + else + continue; + + if (count == index) { + if (span->text_item) { + /* Not use atk_gobject_accessible_for_object for event + * text_item we need to do special thing here + */ + atk_object = ea_calendar_helpers_get_accessible_for (span->text_item); + } + else { + atk_object = ea_calendar_helpers_get_accessible_for (week_view->jump_buttons[current_day == -1 ? 0 : current_day]); + } + g_object_ref (atk_object); + break; + } + } + +#ifdef ACC_DEBUG + printf ("EvoAcc: ea_week_view_ref_child [%d]=%p\n", + index, (gpointer)atk_object); +#endif + return atk_object; +} diff --git a/calendar/gui/ea-week-view.h b/calendar/gui/ea-week-view.h new file mode 100644 index 0000000000..bb71c17e74 --- /dev/null +++ b/calendar/gui/ea-week-view.h @@ -0,0 +1,59 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_WEEK_VIEW_H__ +#define __EA_WEEK_VIEW_H__ + +#include "ea-cal-view.h" +#include "e-week-view.h" + +G_BEGIN_DECLS + +#define EA_TYPE_WEEK_VIEW (ea_week_view_get_type ()) +#define EA_WEEK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_WEEK_VIEW, EaWeekView)) +#define EA_WEEK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_WEEK_VIEW, EaWeekViewClass)) +#define EA_IS_WEEK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_WEEK_VIEW)) +#define EA_IS_WEEK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_WEEK_VIEW)) +#define EA_WEEK_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_WEEK_VIEW, EaWeekViewClass)) + +typedef struct _EaWeekView EaWeekView; +typedef struct _EaWeekViewClass EaWeekViewClass; + +struct _EaWeekView +{ + EaCalView parent; +}; + +GType ea_week_view_get_type (void); + +struct _EaWeekViewClass +{ + EaCalViewClass parent_class; +}; + +AtkObject* ea_week_view_new (GtkWidget *widget); + +G_END_DECLS + + +#endif /* __EA_WEEK_VIEW_H__ */ diff --git a/calendar/module/Makefile.am b/calendar/module/Makefile.am deleted file mode 100644 index 59c6f8098d..0000000000 --- a/calendar/module/Makefile.am +++ /dev/null @@ -1,81 +0,0 @@ -INCLUDES = \ - -DG_LOG_DOMAIN=\"calendar-modules\" \ - -I$(top_srcdir) \ - -I$(top_srcdir)/widgets \ - -DEVOLUTION_ETSPECDIR=\""$(etspecdir)"\" \ - $(EVOLUTION_CALENDAR_CFLAGS) - -module_LTLIBRARIES = \ - libevolution-module-calendar.la - -libevolution_module_calendar_la_SOURCES = \ - evolution-module-calendar.c \ - e-cal-shell-backend.c \ - e-cal-shell-backend.h \ - e-cal-shell-content.c \ - e-cal-shell-content.h \ - e-cal-shell-migrate.c \ - e-cal-shell-migrate.h \ - e-cal-shell-settings.c \ - e-cal-shell-settings.h \ - e-cal-shell-sidebar.c \ - e-cal-shell-sidebar.h \ - e-cal-shell-view.c \ - e-cal-shell-view.h \ - e-cal-shell-view-actions.c \ - e-cal-shell-view-actions.h \ - e-cal-shell-view-memopad.c \ - e-cal-shell-view-private.c \ - e-cal-shell-view-private.h \ - e-cal-shell-view-taskpad.c \ - e-memo-shell-backend.c \ - e-memo-shell-backend.h \ - e-memo-shell-content.c \ - e-memo-shell-content.h \ - e-memo-shell-migrate.c \ - e-memo-shell-migrate.h \ - e-memo-shell-sidebar.c \ - e-memo-shell-sidebar.h \ - e-memo-shell-view.c \ - e-memo-shell-view.h \ - e-memo-shell-view-actions.c \ - e-memo-shell-view-actions.h \ - e-memo-shell-view-private.c \ - e-memo-shell-view-private.h \ - e-task-shell-backend.c \ - e-task-shell-backend.h \ - e-task-shell-content.c \ - e-task-shell-content.h \ - e-task-shell-migrate.c \ - e-task-shell-migrate.h \ - e-task-shell-sidebar.c \ - e-task-shell-sidebar.h \ - e-task-shell-view.c \ - e-task-shell-view.h \ - e-task-shell-view-actions.c \ - e-task-shell-view-actions.h \ - e-task-shell-view-private.c \ - e-task-shell-view-private.h - -# Removed from all three -# $(top_builddir)/a11y/calendar/libevolution-calendar-a11y.la - -libevolution_module_calendar_la_LIBADD = \ - $(top_builddir)/shell/libeshell.la \ - $(top_builddir)/calendar/gui/libcal-gui.la \ - $(top_builddir)/calendar/importers/libevolution-calendar-importers.la \ - $(top_builddir)/mail/libevolution-module-mail.la \ - $(top_builddir)/addressbook/gui/contact-editor/libecontacteditor.la \ - $(top_builddir)/addressbook/gui/contact-list-editor/libecontactlisteditor.la \ - $(top_builddir)/e-util/libeutil.la \ - $(top_builddir)/filter/libfilter.la \ - $(top_builddir)/widgets/menus/libmenus.la \ - $(top_builddir)/widgets/misc/libemiscwidgets.la \ - $(top_builddir)/widgets/table/libetable.la \ - $(CAMEL_LIBS) \ - $(EVOLUTION_CALENDAR_LIBS) - -libevolution_module_calendar_la_LDFLAGS = \ - -module -avoid-version $(NO_UNDEFINED) - --include $(top_srcdir)/git.mk diff --git a/calendar/module/e-cal-shell-backend.c b/calendar/module/e-cal-shell-backend.c deleted file mode 100644 index 675a3d4fa6..0000000000 --- a/calendar/module/e-cal-shell-backend.c +++ /dev/null @@ -1,666 +0,0 @@ -/* - * e-cal-shell-backend.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-cal-shell-backend.h" - -#include -#include -#include -#include -#include -#include - -#include "e-util/e-import.h" -#include "shell/e-shell.h" -#include "shell/e-shell-backend.h" -#include "shell/e-shell-window.h" -#include "widgets/misc/e-preferences-window.h" - -#include "calendar/common/authentication.h" -#include "calendar/gui/calendar-config.h" -#include "calendar/gui/comp-util.h" -#include "calendar/gui/e-attachment-handler-calendar.h" -#include "calendar/gui/e-cal-config.h" -#include "calendar/gui/e-cal-event.h" -#include "calendar/gui/dialogs/cal-prefs-dialog.h" -#include "calendar/gui/dialogs/calendar-setup.h" -#include "calendar/gui/dialogs/event-editor.h" -#include "calendar/importers/evolution-calendar-importer.h" - -#include "e-cal-shell-migrate.h" -#include "e-cal-shell-settings.h" -#include "e-cal-shell-view.h" - -#define E_CAL_SHELL_BACKEND_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_CAL_SHELL_BACKEND, ECalShellBackendPrivate)) - -#define CONTACTS_BASE_URI "contacts://" -#define WEATHER_BASE_URI "weather://" -#define WEB_BASE_URI "webcal://" -#define PERSONAL_RELATIVE_URI "system" - -struct _ECalShellBackendPrivate { - ESourceList *source_list; -}; - -enum { - PROP_0, - PROP_SOURCE_LIST -}; - -static gpointer parent_class; -static GType cal_shell_backend_type; - -static void -cal_shell_backend_ensure_sources (EShellBackend *shell_backend) -{ - /* XXX This is basically the same algorithm across all backends. - * Maybe we could somehow integrate this into EShellBackend? */ - - ECalShellBackendPrivate *priv; - ESourceGroup *on_this_computer; - ESourceGroup *on_the_web; - ESourceGroup *contacts; - ESourceGroup *weather; - ESource *birthdays; - ESource *personal; - EShell *shell; - EShellSettings *shell_settings; - GSList *groups, *iter; - const gchar *data_dir; - const gchar *name; - gchar *base_uri; - gchar *filename; - gchar *property; - - on_this_computer = NULL; - on_the_web = NULL; - contacts = NULL; - weather = NULL; - birthdays = NULL; - personal = NULL; - - priv = E_CAL_SHELL_BACKEND_GET_PRIVATE (shell_backend); - - shell = e_shell_backend_get_shell (shell_backend); - shell_settings = e_shell_get_shell_settings (shell); - - if (!e_cal_get_sources (&priv->source_list, E_CAL_SOURCE_TYPE_EVENT, NULL)) { - g_warning ("Could not get calendar sources from GConf!"); - return; - } - - data_dir = e_shell_backend_get_data_dir (shell_backend); - filename = g_build_filename (data_dir, "local", NULL); - base_uri = g_filename_to_uri (filename, NULL, NULL); - g_free (filename); - - groups = e_source_list_peek_groups (priv->source_list); - for (iter = groups; iter != NULL; iter = iter->next) { - ESourceGroup *source_group = iter->data; - const gchar *group_base_uri; - - group_base_uri = e_source_group_peek_base_uri (source_group); - - /* Compare only "file://" part. if the user's home - * changes, we do not want to create another group. */ - if (on_this_computer == NULL && - strncmp (base_uri, group_base_uri, 7) == 0) - on_this_computer = source_group; - - else if (on_the_web == NULL && - strcmp (WEB_BASE_URI, group_base_uri) == 0) - on_the_web = source_group; - - else if (contacts == NULL && - strcmp (CONTACTS_BASE_URI, group_base_uri) == 0) - contacts = source_group; - - else if (weather == NULL && - strcmp (WEATHER_BASE_URI, group_base_uri) == 0) - weather = source_group; - } - - name = _("On This Computer"); - - if (on_this_computer != NULL) { - GSList *sources; - const gchar *group_base_uri; - - /* Force the group name to the current locale. */ - e_source_group_set_name (on_this_computer, name); - - sources = e_source_group_peek_sources (on_this_computer); - group_base_uri = e_source_group_peek_base_uri (on_this_computer); - - /* Make sure this group includes a "Personal" source. */ - for (iter = sources; iter != NULL; iter = iter->next) { - ESource *source = iter->data; - const gchar *relative_uri; - - relative_uri = e_source_peek_relative_uri (source); - if (relative_uri == NULL) - continue; - - if (strcmp (PERSONAL_RELATIVE_URI, relative_uri) != 0) - continue; - - personal = source; - break; - } - - /* Make sure we have the correct base URI. This can - * change when the user's home directory changes. */ - if (strcmp (base_uri, group_base_uri) != 0) { - e_source_group_set_base_uri ( - on_this_computer, base_uri); - - /* XXX We shouldn't need this sync call here as - * set_base_uri() results in synching to GConf, - * but that happens in an idle loop and too late - * to prevent the user from seeing a "Cannot - * Open ... because of invalid URI" error. */ - e_source_list_sync (priv->source_list, NULL); - } - - } else { - ESourceGroup *source_group; - - source_group = e_source_group_new (name, base_uri); - e_source_list_add_group (priv->source_list, source_group, -1); - g_object_unref (source_group); - } - - name = _("Personal"); - - if (personal == NULL) { - ESource *source; - GSList *selected; - gchar *primary; - - source = e_source_new (name, PERSONAL_RELATIVE_URI); - e_source_group_add_source (on_this_computer, source, -1); - g_object_unref (source); - - primary = e_shell_settings_get_string ( - shell_settings, "cal-primary-calendar"); - - selected = calendar_config_get_calendars_selected (); - - if (primary == NULL && selected == NULL) { - const gchar *uid; - - uid = e_source_peek_uid (source); - selected = g_slist_prepend (NULL, g_strdup (uid)); - - e_shell_settings_set_string ( - shell_settings, "cal-primary-calendar", uid); - calendar_config_set_calendars_selected (selected); - } - - g_slist_foreach (selected, (GFunc) g_free, NULL); - g_slist_free (selected); - g_free (primary); - } else { - /* Force the source name to the current locale. */ - e_source_set_name (personal, name); - } - - name = _("On The Web"); - - if (on_the_web == NULL) { - ESourceGroup *source_group; - - source_group = e_source_group_new (name, WEB_BASE_URI); - e_source_list_add_group (priv->source_list, source_group, -1); - g_object_unref (source_group); - } else { - /* Force the group name to the current locale. */ - e_source_group_set_name (on_the_web, name); - } - - name = _("Contacts"); - - if (contacts != NULL) { - GSList *sources; - - /* Force the group name to the current locale. */ - e_source_group_set_name (contacts, name); - - sources = e_source_group_peek_sources (contacts); - - if (sources != NULL) { - GSList *trash; - - /* There is only one source under Contacts. */ - birthdays = E_SOURCE (sources->data); - sources = g_slist_next (sources); - - /* Delete any other sources in this group. - * Earlier versions allowed you to create - * additional sources under Contacts. */ - trash = g_slist_copy (sources); - while (trash != NULL) { - ESource *source = trash->data; - e_source_group_remove_source (contacts, source); - trash = g_slist_delete_link (trash, trash); - } - - } - } else { - ESourceGroup *source_group; - - source_group = e_source_group_new (name, CONTACTS_BASE_URI); - e_source_list_add_group (priv->source_list, source_group, -1); - g_object_unref (source_group); - - /* This is now a borrowed reference. */ - contacts = source_group; - } - - /* XXX e_source_group_get_property() returns a newly-allocated - * string when it could just as easily return a const string. - * Unfortunately, fixing that would break the API. */ - property = e_source_group_get_property (contacts, "create_source"); - if (property == NULL) - e_source_group_set_property (contacts, "create_source", "no"); - g_free (property); - - name = _("Birthdays & Anniversaries"); - - if (birthdays == NULL) { - ESource *source; - const gchar *name; - - name = _("Birthdays & Anniversaries"); - source = e_source_new (name, "/"); - e_source_group_add_source (contacts, source, -1); - g_object_unref (source); - - /* This is now a borrowed reference. */ - birthdays = source; - } else { - /* Force the source name to the current locale. */ - e_source_set_name (birthdays, name); - } - - if (e_source_get_property (birthdays, "delete") == NULL) - e_source_set_property (birthdays, "delete", "no"); - - if (e_source_peek_color_spec (birthdays) == NULL) - e_source_set_color_spec (birthdays, "#DDBECE"); - - name = _("Weather"); - - if (weather == NULL) { - ESourceGroup *source_group; - - source_group = e_source_group_new (name, WEATHER_BASE_URI); - e_source_list_add_group (priv->source_list, source_group, -1); - g_object_unref (source_group); - } else { - /* Force the group name to the current locale. */ - e_source_group_set_name (weather, name); - } - - g_free (base_uri); -} - -static void -cal_shell_backend_cal_opened_cb (ECal *cal, - ECalendarStatus status, - GtkAction *action) -{ - EShell *shell; - ECalComponent *comp; - CompEditor *editor; - CompEditorFlags flags = 0; - const gchar *action_name; - gboolean all_day; - - /* FIXME Pass this in. */ - shell = e_shell_get_default (); - - /* XXX Handle errors better. */ - if (status != E_CALENDAR_STATUS_OK) - return; - - action_name = gtk_action_get_name (action); - - flags |= COMP_EDITOR_NEW_ITEM; - flags |= COMP_EDITOR_USER_ORG; - if (strcmp (action_name, "event-meeting-new") == 0) - flags |= COMP_EDITOR_MEETING; - - all_day = (strcmp (action_name, "event-all-day-new") == 0); - - editor = event_editor_new (cal, shell, flags); - comp = cal_comp_event_new_with_current_time (cal, all_day); - comp_editor_edit_comp (editor, comp); - - gtk_window_present (GTK_WINDOW (editor)); - - g_object_unref (comp); - g_object_unref (cal); -} - -static void -action_event_new_cb (GtkAction *action, - EShellWindow *shell_window) -{ - ECal *cal = NULL; - ECalSourceType source_type; - ESourceList *source_list; - EShellSettings *shell_settings; - EShell *shell; - gchar *uid; - - /* This callback is used for both appointments and meetings. */ - - source_type = E_CAL_SOURCE_TYPE_EVENT; - - shell = e_shell_window_get_shell (shell_window); - shell_settings = e_shell_get_shell_settings (shell); - - if (!e_cal_get_sources (&source_list, source_type, NULL)) { - g_warning ("Could not get calendar sources from GConf!"); - return; - } - - uid = e_shell_settings_get_string ( - shell_settings, "cal-primary-calendar"); - - if (uid != NULL) { - ESource *source; - - source = e_source_list_peek_source_by_uid (source_list, uid); - if (source != NULL) - cal = auth_new_cal_from_source (source, source_type); - g_free (uid); - } - - if (cal == NULL) - cal = auth_new_cal_from_default (source_type); - - g_return_if_fail (cal != NULL); - - g_signal_connect ( - cal, "cal-opened", - G_CALLBACK (cal_shell_backend_cal_opened_cb), action); - - e_cal_open_async (cal, FALSE); -} - -static void -action_calendar_new_cb (GtkAction *action, - EShellWindow *shell_window) -{ - calendar_setup_new_calendar (GTK_WINDOW (shell_window)); -} - -static GtkActionEntry item_entries[] = { - - { "event-new", - "appointment-new", - NC_("New", "_Appointment"), - "a", - N_("Create a new appointment"), - G_CALLBACK (action_event_new_cb) }, - - { "event-all-day-new", - "stock_new-24h-appointment", - NC_("New", "All Day A_ppointment"), - NULL, - N_("Create a new all-day appointment"), - G_CALLBACK (action_event_new_cb) }, - - { "event-meeting-new", - "stock_new-meeting", - NC_("New", "M_eeting"), - "e", - N_("Create a new meeting request"), - G_CALLBACK (action_event_new_cb) } -}; - -static GtkActionEntry source_entries[] = { - - { "calendar-new", - "x-office-calendar", - NC_("New", "Cale_ndar"), - NULL, - N_("Create a new calendar"), - G_CALLBACK (action_calendar_new_cb) } -}; - -static void -cal_shell_backend_init_hooks (void) -{ - e_plugin_hook_register_type (e_cal_config_hook_get_type ()); - e_plugin_hook_register_type (e_cal_event_hook_get_type ()); -} - -static void -cal_shell_backend_init_importers (void) -{ - EImportClass *import_class; - EImportImporter *importer; - - import_class = g_type_class_ref (e_import_get_type ()); - - importer = gnome_calendar_importer_peek (); - e_import_class_add_importer (import_class, importer, NULL, NULL); - - importer = ical_importer_peek (); - e_import_class_add_importer (import_class, importer, NULL, NULL); - - importer = vcal_importer_peek (); - e_import_class_add_importer (import_class, importer, NULL, NULL); -} - -static void -cal_shell_backend_init_preferences (EShell *shell) -{ - GtkWidget *preferences_window; - - preferences_window = e_shell_get_preferences_window (shell); - - e_preferences_window_add_page ( - E_PREFERENCES_WINDOW (preferences_window), - "calendar-and-tasks", - "preferences-calendar-and-tasks", - _("Calendar and Tasks"), - calendar_prefs_dialog_new (shell), - 600); -} - -static gboolean -cal_shell_backend_handle_uri_cb (EShellBackend *shell_backend, - const gchar *uri) -{ - /* FIXME */ - return FALSE; -} - -static void -cal_shell_backend_window_created_cb (EShellBackend *shell_backend, - GtkWindow *window) -{ - const gchar *backend_name; - - if (!E_IS_SHELL_WINDOW (window)) - return; - - backend_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name; - - e_shell_window_register_new_item_actions ( - E_SHELL_WINDOW (window), backend_name, - item_entries, G_N_ELEMENTS (item_entries)); - - e_shell_window_register_new_source_actions ( - E_SHELL_WINDOW (window), backend_name, - source_entries, G_N_ELEMENTS (source_entries)); -} - -static void -cal_shell_backend_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_SOURCE_LIST: - g_value_set_object ( - value, - e_cal_shell_backend_get_source_list ( - E_CAL_SHELL_BACKEND (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -cal_shell_backend_dispose (GObject *object) -{ - ECalShellBackendPrivate *priv; - - priv = E_CAL_SHELL_BACKEND_GET_PRIVATE (object); - - if (priv->source_list != NULL) { - g_object_unref (priv->source_list); - priv->source_list = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -cal_shell_backend_constructed (GObject *object) -{ - EShell *shell; - EShellBackend *shell_backend; - - shell_backend = E_SHELL_BACKEND (object); - shell = e_shell_backend_get_shell (shell_backend); - - cal_shell_backend_ensure_sources (shell_backend); - - g_signal_connect_swapped ( - shell, "handle-uri", - G_CALLBACK (cal_shell_backend_handle_uri_cb), - shell_backend); - - g_signal_connect_swapped ( - shell, "window-created", - G_CALLBACK (cal_shell_backend_window_created_cb), - shell_backend); - - cal_shell_backend_init_hooks (); - cal_shell_backend_init_importers (); - - /* Initialize settings before initializing preferences, - * since the preferences bind to the shell settings. */ - e_cal_shell_backend_init_settings (shell); - cal_shell_backend_init_preferences (shell); - - e_attachment_handler_calendar_get_type (); -} - -static void -cal_shell_backend_class_init (ECalShellBackendClass *class) -{ - GObjectClass *object_class; - EShellBackendClass *shell_backend_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (ECalShellBackendPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->get_property = cal_shell_backend_get_property; - object_class->dispose = cal_shell_backend_dispose; - object_class->constructed = cal_shell_backend_constructed; - - shell_backend_class = E_SHELL_BACKEND_CLASS (class); - shell_backend_class->shell_view_type = E_TYPE_CAL_SHELL_VIEW; - shell_backend_class->name = "calendar"; - shell_backend_class->aliases = ""; - shell_backend_class->schemes = "calendar"; - shell_backend_class->sort_order = 400; - shell_backend_class->start = NULL; - shell_backend_class->is_busy = NULL; - shell_backend_class->shutdown = NULL; - shell_backend_class->migrate = e_cal_shell_backend_migrate; - - g_object_class_install_property ( - object_class, - PROP_SOURCE_LIST, - g_param_spec_object ( - "source-list", - _("Source List"), - _("The registry of calendars"), - E_TYPE_SOURCE_LIST, - G_PARAM_READABLE)); -} - -static void -cal_shell_backend_init (ECalShellBackend *cal_shell_backend) -{ - cal_shell_backend->priv = - E_CAL_SHELL_BACKEND_GET_PRIVATE (cal_shell_backend); -} - -GType -e_cal_shell_backend_get_type (void) -{ - return cal_shell_backend_type; -} - -void -e_cal_shell_backend_register_type (GTypeModule *type_module) -{ - const GTypeInfo type_info = { - sizeof (ECalShellBackendClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) cal_shell_backend_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (ECalShellBackend), - 0, /* n_preallocs */ - (GInstanceInitFunc) cal_shell_backend_init, - NULL /* value_table */ - }; - - cal_shell_backend_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_BACKEND, - "ECalShellBackend", &type_info, 0); -} - -ESourceList * -e_cal_shell_backend_get_source_list (ECalShellBackend *cal_shell_backend) -{ - g_return_val_if_fail ( - E_IS_CAL_SHELL_BACKEND (cal_shell_backend), NULL); - - return cal_shell_backend->priv->source_list; -} diff --git a/calendar/module/e-cal-shell-backend.h b/calendar/module/e-cal-shell-backend.h deleted file mode 100644 index 497e200490..0000000000 --- a/calendar/module/e-cal-shell-backend.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * e-cal-shell-backend.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_CAL_SHELL_BACKEND_H -#define E_CAL_SHELL_BACKEND_H - -#include -#include - -/* Standard GObject macros */ -#define E_TYPE_CAL_SHELL_BACKEND \ - (e_cal_shell_backend_get_type ()) -#define E_CAL_SHELL_BACKEND(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_CAL_SHELL_BACKEND, ECalShellBackend)) -#define E_CAL_SHELL_BACKEND_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_CAL_SHELL_BACKEND, ECalShellBackendClass)) -#define E_IS_CAL_SHELL_BACKEND(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_CAL_SHELL_BACKEND)) -#define E_IS_CAL_SHELL_BACKEND_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_CAL_SHELL_BACKEND)) -#define E_CAL_SHELL_BACKEND_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_CAL_SHELL_BACKEND, ECalShellBackendClass)) - -G_BEGIN_DECLS - -typedef struct _ECalShellBackend ECalShellBackend; -typedef struct _ECalShellBackendClass ECalShellBackendClass; -typedef struct _ECalShellBackendPrivate ECalShellBackendPrivate; - -struct _ECalShellBackend { - EShellBackend parent; - ECalShellBackendPrivate *priv; -}; - -struct _ECalShellBackendClass { - EShellBackendClass parent_class; -}; - -GType e_cal_shell_backend_get_type (void); -void e_cal_shell_backend_register_type - (GTypeModule *type_module); -ESourceList * e_cal_shell_backend_get_source_list - (ECalShellBackend *cal_shell_backend); - -G_END_DECLS - -#endif /* E_CAL_SHELL_BACKEND_H */ diff --git a/calendar/module/e-cal-shell-content.c b/calendar/module/e-cal-shell-content.c deleted file mode 100644 index 6afb40dce7..0000000000 --- a/calendar/module/e-cal-shell-content.c +++ /dev/null @@ -1,827 +0,0 @@ -/* - * e-cal-shell-content.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-cal-shell-content.h" - -#include -#include - -#include "e-util/gconf-bridge.h" - -#include "calendar/gui/calendar-config.h" -#include "calendar/gui/e-cal-list-view-config.h" -#include "calendar/gui/e-cal-model-calendar.h" -#include "calendar/gui/e-calendar-table.h" -#include "calendar/gui/e-calendar-table-config.h" -#include "calendar/gui/e-day-view-config.h" -#include "calendar/gui/e-memo-table-config.h" -#include "calendar/gui/e-week-view-config.h" - -#include "widgets/menus/gal-view-etable.h" - -#define E_CAL_SHELL_CONTENT_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_CAL_SHELL_CONTENT, ECalShellContentPrivate)) - -struct _ECalShellContentPrivate { - GtkWidget *hpaned; - GtkWidget *notebook; - GtkWidget *vpaned; - - GtkWidget *day_view; - GtkWidget *work_week_view; - GtkWidget *week_view; - GtkWidget *month_view; - GtkWidget *list_view; - GtkWidget *task_table; - GtkWidget *memo_table; - - EDayViewConfig *day_view_config; - EDayViewConfig *work_week_view_config; - EWeekViewConfig *week_view_config; - EWeekViewConfig *month_view_config; - ECalListViewConfig *list_view_config; - ECalendarTableConfig *task_table_config; - EMemoTableConfig *memo_table_config; - - GalViewInstance *view_instance; - - guint paned_binding_id; -}; - -enum { - PROP_0 -}; - -/* Used to indicate who has the focus within the calendar view. */ -typedef enum { - FOCUS_CALENDAR, - FOCUS_MEMO_TABLE, - FOCUS_TASK_TABLE, - FOCUS_OTHER -} FocusLocation; - -static gpointer parent_class; -static GType cal_shell_content_type; - -static void -cal_shell_content_display_view_cb (ECalShellContent *cal_shell_content, - GalView *gal_view) -{ - /* FIXME */ -} - -static void -cal_shell_content_notify_view_id_cb (ECalShellContent *cal_shell_content) -{ - EShellContent *shell_content; - EShellView *shell_view; - GConfBridge *bridge; - GtkWidget *paned; - guint binding_id; - const gchar *key; - const gchar *view_id; - - bridge = gconf_bridge_get (); - paned = cal_shell_content->priv->hpaned; - binding_id = cal_shell_content->priv->paned_binding_id; - - shell_content = E_SHELL_CONTENT (cal_shell_content); - shell_view = e_shell_content_get_shell_view (shell_content); - view_id = e_shell_view_get_view_id (shell_view); - - if (binding_id > 0) - gconf_bridge_unbind (bridge, binding_id); - - if (view_id != NULL && strcmp (view_id, "Month_View") == 0) - key = "/apps/evolution/calendar/display/month_hpane_position"; - else - key = "/apps/evolution/calendar/display/hpane_position"; - - binding_id = gconf_bridge_bind_property_delayed ( - bridge, key, G_OBJECT (paned), "position"); - - cal_shell_content->priv->paned_binding_id = binding_id; -} - -static FocusLocation -cal_shell_content_get_focus_location (ECalShellContent *cal_shell_content) -{ - return FOCUS_OTHER; -#if 0 /* TEMPORARILY DISABLED */ - GtkWidget *widget; - GnomeCalendar *calendar; - ECalendarTable *task_table; - EMemoTable *memo_table; - ETable *table; - ECalendarView *calendar_view; - - calendar = GNOME_CALENDAR (cal_shell_content->priv->calendar); - widget = gnome_calendar_get_current_view_widget (calendar); - - memo_table = E_MEMO_TABLE (cal_shell_content->priv->memo_table); - task_table = E_CALENDAR_TABLE (cal_shell_content->priv->task_table); - - table = e_memo_table_get_table (memo_table); - if (GTK_WIDGET_HAS_FOCUS (table->table_canvas)) - return FOCUS_MEMO_TABLE; - - table = e_calendar_table_get_table (task_table); - if (GTK_WIDGET_HAS_FOCUS (table->table_canvas)) - return FOCUS_TASK_TABLE; - - if (E_IS_DAY_VIEW (widget)) { - EDayView *view = E_DAY_VIEW (widget); - - if (GTK_WIDGET_HAS_FOCUS (view->top_canvas)) - return FOCUS_CALENDAR; - - if (GNOME_CANVAS (view->top_canvas)->focused_item != NULL) - return FOCUS_CALENDAR; - - if (GTK_WIDGET_HAS_FOCUS (view->main_canvas)) - return FOCUS_CALENDAR; - - if (GNOME_CANVAS (view->main_canvas)->focused_item != NULL) - return FOCUS_CALENDAR; - - } else if (E_IS_WEEK_VIEW (widget)) { - EWeekView *view = E_WEEK_VIEW (widget); - - if (GTK_WIDGET_HAS_FOCUS (view->main_canvas)) - return FOCUS_CALENDAR; - - if (GNOME_CANVAS (view->main_canvas)->focused_item != NULL) - return FOCUS_CALENDAR; - - } else if (E_IS_CAL_LIST_VIEW (widget)) { - ECalListView *view = E_CAL_LIST_VIEW (widget); - - table = e_table_scrolled_get_table (view->table_scrolled); - if (GTK_WIDGET_HAS_FOCUS (table)) - return FOCUS_CALENDAR; - } - - return FOCUS_OTHER; -#endif -} - -static void -cal_shell_content_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -cal_shell_content_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -cal_shell_content_dispose (GObject *object) -{ - ECalShellContentPrivate *priv; - - priv = E_CAL_SHELL_CONTENT_GET_PRIVATE (object); - - if (priv->hpaned != NULL) { - g_object_unref (priv->hpaned); - priv->hpaned = NULL; - } - - if (priv->notebook != NULL) { - g_object_unref (priv->notebook); - priv->notebook = NULL; - } - - if (priv->vpaned != NULL) { - g_object_unref (priv->vpaned); - priv->vpaned = NULL; - } - - if (priv->day_view != NULL) { - g_object_unref (priv->day_view); - priv->day_view = NULL; - } - - if (priv->work_week_view != NULL) { - g_object_unref (priv->work_week_view); - priv->work_week_view = NULL; - } - - if (priv->week_view != NULL) { - g_object_unref (priv->week_view); - priv->week_view = NULL; - } - - if (priv->month_view != NULL) { - g_object_unref (priv->month_view); - priv->month_view = NULL; - } - - if (priv->list_view != NULL) { - g_object_unref (priv->list_view); - priv->list_view = NULL; - } - - if (priv->task_table != NULL) { - g_object_unref (priv->task_table); - priv->task_table = NULL; - } - - if (priv->memo_table != NULL) { - g_object_unref (priv->memo_table); - priv->memo_table = NULL; - } - - if (priv->day_view_config != NULL) { - g_object_unref (priv->day_view_config); - priv->day_view_config = NULL; - } - - if (priv->work_week_view_config != NULL) { - g_object_unref (priv->work_week_view_config); - priv->work_week_view_config = NULL; - } - - if (priv->week_view_config != NULL) { - g_object_unref (priv->week_view_config); - priv->week_view_config = NULL; - } - - if (priv->month_view_config != NULL) { - g_object_unref (priv->month_view_config); - priv->month_view_config = NULL; - } - - if (priv->list_view_config != NULL) { - g_object_unref (priv->list_view_config); - priv->list_view_config = NULL; - } - - if (priv->task_table_config != NULL) { - g_object_unref (priv->task_table_config); - priv->task_table_config = NULL; - } - - if (priv->memo_table_config != NULL) { - g_object_unref (priv->memo_table_config); - priv->memo_table_config = NULL; - } - - if (priv->view_instance != NULL) { - g_object_unref (priv->view_instance); - priv->view_instance = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -cal_shell_content_finalize (GObject *object) -{ - ECalShellContentPrivate *priv; - - priv = E_CAL_SHELL_CONTENT_GET_PRIVATE (object); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -cal_shell_content_constructed (GObject *object) -{ - ECalShellContentPrivate *priv; - ECalModelCalendar *cal_model; - ECalModel *memo_model; - ECalModel *task_model; - EShellContent *shell_content; - EShellBackend *shell_backend; - EShellView *shell_view; - EShellWindow *shell_window; - EShellContent *foreign_content; - EShellView *foreign_view; - GalViewInstance *view_instance; - GConfBridge *bridge; - GtkWidget *container; - GtkWidget *widget; - const gchar *config_dir; - const gchar *key; - gchar *filename; - gchar *markup; - gint page_num; - - priv = E_CAL_SHELL_CONTENT_GET_PRIVATE (object); - - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (parent_class)->constructed (object); - - shell_content = E_SHELL_CONTENT (object); - shell_view = e_shell_content_get_shell_view (shell_content); - shell_window = e_shell_view_get_shell_window (shell_view); - - shell_backend = e_shell_view_get_shell_backend (shell_view); - config_dir = e_shell_backend_get_config_dir (shell_backend); - - /* Calendar model for the views. */ - cal_model = e_cal_model_calendar_new (); - e_cal_model_set_flags ( - E_CAL_MODEL (cal_model), - E_CAL_MODEL_FLAGS_EXPAND_RECURRENCES); - - /* We borrow the memopad and taskpad models from the memo - * and task views, loading the views if necessary. */ - - foreign_view = e_shell_window_get_shell_view (shell_window, "memos"); - foreign_content = e_shell_view_get_shell_content (foreign_view); - g_object_get (foreign_content, "model", &memo_model, NULL); - - foreign_view = e_shell_window_get_shell_view (shell_window, "tasks"); - foreign_content = e_shell_view_get_shell_content (foreign_view); - g_object_get (foreign_content, "model", &task_model, NULL); - - /* Build content widgets. */ - - container = GTK_WIDGET (object); - - /* FIXME Need to deal with saving and restoring the position. - * Month view has its own position. */ - widget = gtk_hpaned_new (); - gtk_container_add (GTK_CONTAINER (container), widget); - priv->hpaned = g_object_ref (widget); - gtk_widget_show (widget); - - container = priv->hpaned; - - widget = gtk_notebook_new (); - gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE); - gtk_notebook_set_show_border (GTK_NOTEBOOK (widget), FALSE); - gtk_paned_pack1 (GTK_PANED (container), widget, FALSE, TRUE); - priv->notebook = g_object_ref (widget); - gtk_widget_show (widget); - - /* FIXME Need to deal with saving and restoring the position. - * Month view has its own position. */ - widget = gtk_vpaned_new (); - gtk_paned_pack2 (GTK_PANED (container), widget, TRUE, TRUE); - priv->vpaned = g_object_ref (widget); - gtk_widget_show (widget); - - container = priv->notebook; - - /* Add views in the order defined by GnomeCalendarViewType, such - * that the notebook page number corresponds to the view type. - * The assertions below ensure that stays true. */ - -#if 0 /* Not so fast... get the memo/task pads working first. */ - /* FIXME Need to establish a calendar and timezone first. */ - widget = e_day_view_new (E_CAL_MODEL (cal_model)); - e_calendar_view_set_calendar ( - E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); - e_calendar_view_set_timezone ( - E_CALENDAR_VIEW (widget), priv->timezone); - page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); - gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); - g_return_if_fail (page_num == GNOME_CAL_DAY_VIEW); - priv->day_view = g_object_ref (widget); - gtk_widget_show (widget); - - /* FIXME Need to establish a calendar and timezone first. */ - widget = e_day_view_new (E_CAL_MODEL (cal_model)); - e_day_view_set_work_week_view (E_DAY_VIEW (widget), TRUE); - e_day_view_set_days_shown (E_DAY_VIEW (widget), 5); - e_calendar_view_set_calendar ( - E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); - e_calendar_view_set_timezone ( - E_CALENDAR_VIEW (widget), priv->timezone); - page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); - gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); - g_return_if_fail (page_num == GNOME_CAL_WORK_WEEK_VIEW); - priv->work_week_view = g_object_ref (widget); - gtk_widget_show (widget); - - /* FIXME Need to establish a calendar and timezone first. */ - widget = e_week_view_new (E_CAL_MODEL (cal_model)); - e_calendar_view_set_calendar ( - E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); - e_calendar_view_set_timezone ( - E_CALENDAR_VIEW (widget), priv->timezone); - page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); - gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); - g_return_if_fail (page_num == GNOME_CAL_WEEK_VIEW); - priv->week_view = g_object_ref (widget); - gtk_widget_show (widget); - - /* FIXME Need to establish a calendar and timezone first. */ - widget = e_week_view_new (E_CAL_MODEL (cal_model)); - e_week_view_set_multi_week_view (E_WEEK_VIEW (widget), TRUE); - e_week_view_set_weeks_shown (E_WEEK_VIEW (widget), 6); - e_calendar_view_set_calendar ( - E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); - e_calendar_view_set_timezone ( - E_CALENDAR_VIEW (widget), priv->timezone); - page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); - gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); - g_return_if_fail (page_num == GNOME_CAL_MONTH_VIEW); - priv->month_view = g_object_ref (widget); - gtk_widget_show (widget); - - /* FIXME Need to establish a calendar and timezone first. */ - widget = e_cal_list_view_new (E_CAL_MODEL (cal_model)); - e_calendar_view_set_calendar ( - E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); - e_calendar_view_set_timezone ( - E_CALENDAR_VIEW (widget), priv->timezone); - page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); - gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); - g_return_if_fail (page_num == GNOME_CAL_LIST_VIEW); - priv->list_view = g_object_ref (widget); - gtk_widget_show (widget); -#endif - - container = priv->vpaned; - - widget = gtk_vbox_new (FALSE, 0); - gtk_paned_pack1 (GTK_PANED (container), widget, FALSE, FALSE); - gtk_widget_show (widget); - - container = widget; - - widget = gtk_hseparator_new (); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, TRUE, 0); - gtk_widget_show (widget); - - widget = gtk_label_new (NULL); - markup = g_strdup_printf ("%s", _("Tasks")); - gtk_label_set_markup (GTK_LABEL (widget), markup); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, TRUE, 0); - gtk_widget_show (widget); - g_free (markup); - - widget = e_calendar_table_new (shell_view, task_model); - gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); - priv->task_table = g_object_ref (widget); - gtk_widget_show (widget); - - filename = g_build_filename (config_dir, "TaskPad", NULL); - e_calendar_table_load_state (E_CALENDAR_TABLE (widget), filename); - g_free (filename); - - container = priv->vpaned; - - widget = gtk_vbox_new (FALSE, 0); - gtk_paned_pack2 (GTK_PANED (container), widget, TRUE, FALSE); - gtk_widget_show (widget); - - container = widget; - - widget = gtk_label_new (NULL); - markup = g_strdup_printf ("%s", _("Memos")); - gtk_label_set_markup (GTK_LABEL (widget), markup); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, TRUE, 0); - gtk_widget_show (widget); - g_free (markup); - - widget = e_memo_table_new (shell_view, memo_model); - gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); - priv->memo_table = g_object_ref (widget); - gtk_widget_show (widget); - - filename = g_build_filename (config_dir, "MemoPad", NULL); - e_memo_table_load_state (E_MEMO_TABLE (widget), filename); - g_free (filename); - - /* Configuration managers for views and tables. */ - priv->day_view_config = e_day_view_config_new ( - E_DAY_VIEW (priv->day_view)); - priv->work_week_view_config = e_day_view_config_new ( - E_DAY_VIEW (priv->work_week_view)); - priv->week_view_config = e_week_view_config_new ( - E_WEEK_VIEW (priv->week_view)); - priv->month_view_config = e_week_view_config_new ( - E_WEEK_VIEW (priv->month_view)); - priv->list_view_config = e_cal_list_view_config_new ( - E_CAL_LIST_VIEW (priv->list_view)); - priv->task_table_config = e_calendar_table_config_new ( - E_CALENDAR_TABLE (priv->task_table)); - priv->memo_table_config = e_memo_table_config_new ( - E_MEMO_TABLE (priv->memo_table)); - - /* Load the view instance. */ - - view_instance = e_shell_view_new_view_instance (shell_view, NULL); - g_signal_connect_swapped ( - view_instance, "display-view", - G_CALLBACK (cal_shell_content_display_view_cb), - object); - gal_view_instance_load (view_instance); - priv->view_instance = view_instance; - - g_signal_connect_swapped ( - shell_view, "notify::view-id", - G_CALLBACK (cal_shell_content_notify_view_id_cb), - object); - - /* Bind GObject properties to GConf keys. */ - - bridge = gconf_bridge_get (); - - object = G_OBJECT (priv->vpaned); - key = "/apps/evolution/calendar/display/vpane_position"; - gconf_bridge_bind_property_delayed (bridge, key, object, "position"); - - g_object_unref (memo_model); - g_object_unref (task_model); -} - -static void -cal_shell_content_class_init (ECalShellContentClass *class) -{ - GObjectClass *object_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (ECalShellContentPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->set_property = cal_shell_content_set_property; - object_class->get_property = cal_shell_content_get_property; - object_class->dispose = cal_shell_content_dispose; - object_class->finalize = cal_shell_content_finalize; - object_class->constructed = cal_shell_content_constructed; -} - -static void -cal_shell_content_init (ECalShellContent *cal_shell_content) -{ - cal_shell_content->priv = - E_CAL_SHELL_CONTENT_GET_PRIVATE (cal_shell_content); - - /* Postpone widget construction until we have a shell view. */ -} - -GType -e_cal_shell_content_get_type (void) -{ - return cal_shell_content_type; -} - -void -e_cal_shell_content_register_type (GTypeModule *type_module) -{ - static const GTypeInfo type_info = { - sizeof (ECalShellContentClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) cal_shell_content_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (ECalShellContent), - 0, /* n_preallocs */ - (GInstanceInitFunc) cal_shell_content_init, - NULL /* value_table */ - }; - - cal_shell_content_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_CONTENT, - "ECalShellContent", &type_info, 0); -} - -GtkWidget * -e_cal_shell_content_new (EShellView *shell_view) -{ - g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - - return g_object_new ( - E_TYPE_CAL_SHELL_CONTENT, - "shell-view", shell_view, NULL); -} - -GnomeCalendar * -e_cal_shell_content_get_calendar (ECalShellContent *cal_shell_content) -{ - g_return_val_if_fail ( - E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL); - - /* FIXME */ - /*return GNOME_CALENDAR (cal_shell_content->priv->calendar);*/ - return NULL; -} - -EMemoTable * -e_cal_shell_content_get_memo_table (ECalShellContent *cal_shell_content) -{ - g_return_val_if_fail ( - E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL); - - return E_MEMO_TABLE (cal_shell_content->priv->memo_table); -} - -ECalendarTable * -e_cal_shell_content_get_task_table (ECalShellContent *cal_shell_content) -{ - g_return_val_if_fail ( - E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL); - - return E_CALENDAR_TABLE (cal_shell_content->priv->task_table); -} - -icaltimezone * -e_cal_shell_content_get_timezone (ECalShellContent *cal_shell_content) -{ - g_return_val_if_fail ( - E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL); - - /* FIXME */ - /*return cal_shell_content->priv->timezone;*/ - return NULL; -} - -GalViewInstance * -e_cal_shell_content_get_view_instance (ECalShellContent *cal_shell_content) -{ - g_return_val_if_fail ( - E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL); - - return cal_shell_content->priv->view_instance; -} - -void -e_cal_shell_content_copy_clipboard (ECalShellContent *cal_shell_content) -{ -#if 0 - GnomeCalendar *calendar; - EMemoTable *memo_table; - ECalendarTable *task_table; - - g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); - - calendar = e_cal_shell_content_get_calendar (cal_shell_content); - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - switch (cal_shell_content_get_focus_location (cal_shell_content)) { - case FOCUS_CALENDAR: - gnome_calendar_copy_clipboard (calendar); - break; - - case FOCUS_MEMO_TABLE: - e_memo_table_copy_clipboard (memo_table); - break; - - case FOCUS_TASK_TABLE: - e_calendar_table_copy_clipboard (task_table); - break; - - default: - g_return_if_reached (); - } -#endif -} - -void -e_cal_shell_content_cut_clipboard (ECalShellContent *cal_shell_content) -{ -#if 0 - GnomeCalendar *calendar; - EMemoTable *memo_table; - ECalendarTable *task_table; - - g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); - - calendar = e_cal_shell_content_get_calendar (cal_shell_content); - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - switch (cal_shell_content_get_focus_location (cal_shell_content)) { - case FOCUS_CALENDAR: - gnome_calendar_cut_clipboard (calendar); - break; - - case FOCUS_MEMO_TABLE: - e_memo_table_copy_clipboard (memo_table); - break; - - case FOCUS_TASK_TABLE: - e_calendar_table_copy_clipboard (task_table); - break; - - default: - g_return_if_reached (); - } -#endif -} - -void -e_cal_shell_content_paste_clipboard (ECalShellContent *cal_shell_content) -{ -#if 0 - GnomeCalendar *calendar; - EMemoTable *memo_table; - ECalendarTable *task_table; - - g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); - - calendar = e_cal_shell_content_get_calendar (cal_shell_content); - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - switch (cal_shell_content_get_focus_location (cal_shell_content)) { - case FOCUS_CALENDAR: - gnome_calendar_paste_clipboard (calendar); - break; - - case FOCUS_MEMO_TABLE: - e_memo_table_copy_clipboard (memo_table); - break; - - case FOCUS_TASK_TABLE: - e_calendar_table_copy_clipboard (task_table); - break; - - default: - g_return_if_reached (); - } -#endif -} - -void -e_cal_shell_content_delete_selection (ECalShellContent *cal_shell_content) -{ -#if 0 - GnomeCalendar *calendar; - EMemoTable *memo_table; - ECalendarTable *task_table; - - g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); - - calendar = e_cal_shell_content_get_calendar (cal_shell_content); - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - switch (cal_shell_content_get_focus_location (cal_shell_content)) { - case FOCUS_CALENDAR: - gnome_calendar_delete_selection (calendar); - break; - - case FOCUS_MEMO_TABLE: - e_memo_table_delete_selected (memo_table); - break; - - case FOCUS_TASK_TABLE: - e_calendar_table_delete_selected (task_table); - break; - - default: - g_return_if_reached (); - } -#endif -} - -void -e_cal_shell_content_delete_selected_occurrence (ECalShellContent *cal_shell_content) -{ -#if 0 - GnomeCalendar *calendar; - FocusLocation focus; - - g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); - - focus = cal_shell_content_get_focus_location (cal_shell_content); - calendar = e_cal_shell_content_get_calendar (cal_shell_content); - - if (focus == FOCUS_CALENDAR) - gnome_calendar_delete_selected_occurrence (calendar); -#endif -} diff --git a/calendar/module/e-cal-shell-content.h b/calendar/module/e-cal-shell-content.h deleted file mode 100644 index 44e13f733c..0000000000 --- a/calendar/module/e-cal-shell-content.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * e-cal-shell-content.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_CAL_SHELL_CONTENT_H -#define E_CAL_SHELL_CONTENT_H - -#include -#include - -#include -#include -#include - -/* Standard GObject macros */ -#define E_TYPE_CAL_SHELL_CONTENT \ - (e_cal_shell_content_get_type ()) -#define E_CAL_SHELL_CONTENT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_CAL_SHELL_CONTENT, ECalShellContent)) -#define E_CAL_SHELL_CONTENT_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_CAL_SHELL_CONTENT, ECalShellContentClass)) -#define E_IS_CAL_SHELL_CONTENT(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_CAL_SHELL_CONTENT)) -#define E_IS_CAL_SHELL_CONTENT_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_CAL_SHELL_CONTENT)) -#define E_CAL_SHELL_CONTENT_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_CAL_SHELL_CONTENT, ECalShellContentClass)) - -G_BEGIN_DECLS - -typedef struct _ECalShellContent ECalShellContent; -typedef struct _ECalShellContentClass ECalShellContentClass; -typedef struct _ECalShellContentPrivate ECalShellContentPrivate; - -enum { - E_CAL_SHELL_CONTENT_SELECTION_SINGLE = 1 << 0, - E_CAL_SHELL_CONTENT_SELECTION_MULTIPLE = 1 << 1, - E_CAL_SHELL_CONTENT_SELECTION_IS_ASSIGNABLE = 1 << 2, - E_CAL_SHELL_CONTENT_SELECTION_IS_COMPLETE = 1 << 3, - E_CAL_SHELL_CONTENT_SELECTION_IS_EDITABLE = 1 << 4, - E_CAL_SHELL_CONTENT_SELECTION_IS_MEETING = 1 << 5, - E_CAL_SHELL_CONTENT_SELECTION_IS_ORGANIZER = 1 << 6, - E_CAL_SHELL_CONTENT_SELECTION_IS_RECURRING = 1 << 7, - E_CAL_SHELL_CONTENT_SELECTION_CAN_ACCEPT = 1 << 8, - E_CAL_SHELL_CONTENT_SELECTION_CAN_DELEGATE = 1 << 9, - E_CAL_SHELL_CONTENT_SELECTION_CAN_SAVE = 1 << 10 -}; - -struct _ECalShellContent { - EShellContent parent; - ECalShellContentPrivate *priv; -}; - -struct _ECalShellContentClass { - EShellContentClass parent_class; -}; - -GType e_cal_shell_content_get_type (void); -void e_cal_shell_content_register_type - (GTypeModule *type_module); -GtkWidget * e_cal_shell_content_new (EShellView *shell_view); -GnomeCalendar * e_cal_shell_content_get_calendar - (ECalShellContent *cal_shell_content); -EMemoTable * e_cal_shell_content_get_memo_table - (ECalShellContent *cal_shell_content); -ECalendarTable *e_cal_shell_content_get_task_table - (ECalShellContent *cal_shell_content); -icaltimezone * e_cal_shell_content_get_timezone - (ECalShellContent *cal_shell_content); -GalViewInstance * - e_cal_shell_content_get_view_instance - (ECalShellContent *cal_shell_content); -void e_cal_shell_content_copy_clipboard - (ECalShellContent *cal_shell_content); -void e_cal_shell_content_cut_clipboard - (ECalShellContent *cal_shell_content); -void e_cal_shell_content_paste_clipboard - (ECalShellContent *cal_shell_content); -void e_cal_shell_content_delete_selection - (ECalShellContent *cal_shell_content); -void e_cal_shell_content_delete_selected_occurrence - (ECalShellContent *cal_shell_content); - -G_END_DECLS - -#endif /* E_CAL_SHELL_CONTENT_H */ diff --git a/calendar/module/e-cal-shell-migrate.c b/calendar/module/e-cal-shell-migrate.c deleted file mode 100644 index 9887a5332c..0000000000 --- a/calendar/module/e-cal-shell-migrate.c +++ /dev/null @@ -1,796 +0,0 @@ -/* - * e-cal-shell-backend-migrate.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-cal-shell-migrate.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "e-util/e-bconf-map.h" -#include "e-util/e-folder-map.h" -#include "e-util/e-util-private.h" -#include "calendar/gui/calendar-config.h" -#include "calendar/gui/calendar-config-keys.h" -#include "calendar/gui/e-cal-event.h" -#include "shell/e-shell.h" - -#define WEBCAL_BASE_URI "webcal://" -#define CONTACTS_BASE_URI "contacts://" -#define BAD_CONTACTS_BASE_URI "contact://" -#define PERSONAL_RELATIVE_URI "system" - -static e_gconf_map_t calendar_display_map[] = { - /* /Calendar/Display */ - { "Timezone", "calendar/display/timezone", E_GCONF_MAP_STRING }, - { "Use24HourFormat", "calendar/display/use_24hour_format", E_GCONF_MAP_BOOL }, - { "WeekStartDay", "calendar/display/week_start_day", E_GCONF_MAP_INT }, - { "DayStartHour", "calendar/display/day_start_hour", E_GCONF_MAP_INT }, - { "DayStartMinute", "calendar/display/day_start_minute", E_GCONF_MAP_INT }, - { "DayEndHour", "calendar/display/day_end_hour", E_GCONF_MAP_INT }, - { "DayEndMinute", "calendar/display/day_end_minute", E_GCONF_MAP_INT }, - { "TimeDivisions", "calendar/display/time_divisions", E_GCONF_MAP_INT }, - { "View", "calendar/display/default_view", E_GCONF_MAP_INT }, - { "HPanePosition", "calendar/display/hpane_position", E_GCONF_MAP_FLOAT }, - { "VPanePosition", "calendar/display/vpane_position", E_GCONF_MAP_FLOAT }, - { "MonthHPanePosition", "calendar/display/month_hpane_position", E_GCONF_MAP_FLOAT }, - { "MonthVPanePosition", "calendar/display/month_vpane_position", E_GCONF_MAP_FLOAT }, - { "CompressWeekend", "calendar/display/compress_weekend", E_GCONF_MAP_BOOL }, - { "ShowEventEndTime", "calendar/display/show_event_end", E_GCONF_MAP_BOOL }, - { "WorkingDays", "calendar/display/working_days", E_GCONF_MAP_INT }, - { NULL }, -}; - -static e_gconf_map_t calendar_other_map[] = { - /* /Calendar/Other */ - { "ConfirmDelete", "calendar/prompts/confirm_delete", E_GCONF_MAP_BOOL }, - { "ConfirmExpunge", "calendar/prompts/confirm_purge", E_GCONF_MAP_BOOL }, - { "UseDefaultReminder", "calendar/other/use_default_reminder", E_GCONF_MAP_BOOL }, - { "DefaultReminderInterval", "calendar/other/default_reminder_interval", E_GCONF_MAP_INT }, - { "DefaultReminderUnits", "calendar/other/default_reminder_units", E_GCONF_MAP_STRING }, - { NULL }, -}; - -static e_gconf_map_t calendar_datenavigator_map[] = { - /* /Calendar/DateNavigator */ - { "ShowWeekNumbers", "calendar/date_navigator/show_week_numbers", E_GCONF_MAP_BOOL }, - { NULL }, -}; - -static e_gconf_map_t calendar_alarmnotify_map[] = { - /* /Calendar/AlarmNotify */ - { "LastNotificationTime", "calendar/notify/last_notification_time", E_GCONF_MAP_INT }, - { "CalendarToLoad%i", "calendar/notify/calendars", E_GCONF_MAP_STRING|E_GCONF_MAP_LIST }, - { "BlessedProgram%i", "calendar/notify/programs", E_GCONF_MAP_STRING|E_GCONF_MAP_LIST }, - { NULL }, -}; - -static e_gconf_map_list_t calendar_remap_list[] = { - - { "/Calendar/Display", calendar_display_map }, - { "/Calendar/Other/Map", calendar_other_map }, - { "/Calendar/DateNavigator", calendar_datenavigator_map }, - { "/Calendar/AlarmNotify", calendar_alarmnotify_map }, - - { NULL }, -}; - -static GtkWidget *window; -static GtkLabel *label; -static GtkProgressBar *progress; - -#ifndef G_OS_WIN32 - -/* No previous versions have been available on Win32, so don't - * bother with upgrade support from 1.x on Win32. - */ - -static void -setup_progress_dialog (void) -{ - GtkWidget *vbox, *hbox, *w; - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title ((GtkWindow *) window, _("Migrating...")); - gtk_window_set_modal ((GtkWindow *) window, TRUE); - gtk_container_set_border_width ((GtkContainer *) window, 6); - - vbox = gtk_vbox_new (FALSE, 6); - gtk_widget_show (vbox); - gtk_container_add ((GtkContainer *) window, vbox); - - w = gtk_label_new (_("The location and hierarchy of the Evolution calendar " - "folders has changed since Evolution 1.x.\n\nPlease be " - "patient while Evolution migrates your folders...")); - - gtk_label_set_line_wrap ((GtkLabel *) w, TRUE); - gtk_widget_show (w); - gtk_box_pack_start_defaults ((GtkBox *) vbox, w); - - hbox = gtk_hbox_new (FALSE, 6); - gtk_widget_show (hbox); - gtk_box_pack_start_defaults ((GtkBox *) vbox, hbox); - - label = (GtkLabel *) gtk_label_new (""); - gtk_widget_show ((GtkWidget *) label); - gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) label); - - progress = (GtkProgressBar *) gtk_progress_bar_new (); - gtk_widget_show ((GtkWidget *) progress); - gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) progress); - - gtk_widget_show (window); -} - -static void -dialog_close (void) -{ - gtk_widget_destroy ((GtkWidget *) window); -} - -static void -dialog_set_folder_name (const gchar *folder_name) -{ - gchar *text; - - text = g_strdup_printf (_("Migrating '%s':"), folder_name); - gtk_label_set_text (label, text); - g_free (text); - - gtk_progress_bar_set_fraction (progress, 0.0); - - while (gtk_events_pending ()) - gtk_main_iteration (); -} - -static void -dialog_set_progress (double percent) -{ - gchar text[5]; - - snprintf (text, sizeof (text), "%d%%", (gint) (percent * 100.0f)); - - gtk_progress_bar_set_fraction (progress, percent); - gtk_progress_bar_set_text (progress, text); - - while (gtk_events_pending ()) - gtk_main_iteration (); -} - -static gboolean -check_for_conflict (ESourceGroup *group, gchar *name) -{ - GSList *sources; - GSList *s; - - sources = e_source_group_peek_sources (group); - - for (s = sources; s; s = s->next) { - ESource *source = E_SOURCE (s->data); - - if (!strcmp (e_source_peek_name (source), name)) - return TRUE; - } - - return FALSE; -} - -static gchar * -get_source_name (ESourceGroup *group, const gchar *path) -{ - gchar **p = g_strsplit (path, "/", 0); - gint i, j, starting_index; - gint num_elements; - gboolean conflict; - GString *s = g_string_new (NULL); - - for (i = 0; p[i]; i ++); - - num_elements = i; - i--; - - /* p[i] is now the last path element */ - - /* check if it conflicts */ - starting_index = i; - do { - for (j = starting_index; j < num_elements; j += 2) { - if (j != starting_index) - g_string_append_c (s, '_'); - g_string_append (s, p[j]); - } - - conflict = check_for_conflict (group, s->str); - - - /* if there was a conflict back up 2 levels (skipping the /subfolder/ element) */ - if (conflict) - starting_index -= 2; - - /* we always break out if we can't go any further, - regardless of whether or not we conflict. */ - if (starting_index < 0) - break; - - } while (conflict); - g_strfreev (p); - - return g_string_free (s, FALSE); -} - -static gboolean -migrate_ical (ECal *old_ecal, ECal *new_ecal) -{ - GList *l, *objects; - gint num_added = 0; - gint num_objects; - gboolean retval = TRUE; - - /* both ecals are loaded, start the actual migration */ - if (!e_cal_get_object_list (old_ecal, "#t", &objects, NULL)) - return FALSE; - - num_objects = g_list_length (objects); - for (l = objects; l; l = l->next) { - icalcomponent *ical_comp = l->data; - GError *error = NULL; - - if (!e_cal_create_object (new_ecal, ical_comp, NULL, &error)) { - g_warning ("Migration of object failed: %s", error->message); - retval = FALSE; - } - - g_clear_error (&error); - - num_added ++; - dialog_set_progress ((double)num_added / num_objects); - } - - g_list_foreach (objects, (GFunc) icalcomponent_free, NULL); - g_list_free (objects); - - return retval; -} - -static gboolean -migrate_ical_folder_to_source (gchar *old_path, ESource *new_source, ECalSourceType type) -{ - ECal *old_ecal = NULL, *new_ecal = NULL; - ESource *old_source; - ESourceGroup *group; - gchar *old_uri = g_strdup_printf ("file://%s", old_path); - GError *error = NULL; - gboolean retval = FALSE; - - group = e_source_group_new ("", old_uri); - old_source = e_source_new ("", ""); - e_source_group_add_source (group, old_source, -1); - - dialog_set_folder_name (e_source_peek_name (new_source)); - - if (!(old_ecal = e_cal_new (old_source, type))) { - g_warning ("could not find a backend for '%s'", e_source_get_uri (old_source)); - goto finish; - } - if (!e_cal_open (old_ecal, FALSE, &error)) { - g_warning ("failed to load source ecal for migration: '%s' (%s)", error->message, - e_source_get_uri (old_source)); - goto finish; - } - - if (!(new_ecal = e_cal_new (new_source, type))) { - g_warning ("could not find a backend for '%s'", e_source_get_uri (new_source)); - goto finish; - } - if (!e_cal_open (new_ecal, FALSE, &error)) { - g_warning ("failed to load destination ecal for migration: '%s' (%s)", error->message, - e_source_get_uri (new_source)); - goto finish; - } - - retval = migrate_ical (old_ecal, new_ecal); - -finish: - g_clear_error (&error); - if (old_ecal) - g_object_unref (old_ecal); - g_object_unref (group); - if (new_ecal) - g_object_unref (new_ecal); - g_free (old_uri); - - return retval; -} - -static gboolean -migrate_ical_folder (gchar *old_path, ESourceGroup *dest_group, gchar *source_name, ECalSourceType type) -{ - ESource *new_source; - gboolean retval; - - new_source = e_source_new (source_name, source_name); - e_source_set_relative_uri (new_source, e_source_peek_uid (new_source)); - e_source_group_add_source (dest_group, new_source, -1); - - retval = migrate_ical_folder_to_source (old_path, new_source, type); - - g_object_unref (new_source); - - return retval; -} - -#endif /* !G_OS_WIN32 */ - -#ifndef G_OS_WIN32 - -static void -migrate_pilot_db_key (const gchar *key, gpointer user_data) -{ - EXmlHash *xmlhash = user_data; - - e_xmlhash_add (xmlhash, key, ""); -} - -static void -migrate_pilot_data (const gchar *component, const gchar *conduit, const gchar *old_path, const gchar *new_path) -{ - gchar *changelog, *map; - const gchar *dent; - const gchar *ext; - gchar *filename; - GDir *dir; - - if (!(dir = g_dir_open (old_path, 0, NULL))) - return; - - map = g_alloca (12 + strlen (conduit)); - sprintf (map, "pilot-map-%s-", conduit); - - changelog = g_alloca (24 + strlen (conduit)); - sprintf (changelog, "pilot-sync-evolution-%s-", conduit); - - while ((dent = g_dir_read_name (dir))) { - if (!strncmp (dent, map, strlen (map)) && - ((ext = strrchr (dent, '.')) && !strcmp (ext, ".xml"))) { - /* pilot map file - src and dest file formats are identical */ - guchar inbuf[4096]; - gsize nread, nwritten; - gint fd0, fd1; - gssize n; - - filename = g_build_filename (old_path, dent, NULL); - if ((fd0 = g_open (filename, O_RDONLY|O_BINARY, 0)) == -1) { - g_free (filename); - continue; - } - - g_free (filename); - filename = g_build_filename (new_path, dent, NULL); - if ((fd1 = g_open (filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666)) == -1) { - g_free (filename); - close (fd0); - continue; - } - - do { - do { - n = read (fd0, inbuf, sizeof (inbuf)); - } while (n == -1 && errno == EINTR); - - if (n < 1) - break; - - nread = n; - nwritten = 0; - do { - do { - n = write (fd1, inbuf + nwritten, nread - nwritten); - } while (n == -1 && errno == EINTR); - - if (n > 0) - nwritten += n; - } while (nwritten < nread && n != -1); - - if (n == -1) - break; - } while (1); - - if (n != -1) - n = fsync (fd1); - - if (n == -1) { - g_warning ("Failed to migrate %s: %s", dent, strerror (errno)); - g_unlink (filename); - } - - close (fd0); - close (fd1); - g_free (filename); - } else if (!strncmp (dent, changelog, strlen (changelog)) && - ((ext = strrchr (dent, '.')) && !strcmp (ext, ".db"))) { - /* src and dest formats differ, src format is db3 while dest format is xml */ - EXmlHash *xmlhash; - EDbHash *dbhash; - struct stat st; - - filename = g_build_filename (old_path, dent, NULL); - if (g_stat (filename, &st) == -1) { - g_free (filename); - continue; - } - - dbhash = e_dbhash_new (filename); - g_free (filename); - - filename = g_strdup_printf ("%s/%s.ics-%s", new_path, component, dent); - if (g_stat (filename, &st) != -1) - g_unlink (filename); - xmlhash = e_xmlhash_new (filename); - g_free (filename); - - e_dbhash_foreach_key (dbhash, migrate_pilot_db_key, xmlhash); - - e_dbhash_destroy (dbhash); - - e_xmlhash_write (xmlhash); - e_xmlhash_destroy (xmlhash); - } - } - - g_dir_close (dir); -} - -#endif - -static ESourceGroup * -create_calendar_contact_source (ESourceList *source_list) -{ - ESourceGroup *group; - ESource *source; - - /* Create the contacts group */ - group = e_source_group_new (_("Contacts"), CONTACTS_BASE_URI); - e_source_list_add_group (source_list, group, -1); - - source = e_source_new (_("Birthdays & Anniversaries"), "/"); - e_source_group_add_source (group, source, -1); - g_object_unref (source); - - e_source_set_color_spec (source, "#FED4D3"); - e_source_group_set_readonly (group, TRUE); - - return group; -} - -static void -create_calendar_sources (EShellBackend *shell_backend, - ESourceList *source_list, - ESourceGroup **on_this_computer, - ESource **personal_source, - ESourceGroup **on_the_web, - ESourceGroup **contacts) -{ - EShell *shell; - EShellSettings *shell_settings; - GSList *groups; - ESourceGroup *group; - gchar *base_uri, *base_uri_proto; - const gchar *base_dir; - - *on_this_computer = NULL; - *on_the_web = NULL; - *contacts = NULL; - *personal_source = NULL; - - shell = e_shell_backend_get_shell (shell_backend); - shell_settings = e_shell_get_shell_settings (shell); - - base_dir = e_shell_backend_get_config_dir (shell_backend); - base_uri = g_build_filename (base_dir, "local", NULL); - - base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL); - - groups = e_source_list_peek_groups (source_list); - if (groups) { - /* groups are already there, we need to search for things... */ - GSList *g; - - for (g = groups; g; g = g->next) { - - group = E_SOURCE_GROUP (g->data); - - if (!strcmp (BAD_CONTACTS_BASE_URI, e_source_group_peek_base_uri (group))) - e_source_group_set_base_uri (group, CONTACTS_BASE_URI); - - if (!strcmp (base_uri, e_source_group_peek_base_uri (group))) - e_source_group_set_base_uri (group, base_uri_proto); - - if (!*on_this_computer && !strcmp (base_uri_proto, e_source_group_peek_base_uri (group))) - *on_this_computer = g_object_ref (group); - else if (!*on_the_web && !strcmp (WEBCAL_BASE_URI, e_source_group_peek_base_uri (group))) - *on_the_web = g_object_ref (group); - else if (!*contacts && !strcmp (CONTACTS_BASE_URI, e_source_group_peek_base_uri (group))) - *contacts = g_object_ref (group); - } - } - - if (*on_this_computer) { - /* make sure "Personal" shows up as a source under - this group */ - GSList *sources = e_source_group_peek_sources (*on_this_computer); - GSList *s; - for (s = sources; s; s = s->next) { - ESource *source = E_SOURCE (s->data); - const gchar *relative_uri; - - relative_uri = e_source_peek_relative_uri (source); - if (relative_uri == NULL) - continue; - if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) { - *personal_source = g_object_ref (source); - break; - } - } - } else { - /* create the local source group */ - group = e_source_group_new (_("On This Computer"), base_uri_proto); - e_source_list_add_group (source_list, group, -1); - - *on_this_computer = group; - } - - if (!*personal_source) { - gchar *primary_calendar; - - /* Create the default Person calendar */ - ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); - e_source_group_add_source (*on_this_computer, source, -1); - - primary_calendar = e_shell_settings_get_string ( - shell_settings, "cal-primary-calendar"); - - if (!primary_calendar && !calendar_config_get_calendars_selected ()) { - GSList selected; - - e_shell_settings_set_string ( - shell_settings, "cal-primary-calendar", - e_source_peek_uid (source)); - - selected.data = (gpointer)e_source_peek_uid (source); - selected.next = NULL; - calendar_config_set_calendars_selected (&selected); - } - - g_free (primary_calendar); - e_source_set_color_spec (source, "#BECEDD"); - *personal_source = source; - } - - if (!*on_the_web) { - /* Create the Webcal source group */ - group = e_source_group_new (_("On The Web"), WEBCAL_BASE_URI); - e_source_list_add_group (source_list, group, -1); - - *on_the_web = group; - } - - if (!*contacts) { - group = create_calendar_contact_source (source_list); - - *contacts = group; - } - - g_free (base_uri_proto); - g_free (base_uri); -} - -gboolean -e_cal_shell_backend_migrate (EShellBackend *shell_backend, - gint major, - gint minor, - gint micro, - GError **error) -{ - ESourceGroup *on_this_computer = NULL, *on_the_web = NULL, *contacts = NULL; - ESource *personal_source = NULL; - ESourceList *source_list; - ECalEvent *ece; - ECalEventTargetModule *target; - gboolean retval = FALSE; - - source_list = g_object_get_data ( - G_OBJECT (shell_backend), "source-list"); - - /* we call this unconditionally now - create_groups either - creates the groups/sources or it finds the necessary - groups/sources. */ - create_calendar_sources ( - shell_backend, source_list, &on_this_computer, - &personal_source, &on_the_web, &contacts); - -#ifndef G_OS_WIN32 - if (major == 1) { - xmlDocPtr config_doc = NULL; - gchar *conf_file; - struct stat st; - - conf_file = g_build_filename (g_get_home_dir (), "evolution", "config.xmldb", NULL); - if (lstat (conf_file, &st) == 0 && S_ISREG (st.st_mode)) - config_doc = xmlParseFile (conf_file); - g_free (conf_file); - - if (config_doc && minor <= 2) { - GConfClient *gconf; - gint res = 0; - - /* move bonobo config to gconf */ - gconf = gconf_client_get_default (); - - res = e_bconf_import (gconf, config_doc, calendar_remap_list); - - g_object_unref (gconf); - - xmlFreeDoc(config_doc); - - if (res != 0) { - /* FIXME: set proper domain/code */ - g_set_error(error, 0, 0, _("Unable to migrate old settings from evolution/config.xmldb")); - goto fail; - } - } - - if (minor <= 4) { - GSList *migration_dirs, *l; - gchar *path, *local_cal_folder; - - setup_progress_dialog (); - - path = g_build_filename (g_get_home_dir (), "evolution", "local", NULL); - migration_dirs = e_folder_map_local_folders (path, "calendar"); - local_cal_folder = g_build_filename (path, "Calendar", NULL); - g_free (path); - - if (personal_source) - migrate_ical_folder_to_source (local_cal_folder, personal_source, E_CAL_SOURCE_TYPE_EVENT); - - for (l = migration_dirs; l; l = l->next) { - gchar *source_name; - - if (personal_source && !strcmp ((gchar *)l->data, local_cal_folder)) - continue; - - source_name = get_source_name (on_this_computer, (gchar *)l->data); - - if (!migrate_ical_folder (l->data, on_this_computer, source_name, E_CAL_SOURCE_TYPE_EVENT)) { - /* FIXME: domain/code */ - g_set_error(error, 0, 0, _("Unable to migrate calendar `%s'"), source_name); - g_free(source_name); - goto fail; - } - - g_free (source_name); - } - - g_free (local_cal_folder); - - dialog_close (); - } - - if (minor <= 4 || (minor == 5 && micro < 5)) { - GConfClient *gconf; - GConfValue *gconf_val; - gint i; - const gchar *keys[] = { - CALENDAR_CONFIG_HPANE_POS, - CALENDAR_CONFIG_VPANE_POS, - CALENDAR_CONFIG_MONTH_HPANE_POS, - CALENDAR_CONFIG_MONTH_VPANE_POS, - NULL - }; - - gconf = gconf_client_get_default (); - - for (i = 0; keys[i]; i++) { - gconf_val = gconf_client_get (gconf, keys[i], NULL); - if (gconf_val) { - if (gconf_val->type != GCONF_VALUE_INT) - gconf_client_unset (gconf, keys[i], NULL); - gconf_value_free (gconf_val); - } - } - - g_object_unref (gconf); - } - - if (minor < 5 || (minor == 5 && micro <= 10)) { - gchar *old_path, *new_path; - - old_path = g_build_filename (g_get_home_dir (), "evolution", "local", "Calendar", NULL); - new_path = g_build_filename (e_shell_backend_get_config_dir (shell_backend), - "local", "system", NULL); - migrate_pilot_data ("calendar", "calendar", old_path, new_path); - g_free (new_path); - g_free (old_path); - } - - /* we only need to do this next step if people ran - older versions of 1.5. We need to clear out the - absolute URI's that were assigned to ESources - during one phase of development, as they take - precedent over relative uris (but aren't updated - when editing an ESource). */ - if (minor == 5 && micro <= 11) { - GSList *g; - for (g = e_source_list_peek_groups (source_list); g; g = g->next) { - ESourceGroup *group = g->data; - GSList *s; - - for (s = e_source_group_peek_sources (group); s; s = s->next) { - ESource *source = s->data; - e_source_set_absolute_uri (source, NULL); - } - } - } - - } -#endif /* !G_OS_WIN32 */ - - e_source_list_sync (source_list, NULL); - - /** @Event: component.migration - * @Title: Migration step in component initialization - * @Target: ECalEventTargetComponent - * - * component.migration is emitted during the calendar component - * initialization process. This allows new calendar backend types - * to be distributed as an e-d-s backend and a plugin without - * reaching their grubby little fingers into migration.c - */ - /* Fire off migration event */ - ece = e_cal_event_peek (); - target = e_cal_event_target_new_module (ece, shell_backend, 0); - e_event_emit ((EEvent *) ece, "module.migration", (EEventTarget *) target); - - retval = TRUE; -fail: - if (on_this_computer) - g_object_unref (on_this_computer); - if (on_the_web) - g_object_unref (on_the_web); - if (contacts) - g_object_unref (contacts); - if (personal_source) - g_object_unref (personal_source); - - return retval; -} - diff --git a/calendar/module/e-cal-shell-migrate.h b/calendar/module/e-cal-shell-migrate.h deleted file mode 100644 index 359ca5ea22..0000000000 --- a/calendar/module/e-cal-shell-migrate.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * e-cal-shell-backend-migrate.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_CAL_SHELL_BACKEND_MIGRATE_H -#define E_CAL_SHELL_BACKEND_MIGRATE_H - -#include -#include - -G_BEGIN_DECLS - -gboolean e_cal_shell_backend_migrate (EShellBackend *shell_backend, - gint major, - gint minor, - gint micro, - GError **error); - -G_END_DECLS - -#endif /* E_CAL_SHELL_BACKEND_MIGRATE_H */ diff --git a/calendar/module/e-cal-shell-settings.c b/calendar/module/e-cal-shell-settings.c deleted file mode 100644 index 03af4aeebc..0000000000 --- a/calendar/module/e-cal-shell-settings.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * e-cal-shell-backend-settings.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-cal-shell-settings.h" - -#include - -void -e_cal_shell_backend_init_settings (EShell *shell) -{ - EShellSettings *shell_settings; - - shell_settings = e_shell_get_shell_settings (shell); - - /* XXX Default values should match the GConf schema. - * Yes it's redundant, but we're stuck with GConf. */ - - e_shell_settings_install_property ( - g_param_spec_string ( - "cal-primary-calendar", - NULL, - NULL, - NULL, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "cal-primary-calendar", - "/apps/evolution/calendar/display/primary_calendar"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "cal-use-system-timezone", - NULL, - NULL, - TRUE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "cal-use-system-timezone", - "/apps/evolution/calendar/display/use_system_timezone"); -} diff --git a/calendar/module/e-cal-shell-settings.h b/calendar/module/e-cal-shell-settings.h deleted file mode 100644 index de8b22888b..0000000000 --- a/calendar/module/e-cal-shell-settings.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * e-cal-shell-backend-settings.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_CAL_SHELL_BACKEND_SETTINGS_H -#define E_CAL_SHELL_BACKEND_SETTINGS_H - -#include - -G_BEGIN_DECLS - -void e_cal_shell_backend_init_settings (EShell *shell); - -G_END_DECLS - -#endif /* E_CAL_SHELL_BACKEND_SETTINGS_H */ diff --git a/calendar/module/e-cal-shell-sidebar.c b/calendar/module/e-cal-shell-sidebar.c deleted file mode 100644 index dc7df596d6..0000000000 --- a/calendar/module/e-cal-shell-sidebar.c +++ /dev/null @@ -1,759 +0,0 @@ -/* - * e-cal-shell-sidebar.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-cal-shell-sidebar.h" - -#include -#include - -#include "e-util/e-error.h" -#include "e-util/gconf-bridge.h" -#include "calendar/common/authentication.h" -#include "calendar/gui/calendar-config.h" -#include "calendar/gui/e-calendar-selector.h" -#include "calendar/gui/e-mini-calendar-config.h" -#include "calendar/gui/misc.h" - -#include "e-cal-shell-backend.h" -#include "e-cal-shell-view.h" - -#define E_CAL_SHELL_SIDEBAR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_CAL_SHELL_SIDEBAR, ECalShellSidebarPrivate)) - -struct _ECalShellSidebarPrivate { - GtkWidget *paned; - GtkWidget *selector; - GtkWidget *mini_calendar; - - /* UID -> Client */ - GHashTable *client_table; - - EMiniCalendarConfig *mini_calendar_config; -}; - -enum { - PROP_0, - PROP_MINI_CALENDAR, - PROP_SELECTOR -}; - -enum { - CLIENT_ADDED, - CLIENT_REMOVED, - STATUS_MESSAGE, - LAST_SIGNAL -}; - -static gpointer parent_class; -static guint signals[LAST_SIGNAL]; -static GType cal_shell_sidebar_type; - -static void -cal_shell_sidebar_emit_client_added (ECalShellSidebar *cal_shell_sidebar, - ECal *client) -{ - guint signal_id = signals[CLIENT_ADDED]; - - g_signal_emit (cal_shell_sidebar, signal_id, 0, client); -} - -static void -cal_shell_sidebar_emit_client_removed (ECalShellSidebar *cal_shell_sidebar, - ECal *client) -{ - guint signal_id = signals[CLIENT_REMOVED]; - - g_signal_emit (cal_shell_sidebar, signal_id, 0, client); -} - -static void -cal_shell_sidebar_emit_status_message (ECalShellSidebar *cal_shell_sidebar, - const gchar *status_message) -{ - guint signal_id = signals[STATUS_MESSAGE]; - - g_signal_emit (cal_shell_sidebar, signal_id, 0, status_message); -} - -static void -cal_shell_sidebar_backend_died_cb (ECalShellSidebar *cal_shell_sidebar, - ECal *client) -{ - EShellView *shell_view; - EShellWindow *shell_window; - EShellSidebar *shell_sidebar; - GHashTable *client_table; - ESource *source; - const gchar *uid; - - client_table = cal_shell_sidebar->priv->client_table; - - shell_sidebar = E_SHELL_SIDEBAR (cal_shell_sidebar); - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - shell_window = e_shell_view_get_shell_window (shell_view); - - source = e_cal_get_source (client); - uid = e_source_peek_uid (source); - - g_object_ref (source); - - g_hash_table_remove (client_table, uid); - cal_shell_sidebar_emit_status_message (cal_shell_sidebar, NULL); - - e_error_run ( - GTK_WINDOW (shell_window), - "calendar:calendar-crashed", NULL); - - g_object_unref (source); -} - -static void -cal_shell_sidebar_backend_error_cb (ECalShellSidebar *cal_shell_sidebar, - const gchar *message, - ECal *client) -{ - EShellView *shell_view; - EShellWindow *shell_window; - EShellSidebar *shell_sidebar; - GtkWidget *dialog; - const gchar *uri; - gchar *uri_no_passwd; - - shell_sidebar = E_SHELL_SIDEBAR (cal_shell_sidebar); - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - shell_window = e_shell_view_get_shell_window (shell_view); - - uri = e_cal_get_uri (client); - uri_no_passwd = get_uri_without_password (uri); - - dialog = gtk_message_dialog_new ( - GTK_WINDOW (shell_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, - _("Error on %s\n%s"), - uri_no_passwd, message); - - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - - g_free (uri_no_passwd); -} - -static void -cal_shell_sidebar_client_opened_cb (ECalShellSidebar *cal_shell_sidebar, - ECalendarStatus status, - ECal *client) -{ - EShellView *shell_view; - EShellWindow *shell_window; - EShellSidebar *shell_sidebar; - ESource *source; - - source = e_cal_get_source (client); - - shell_sidebar = E_SHELL_SIDEBAR (cal_shell_sidebar); - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - shell_window = e_shell_view_get_shell_window (shell_view); - - if (status == E_CALENDAR_STATUS_AUTHENTICATION_FAILED || - status == E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED) - auth_cal_forget_password (client); - - switch (status) { - case E_CALENDAR_STATUS_OK: - g_signal_handlers_disconnect_matched ( - client, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, - cal_shell_sidebar_client_opened_cb, NULL); - - cal_shell_sidebar_emit_status_message ( - cal_shell_sidebar, _("Loading calendars")); - cal_shell_sidebar_emit_client_added ( - cal_shell_sidebar, client); - cal_shell_sidebar_emit_status_message ( - cal_shell_sidebar, NULL); - break; - - case E_CALENDAR_STATUS_AUTHENTICATION_FAILED: - e_cal_open_async (client, FALSE); - break; - - case E_CALENDAR_STATUS_BUSY: - break; - - case E_CALENDAR_STATUS_REPOSITORY_OFFLINE: - e_error_run ( - GTK_WINDOW (shell_window), - "calendar:prompt-no-contents-offline-calendar", - NULL); - break; - - default: - cal_shell_sidebar_emit_client_removed ( - cal_shell_sidebar, client); - break; - } -} - -static void -cal_shell_sidebar_row_changed_cb (ECalShellSidebar *cal_shell_sidebar, - GtkTreePath *tree_path, - GtkTreeIter *tree_iter, - GtkTreeModel *tree_model) -{ - ESourceSelector *selector; - ESource *source; - - /* XXX ESourceSelector's underlying tree store has only one - * column: ESource objects. While we're not supposed to - * know this, listening for "row-changed" signals from - * the model is easier to deal with than the selector's - * "selection-changed" signal, which doesn't tell you - * _which_ row changed. */ - - selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); - gtk_tree_model_get (tree_model, tree_iter, 0, &source, -1); - - /* XXX This signal gets emitted a lot while the model is being - * rebuilt, during which time we won't get a valid ESource. - * ESourceSelector should probably block this signal while - * rebuilding the model, but we'll be forgiving and not - * emit a warning. */ - if (!E_IS_SOURCE (source)) - return; - - if (e_source_selector_source_is_selected (selector, source)) - e_cal_shell_sidebar_add_source (cal_shell_sidebar, source); - else - e_cal_shell_sidebar_remove_source (cal_shell_sidebar, source); -} - -static void -cal_shell_sidebar_selection_changed_cb (ECalShellSidebar *cal_shell_sidebar, - ESourceSelector *selector) -{ - GSList *list, *iter; - - /* This signal is emitted less frequently than "row-changed", - * especially when the model is being rebuilt. So we'll take - * it easy on poor GConf. */ - - list = e_source_selector_get_selection (selector); - - for (iter = list; iter != NULL; iter = iter->next) { - ESource *source = iter->data; - - iter->data = (gpointer) e_source_peek_uid (source); - g_object_unref (source); - } - - calendar_config_set_calendars_selected (list); - - g_slist_free (list); -} - -static void -cal_shell_sidebar_primary_selection_changed_cb (ECalShellSidebar *cal_shell_sidebar, - ESourceSelector *selector) -{ - EShell *shell; - EShellView *shell_view; - EShellWindow *shell_window; - EShellSidebar *shell_sidebar; - EShellSettings *shell_settings; - ESource *source; - - /* XXX ESourceSelector needs a "primary-selection-uid" property - * so we can just bind the property with GConfBridge. */ - - source = e_source_selector_peek_primary_selection (selector); - if (source == NULL) - return; - - shell_sidebar = E_SHELL_SIDEBAR (cal_shell_sidebar); - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - shell_window = e_shell_view_get_shell_window (shell_view); - - shell = e_shell_window_get_shell (shell_window); - shell_settings = e_shell_get_shell_settings (shell); - - e_shell_settings_set_string ( - shell_settings, "cal-primary-calendar", - e_source_peek_uid (source)); -} - -static void -cal_shell_sidebar_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_MINI_CALENDAR: - g_value_set_object ( - value, e_cal_shell_sidebar_get_mini_calendar ( - E_CAL_SHELL_SIDEBAR (object))); - return; - - case PROP_SELECTOR: - g_value_set_object ( - value, e_cal_shell_sidebar_get_selector ( - E_CAL_SHELL_SIDEBAR (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -cal_shell_sidebar_dispose (GObject *object) -{ - ECalShellSidebarPrivate *priv; - - priv = E_CAL_SHELL_SIDEBAR_GET_PRIVATE (object); - - if (priv->paned != NULL) { - g_object_unref (priv->paned); - priv->paned = NULL; - } - - if (priv->selector != NULL) { - g_object_unref (priv->selector); - priv->selector = NULL; - } - - if (priv->mini_calendar != NULL) { - g_object_unref (priv->mini_calendar); - priv->mini_calendar = NULL; - } - - g_hash_table_remove_all (priv->client_table); - - if (priv->mini_calendar_config != NULL) { - g_object_unref (priv->mini_calendar_config); - priv->mini_calendar = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -cal_shell_sidebar_finalize (GObject *object) -{ - ECalShellSidebarPrivate *priv; - - priv = E_CAL_SHELL_SIDEBAR_GET_PRIVATE (object); - - g_hash_table_destroy (priv->client_table); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -cal_shell_sidebar_constructed (GObject *object) -{ - ECalShellSidebarPrivate *priv; - EShell *shell; - EShellView *shell_view; - EShellWindow *shell_window; - EShellBackend *shell_backend; - EShellSidebar *shell_sidebar; - EShellSettings *shell_settings; - ESourceSelector *selector; - ESourceList *source_list; - ESource *source; - ECalendarItem *calitem; - GConfBridge *bridge; - GtkTreeModel *model; - GtkWidget *container; - GtkWidget *widget; - AtkObject *a11y; - GSList *list, *iter; - const gchar *key; - gchar *uid; - - priv = E_CAL_SHELL_SIDEBAR_GET_PRIVATE (object); - - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (parent_class)->constructed (object); - - shell_sidebar = E_SHELL_SIDEBAR (object); - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - shell_backend = e_shell_view_get_shell_backend (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - shell = e_shell_window_get_shell (shell_window); - shell_settings = e_shell_get_shell_settings (shell); - - source_list = e_cal_shell_backend_get_source_list ( - E_CAL_SHELL_BACKEND (shell_backend)); - - container = GTK_WIDGET (shell_sidebar); - - widget = gtk_vpaned_new (); - gtk_container_add (GTK_CONTAINER (container), widget); - priv->paned = g_object_ref (widget); - gtk_widget_show (widget); - - container = widget; - - widget = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy ( - GTK_SCROLLED_WINDOW (widget), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type ( - GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); - gtk_paned_add1 (GTK_PANED (container), widget); - gtk_widget_show (widget); - - container = widget; - - widget = e_calendar_selector_new (source_list); - e_source_selector_set_select_new (E_SOURCE_SELECTOR (widget), TRUE); - gtk_container_add (GTK_CONTAINER (container), widget); - a11y = gtk_widget_get_accessible (widget); - atk_object_set_name (a11y, _("Calendar Selector")); - priv->selector = g_object_ref (widget); - gtk_widget_show (widget); - - container = priv->paned; - - widget = e_calendar_new (); - calitem = E_CALENDAR (widget)->calitem; - e_calendar_item_set_days_start_week_sel (calitem, 9); - e_calendar_item_set_max_days_sel (calitem, 42); - gtk_paned_add2 (GTK_PANED (container), widget); - priv->mini_calendar = g_object_ref (widget); - gtk_widget_show (widget); - - priv->mini_calendar_config = - e_mini_calendar_config_new (E_CALENDAR (widget)); - - /* Restore the selector state from the last session. */ - - selector = E_SOURCE_SELECTOR (priv->selector); - model = gtk_tree_view_get_model (GTK_TREE_VIEW (selector)); - - g_signal_connect_swapped ( - model, "row-changed", - G_CALLBACK (cal_shell_sidebar_row_changed_cb), - object); - - source = NULL; - uid = e_shell_settings_get_string ( - shell_settings, "cal-primary-calendar"); - if (uid != NULL) - source = e_source_list_peek_source_by_uid (source_list, uid); - if (source == NULL) - source = e_source_list_peek_source_any (source_list); - if (source != NULL) - e_source_selector_set_primary_selection (selector, source); - g_free (uid); - - list = calendar_config_get_calendars_selected (); - for (iter = list; iter != NULL; iter = iter->next) { - uid = iter->data; - source = e_source_list_peek_source_by_uid (source_list, uid); - g_free (uid); - - if (source == NULL) - continue; - - e_source_selector_select_source (selector, source); - } - g_slist_free (list); - - /* Listen for subsequent changes to the selector. */ - - g_signal_connect_swapped ( - selector, "selection-changed", - G_CALLBACK (cal_shell_sidebar_selection_changed_cb), - object); - - g_signal_connect_swapped ( - selector, "primary-selection-changed", - G_CALLBACK (cal_shell_sidebar_primary_selection_changed_cb), - object); - - /* Bind GObject properties to GConf keys. */ - - bridge = gconf_bridge_get (); - - object = G_OBJECT (priv->paned); - key = "/apps/evolution/calendar/display/date_navigator_vpane_position"; - gconf_bridge_bind_property_delayed (bridge, key, object, "position"); -} - -static void -cal_shell_sidebar_client_removed (ECalShellSidebar *cal_shell_sidebar, - ECal *client) -{ - ESourceSelector *selector; - GHashTable *client_table; - ESource *source; - const gchar *uid; - - client_table = cal_shell_sidebar->priv->client_table; - selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); - - g_signal_handlers_disconnect_matched ( - client, G_SIGNAL_MATCH_DATA, 0, 0, - NULL, NULL, cal_shell_sidebar); - - source = e_cal_get_source (client); - e_source_selector_unselect_source (selector, source); - - uid = e_source_peek_uid (source); - g_hash_table_remove (client_table, uid); - - cal_shell_sidebar_emit_status_message (cal_shell_sidebar, NULL); -} - -static void -cal_shell_sidebar_class_init (ECalShellSidebarClass *class) -{ - GObjectClass *object_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (ECalShellSidebarPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->get_property = cal_shell_sidebar_get_property; - object_class->dispose = cal_shell_sidebar_dispose; - object_class->finalize = cal_shell_sidebar_finalize; - object_class->constructed = cal_shell_sidebar_constructed; - - class->client_removed = cal_shell_sidebar_client_removed; - - g_object_class_install_property ( - object_class, - PROP_MINI_CALENDAR, - g_param_spec_object ( - "mini-calendar", - _("Mini-Calendar Widget"), - _("This widget displays a miniature calendar"), - E_TYPE_CALENDAR, - G_PARAM_READABLE)); - - g_object_class_install_property ( - object_class, - PROP_SELECTOR, - g_param_spec_object ( - "selector", - _("Source Selector Widget"), - _("This widget displays groups of calendars"), - E_TYPE_SOURCE_SELECTOR, - G_PARAM_READABLE)); - - signals[CLIENT_ADDED] = g_signal_new ( - "client-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ECalShellSidebarClass, client_added), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - E_TYPE_CAL); - - signals[CLIENT_REMOVED] = g_signal_new ( - "client-removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ECalShellSidebarClass, client_removed), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - E_TYPE_CAL); - - signals[STATUS_MESSAGE] = g_signal_new ( - "status-message", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (ECalShellSidebarClass, status_message), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); -} - -static void -cal_shell_sidebar_init (ECalShellSidebar *cal_shell_sidebar) -{ - GHashTable *client_table; - - client_table = g_hash_table_new_full ( - g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_object_unref); - - cal_shell_sidebar->priv = - E_CAL_SHELL_SIDEBAR_GET_PRIVATE (cal_shell_sidebar); - - cal_shell_sidebar->priv->client_table = client_table; - - /* Postpone widget construction until we have a shell view. */ -} - -GType -e_cal_shell_sidebar_get_type (void) -{ - return cal_shell_sidebar_type; -} - -void -e_cal_shell_sidebar_register_type (GTypeModule *type_module) -{ - static const GTypeInfo type_info = { - sizeof (ECalShellSidebarClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) cal_shell_sidebar_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (ECalShellSidebar), - 0, /* n_preallocs */ - (GInstanceInitFunc) cal_shell_sidebar_init, - NULL /* value_table */ - }; - - cal_shell_sidebar_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_SIDEBAR, - "ECalShellSidebar", &type_info, 0); -} - -GtkWidget * -e_cal_shell_sidebar_new (EShellView *shell_view) -{ - g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - - return g_object_new ( - E_TYPE_CAL_SHELL_SIDEBAR, - "shell-view", shell_view, NULL); -} - -GList * -e_cal_shell_sidebar_get_clients (ECalShellSidebar *cal_shell_sidebar) -{ - GHashTable *client_table; - - g_return_val_if_fail ( - E_IS_CAL_SHELL_SIDEBAR (cal_shell_sidebar), NULL); - - client_table = cal_shell_sidebar->priv->client_table; - - return g_hash_table_get_values (client_table); -} - -ECalendar * -e_cal_shell_sidebar_get_mini_calendar (ECalShellSidebar *cal_shell_sidebar) -{ - g_return_val_if_fail ( - E_IS_CAL_SHELL_SIDEBAR (cal_shell_sidebar), NULL); - - return E_CALENDAR (cal_shell_sidebar->priv->mini_calendar); -} - -ESourceSelector * -e_cal_shell_sidebar_get_selector (ECalShellSidebar *cal_shell_sidebar) -{ - g_return_val_if_fail ( - E_IS_CAL_SHELL_SIDEBAR (cal_shell_sidebar), NULL); - - return E_SOURCE_SELECTOR (cal_shell_sidebar->priv->selector); -} - -void -e_cal_shell_sidebar_add_source (ECalShellSidebar *cal_shell_sidebar, - ESource *source) -{ - ESourceSelector *selector; - GHashTable *client_table; - ECal *client; - const gchar *uid; - const gchar *uri; - gchar *message; - - g_return_if_fail (E_IS_CAL_SHELL_SIDEBAR (cal_shell_sidebar)); - g_return_if_fail (E_IS_SOURCE (source)); - - client_table = cal_shell_sidebar->priv->client_table; - selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); - - uid = e_source_peek_uid (source); - client = g_hash_table_lookup (client_table, uid); - - if (client != NULL) - return; - - client = auth_new_cal_from_source (source, E_CAL_SOURCE_TYPE_EVENT); - g_return_if_fail (client != NULL); - - g_signal_connect_swapped ( - client, "backend-died", - G_CALLBACK (cal_shell_sidebar_backend_died_cb), - cal_shell_sidebar); - - g_signal_connect_swapped ( - client, "backend-error", - G_CALLBACK (cal_shell_sidebar_backend_error_cb), - cal_shell_sidebar); - - g_hash_table_insert (client_table, g_strdup (uid), client); - e_source_selector_select_source (selector, source); - - uri = e_cal_get_uri (client); - message = g_strdup_printf (_("Opening calendar at %s"), uri); - cal_shell_sidebar_emit_status_message (cal_shell_sidebar, message); - g_free (message); - - g_signal_connect_swapped ( - client, "cal-opened", - G_CALLBACK (cal_shell_sidebar_client_opened_cb), - cal_shell_sidebar); - - e_cal_open_async (client, FALSE); -} - -void -e_cal_shell_sidebar_remove_source (ECalShellSidebar *cal_shell_sidebar, - ESource *source) -{ - ESourceSelector *selector; - GHashTable *client_table; - ECal *client; - const gchar *uid; - - g_return_if_fail (E_IS_CAL_SHELL_SIDEBAR (cal_shell_sidebar)); - g_return_if_fail (E_IS_SOURCE (source)); - - client_table = cal_shell_sidebar->priv->client_table; - selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); - - uid = e_source_peek_uid (source); - client = g_hash_table_lookup (client_table, uid); - - if (client == NULL) - return; - - cal_shell_sidebar_emit_client_removed (cal_shell_sidebar, client); -} diff --git a/calendar/module/e-cal-shell-sidebar.h b/calendar/module/e-cal-shell-sidebar.h deleted file mode 100644 index c555537abf..0000000000 --- a/calendar/module/e-cal-shell-sidebar.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * e-cal-shell-sidebar.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_CAL_SHELL_SIDEBAR_H -#define E_CAL_SHELL_SIDEBAR_H - -#include -#include - -#include -#include -#include - -/* Standard GObject macros */ -#define E_TYPE_CAL_SHELL_SIDEBAR \ - (e_cal_shell_sidebar_get_type ()) -#define E_CAL_SHELL_SIDEBAR(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_CAL_SHELL_SIDEBAR, ECalShellSidebar)) -#define E_CAL_SHELL_SIDEBAR_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_CAL_SHELL_SIDEBAR, ECalShellSidebarClass)) -#define E_IS_CAL_SHELL_SIDEBAR(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_CAL_SHELL_SIDEBAR)) -#define E_IS_CAL_SHELL_SIDEBAR_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_CAL_SHELL_SIDEBAR)) -#define E_CAL_SHELL_SIDEBAR_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_CAL_SHELL_SIDEBAR, ECalShellSidebarClass)) - -G_BEGIN_DECLS - -typedef struct _ECalShellSidebar ECalShellSidebar; -typedef struct _ECalShellSidebarClass ECalShellSidebarClass; -typedef struct _ECalShellSidebarPrivate ECalShellSidebarPrivate; - -enum { - E_CAL_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE = 1 << 0, - E_CAL_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_EMPTY = 1 << 1, - E_CAL_SHELL_SIDEBAR_SOURCE_CAN_GO_OFFLINE = 1 << 2, - E_CAL_SHELL_SIDEBAR_SOURCE_CAN_DELETE = 1 << 3 -}; - -struct _ECalShellSidebar { - EShellSidebar parent; - ECalShellSidebarPrivate *priv; -}; - -struct _ECalShellSidebarClass { - EShellSidebarClass parent_class; - - /* Signals */ - void (*client_added) (ECalShellSidebar *cal_shell_sidebar, - ECal *client); - void (*client_removed) (ECalShellSidebar *cal_shell_sidebar, - ECal *client); - void (*status_message) (ECalShellSidebar *cal_shell_sidebar, - const gchar *status_message); -}; - -GType e_cal_shell_sidebar_get_type (void); -void e_cal_shell_sidebar_register_type - (GTypeModule *type_module); -GtkWidget * e_cal_shell_sidebar_new (EShellView *shell_view); -GList * e_cal_shell_sidebar_get_clients - (ECalShellSidebar *cal_shell_sidebar); -ECalendar * e_cal_shell_sidebar_get_mini_calendar - (ECalShellSidebar *cal_shell_sidebar); -ESourceSelector * - e_cal_shell_sidebar_get_selector - (ECalShellSidebar *cal_shell_sidebar); -void e_cal_shell_sidebar_add_source - (ECalShellSidebar *cal_shell_sidebar, - ESource *source); -void e_cal_shell_sidebar_remove_source - (ECalShellSidebar *cal_shell_sidebar, - ESource *source); - -G_END_DECLS - -#endif /* E_CAL_SHELL_SIDEBAR_H */ diff --git a/calendar/module/e-cal-shell-view-actions.c b/calendar/module/e-cal-shell-view-actions.c deleted file mode 100644 index 02b7af609e..0000000000 --- a/calendar/module/e-cal-shell-view-actions.c +++ /dev/null @@ -1,1202 +0,0 @@ -/* - * e-cal-shell-view-actions.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-cal-shell-view-private.h" - -static void -action_calendar_copy_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellSidebar *cal_shell_sidebar; - EShellWindow *shell_window; - EShellView *shell_view; - ESourceSelector *selector; - ESource *source; - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; - selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); - source = e_source_selector_peek_primary_selection (selector); - g_return_if_fail (E_IS_SOURCE (source)); - - copy_source_dialog ( - GTK_WINDOW (shell_window), - source, E_CAL_SOURCE_TYPE_EVENT); -} - -static void -action_calendar_delete_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ -#if 0 - ECalShellContent *cal_shell_content; - ECalShellSidebar *cal_shell_sidebar; - EShellWindow *shell_window; - EShellView *shell_view; - ECalendarView *calendar_view; - GnomeCalendarViewType view_type; - ECalModel *model; - ESourceSelector *selector; - ESourceGroup *source_group; - ESourceList *source_list; - ESource *source; - gint response; - gchar *uri; - GError *error = NULL; - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - cal_shell_content = cal_shell_content->priv->cal_shell_content; - view_type = e_cal_shell_content_get_current_view (cal_shell_content); - calendar_view = e_cal_shell_content_get_calendar_view ( - cal_shell_content, view_type); - model = e_calendar_view_get_model (calendar_view); - - cal_shell_sidebar = cal_shell_sidebar->priv->cal_shell_sidebar; - selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); - source = e_source_selector_peek_primary_selection (selector); - g_return_if_fail (E_IS_SOURCE (source)); - - /* Ask for confirmation. */ - response = e_error_run ( - GTK_WINDOW (shell_window), - "calendar:prompt-delete-calendar", - e_source_peek_name (source)); - if (response != GTK_RESPONSE_YES) - return; - - uri = e_source_get_uri (source); - client = e_cal_model_get_client_for_uri (model, uri); - if (client == NULL) - client = e_cal_new_from_uri (uri, E_CAL_SOURCE_TYPE_EVENT); - g_free (uri); - - g_return_if_fail (client != NULL); - - if (!e_cal_remove (client, &error)) { - g_warning ("%s", error->message); - g_error_free (error); - return; - } - - if (e_source_selector_source_is_selected (selector, source)) { - e_cal_shell_sidebar_remove_source ( - cal_shell_sidebar, source); - e_source_selector_unselect_source (selector, source); - } - - source_group = e_source_peek_group (source); - e_source_group_remove_source (source_group, source); - - source_list = cal_shell_view->priv->source_list; - if (!e_source_list_sync (source_list, &error)) { - g_warning ("%s", error->message); - g_error_free (error); - } -#endif -} - -static void -action_calendar_go_back_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ -#if 0 - ECalShellContent *cal_shell_content; - GnomeCalendar *calendar; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - calendar = e_cal_shell_content_get_calendar (cal_shell_content); - - gnome_calendar_previous (calendar); -#endif -} - -static void -action_calendar_go_forward_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ -#if 0 - ECalShellContent *cal_shell_content; - GnomeCalendar *calendar; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - calendar = e_cal_shell_content_get_calendar (cal_shell_content); - - gnome_calendar_next (calendar); -#endif -} - -static void -action_calendar_go_today_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ -#if 0 - ECalShellContent *cal_shell_content; - GnomeCalendar *calendar; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - calendar = e_cal_shell_content_get_calendar (cal_shell_content); - - gnome_calendar_goto_today (calendar); -#endif -} - -static void -action_calendar_jump_to_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ -#if 0 - ECalShellContent *cal_shell_content; - GnomeCalendar *calendar; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - calendar = e_cal_shell_content_get_calendar (cal_shell_content); - - goto_dialog (calendar); -#endif -} - -static void -action_calendar_new_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ -#if 0 - EShellView *shell_view; - EShellWindow *shell_window; - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - calendar_setup_new_calendar (GTK_WINDOW (shell_window)); -#endif -} - -static void -action_calendar_print_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ -#if 0 - ECalShellContent *cal_shell_content; - GnomeCalendar *calendar; - GtkPrintOperationAction print_action; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - calendar = e_cal_shell_content_get_calendar (cal_shell_content); - print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; - - if (gnome_calendar_get_view (calendar) == GNOME_CAL_LIST_VIEW) { - ECalListView *list_view; - GtkWidget *widget; - ETable *table; - - widget = gnome_calendar_get_current_view_widget (calendar); - list_view = E_CAL_LIST_VIEW (widget); - table = e_table_scrolled_get_table (list_view->table_scrolled); - print_table (table, _("Print"), _("Calendar"), action); - } else { - time_t start; - - gnome_calendar_get_current_time_range (calendar, &start, NULL); - print_calendar (calendar, action, start); - } -#endif -} - -static void -action_calendar_print_preview_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ -#if 0 - ECalShellContent *cal_shell_content; - GnomeCalendar *calendar; - GtkPrintOperationAction print_action; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - calendar = e_cal_shell_content_get_calendar (cal_shell_content); - print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW; - - if (gnome_calendar_get_view (calendar) == GNOME_CAL_LIST_VIEW) { - ECalListView *list_view; - GtkWidget *widget; - ETable *table; - - widget = gnome_calendar_get_current_view_widget (calendar); - list_view = E_CAL_LIST_VIEW (widget); - table = e_table_scrolled_get_table (list_view->table_scrolled); - print_table (table, _("Print"), _("Calendar"), action); - } else { - time_t start; - - gnome_calendar_get_current_time_range (calendar, &start, NULL); - print_calendar (calendar, action, start); - } -#endif -} - -static void -action_calendar_properties_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ -#if 0 - ECalShellSidebar *cal_shell_sidebar; - EShellView *shell_view; - EShellWindow *shell_window; - ESource *source; - ESourceSelector *selector; - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; - selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); - source = e_source_selector_peek_primary_selection (selector); - g_return_if_fail (E_IS_SOURCE (source)); - - calendar_setup_edit_calendar (GTK_WINDOW (shell_window), source); -#endif -} - -static void -action_calendar_purge_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - /* FIXME */ -} - -static void -action_calendar_rename_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellSidebar *cal_shell_sidebar; - ESourceSelector *selector; - - cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; - selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); - - e_source_selector_edit_primary_selection (selector); -} - -static void -action_calendar_search_cb (GtkRadioAction *action, - GtkRadioAction *current, - ECalShellView *cal_shell_view) -{ - EShellView *shell_view; - EShellContent *shell_content; - const gchar *search_hint; - - /* XXX Figure out a way to handle this in EShellContent - * instead of every shell view having to handle it. - * The problem is EShellContent does not know what - * the search option actions are for this view. It - * would have to dig up the popup menu and retrieve - * the action for each menu item. Seems messy. */ - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - - search_hint = gtk_action_get_label (GTK_ACTION (current)); - e_shell_content_set_search_hint (shell_content, search_hint); -} - -static void -action_calendar_select_one_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellSidebar *cal_shell_sidebar; - ESourceSelector *selector; - ESource *primary; - GSList *list, *iter; - - /* XXX ESourceSelector should provide a function for this. */ - - cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; - selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); - primary = e_source_selector_peek_primary_selection (selector); - g_return_if_fail (primary != NULL); - - list = e_source_selector_get_selection (selector); - for (iter = list; iter != NULL; iter = iter->next) { - ESource *source = iter->data; - - if (source == primary) - continue; - - e_source_selector_unselect_source (selector, source); - } - e_source_selector_free_selection (list); - - e_source_selector_select_source (selector, primary); -} - -static void -action_calendar_view_cb (GtkRadioAction *action, - GtkRadioAction *current, - ECalShellView *cal_shell_view) -{ - EShellView *shell_view; - GnomeCalendarViewType view_type; - const gchar *view_id; - - shell_view = E_SHELL_VIEW (cal_shell_view); - view_type = gtk_radio_action_get_current_value (action); - - switch (view_type) { - case GNOME_CAL_DAY_VIEW: - view_id = "Day_View"; - break; - - case GNOME_CAL_WORK_WEEK_VIEW: - view_id = "Work_Week_View"; - break; - - case GNOME_CAL_WEEK_VIEW: - view_id = "Week_View"; - break; - - case GNOME_CAL_MONTH_VIEW: - view_id = "Month_View"; - break; - - case GNOME_CAL_LIST_VIEW: - view_id = "List_View"; - break; - - default: - g_return_if_reached (); - } - - e_shell_view_set_view_id (shell_view, view_id); -} - -static void -action_event_all_day_new_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - /* FIXME */ -} - -static void -action_event_clipboard_copy_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - e_cal_shell_content_copy_clipboard (cal_shell_content); -} - -static void -action_event_clipboard_cut_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - e_cal_shell_content_cut_clipboard (cal_shell_content); -} - -static void -action_event_clipboard_paste_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - e_cal_shell_content_paste_clipboard (cal_shell_content); -} - -static void -action_event_copy_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - /* FIXME */ -} - -static void -action_event_delegate_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - /* FIXME */ -} - -static void -action_event_delete_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - e_cal_shell_content_delete_selection (cal_shell_content); -} - -static void -action_event_delete_occurrence_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - e_cal_shell_content_delete_selected_occurrence (cal_shell_content); -} - -static void -action_event_delete_occurrence_all_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - - /* XXX Same as "event-delete". */ - cal_shell_content = cal_shell_view->priv->cal_shell_content; - e_cal_shell_content_delete_selection (cal_shell_content); -} - -static void -action_event_forward_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - /* FIXME */ -} - -static void -action_event_meeting_new_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - /* FIXME */ -} - -static void -action_event_move_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - /* FIXME */ -} - -static void -action_event_new_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - /* FIXME */ -} - -static void -action_event_occurrence_movable_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - /* FIXME */ -} - -static void -action_event_open_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ -#if 0 - ECalShellContent *cal_shell_content; - GnomeCalendar *calendar; - GtkWidget *widget; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - calendar = e_cal_shell_content_get_calendar (cal_shell_content); - widget = gnome_calendar_get_current_view_widget (calendar); - - e_calendar_view_open_event (E_CALENDAR_VIEW (widget)); -#endif -} - -static void -action_event_print_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - /* FIXME */ -} - -static void -action_event_reply_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - /* FIXME */ -} - -static void -action_event_reply_all_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - /* FIXME */ -} - -static void -action_event_save_as_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - /* FIXME */ -} - -static void -action_event_schedule_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - /* FIXME */ -} - -static void -action_gal_save_custom_view_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - EShellView *shell_view; - GalViewInstance *view_instance; - - /* All shell views respond to the activation of this action, - * which is defined by EShellWindow. But only the currently - * active shell view proceeds with saving the custom view. */ - shell_view = E_SHELL_VIEW (cal_shell_view); - if (!e_shell_view_is_active (shell_view)) - return; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - view_instance = e_cal_shell_content_get_view_instance (cal_shell_content); - gal_view_instance_save_as (view_instance); -} - -static void -action_search_execute_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - EShellView *shell_view; - - /* All shell views respond to the activation of this action, - * which is defined by EShellWindow. But only the currently - * active shell view proceeds with executing the search. */ - shell_view = E_SHELL_VIEW (cal_shell_view); - if (!e_shell_view_is_active (shell_view)) - return; - - e_cal_shell_view_execute_search (cal_shell_view); -} - -static void -action_search_filter_cb (GtkRadioAction *action, - GtkRadioAction *current, - ECalShellView *cal_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - gtk_action_activate (ACTION (SEARCH_EXECUTE)); -} - -static GtkActionEntry calendar_entries[] = { - - { "calendar-copy", - GTK_STOCK_COPY, - N_("_Copy..."), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_copy_cb) }, - - { "calendar-delete", - GTK_STOCK_DELETE, - NULL, - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_delete_cb) }, - - { "calendar-go-back", - GTK_STOCK_GO_BACK, - N_("Previous"), - NULL, - N_("Go Back"), - G_CALLBACK (action_calendar_go_back_cb) }, - - { "calendar-go-forward", - GTK_STOCK_GO_FORWARD, - N_("Next"), - NULL, - N_("Go Forward"), - G_CALLBACK (action_calendar_go_forward_cb) }, - - { "calendar-go-today", - "go-today", - N_("Select _Today"), - "t", - N_("Select today"), - G_CALLBACK (action_calendar_go_today_cb) }, - - { "calendar-jump-to", - GTK_STOCK_JUMP_TO, - N_("Select _Date"), - "g", - N_("Select a specific date"), - G_CALLBACK (action_calendar_jump_to_cb) }, - - { "calendar-new", - "x-office-calendar", - N_("_New Calendar"), - NULL, - N_("Create a new calendar"), - G_CALLBACK (action_calendar_new_cb) }, - - { "calendar-properties", - GTK_STOCK_PROPERTIES, - NULL, - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_properties_cb) }, - - { "calendar-purge", - NULL, - N_("Purg_e"), - "e", - N_("Purge old appointments and meetings"), - G_CALLBACK (action_calendar_purge_cb) }, - - { "calendar-rename", - NULL, - N_("_Rename..."), - "F2", - N_("Rename the selected calendar"), - G_CALLBACK (action_calendar_rename_cb) }, - - { "calendar-select-one", - "stock_check-filled", - N_("Show _Only This Calendar"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_select_one_cb) }, - - { "event-clipboard-copy", - GTK_STOCK_COPY, - NULL, - NULL, - N_("Copy the selection"), - G_CALLBACK (action_event_clipboard_copy_cb) }, - - { "event-clipboard-cut", - GTK_STOCK_CUT, - NULL, - NULL, - N_("Cut the selection"), - G_CALLBACK (action_event_clipboard_cut_cb) }, - - { "event-clipboard-paste", - GTK_STOCK_PASTE, - NULL, - NULL, - N_("Paste the clipboard"), - G_CALLBACK (action_event_clipboard_paste_cb) }, - - { "event-copy", - NULL, - N_("Cop_y to Calendar..."), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_copy_cb) }, - - { "event-delegate", - NULL, - N_("_Delegate Meeting..."), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_delegate_cb) }, - - { "event-delete", - GTK_STOCK_DELETE, - NULL, - NULL, - N_("Delete the appointment"), - G_CALLBACK (action_event_delete_cb) }, - - { "event-delete-occurrence", - GTK_STOCK_DELETE, - N_("Delete This _Occurrence"), - NULL, - N_("Delete this occurrence"), - G_CALLBACK (action_event_delete_occurrence_cb) }, - - { "event-delete-occurrence-all", - GTK_STOCK_DELETE, - N_("Delete _All Occurrences"), - NULL, - N_("Delete all occurrences"), - G_CALLBACK (action_event_delete_occurrence_all_cb) }, - - { "event-all-day-new", - NULL, - N_("New All Day _Event..."), - NULL, - N_("Create a new all day event"), - G_CALLBACK (action_event_all_day_new_cb) }, - - { "event-forward", - "mail-forward", - N_("_Forward as iCalendar..."), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_forward_cb) }, - - { "event-meeting-new", - NULL, - N_("New _Meeting..."), - NULL, - N_("Create a new meeting"), - G_CALLBACK (action_event_meeting_new_cb) }, - - { "event-move", - NULL, - N_("Mo_ve to Calendar..."), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_move_cb) }, - - { "event-new", - NULL, - N_("New _Appointment..."), - NULL, - N_("Create a new appointment"), - G_CALLBACK (action_event_new_cb) }, - - { "event-occurrence-movable", - NULL, - N_("Make this Occurrence _Movable"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_occurrence_movable_cb) }, - - { "event-open", - NULL, - N_("_Open Appointment"), - "o", - N_("View the current appointment"), - G_CALLBACK (action_event_open_cb) }, - - { "event-reply", - "mail-reply-sender", - N_("_Reply"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_reply_cb) }, - - { "event-reply-all", - "mail-reply-all", - N_("Reply to _All"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_reply_all_cb) }, - - { "event-save-as", - GTK_STOCK_SAVE_AS, - NULL, - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_save_as_cb) }, - - { "event-schedule", - NULL, - N_("_Schedule Meeting..."), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_schedule_cb) }, - - /*** Menus ***/ - - { "calendar-actions-menu", - NULL, - N_("_Actions"), - NULL, - NULL, - NULL } -}; - -static EPopupActionEntry calendar_popup_entries[] = { - - /* FIXME No equivalent main menu items for the any of the calendar - * popup menu items and for many of the event popup menu items. - * This is an accessibility issue. */ - - { "calendar-popup-copy", - NULL, - "calendar-copy" }, - - { "calendar-popup-delete", - NULL, - "calendar-delete" }, - - { "calendar-popup-go-today", - NULL, - "calendar-go-today" }, - - { "calendar-popup-jump-to", - NULL, - "calendar-jump-to" }, - - { "calendar-popup-properties", - NULL, - "calendar-properties" }, - - { "calendar-popup-rename", - NULL, - "calendar-rename" }, - - { "calendar-popup-select-one", - NULL, - "calendar-select-one" }, - - { "event-popup-clipboard-copy", - NULL, - "event-clipboard-copy" }, - - { "event-popup-clipboard-cut", - NULL, - "event-clipboard-cut" }, - - { "event-popup-clipboard-paste", - NULL, - "event-clipboard-paste" }, - - { "event-popup-copy", - NULL, - "event-copy" }, - - { "event-popup-delegate", - NULL, - "event-delegate" }, - - { "event-popup-delete", - NULL, - "event-delete" }, - - { "event-popup-delete-occurrence", - NULL, - "event-delete-occurrence" }, - - { "event-popup-delete-occurrence-all", - NULL, - "event-delete-occurrence-all" }, - - { "event-popup-forward", - NULL, - "event-forward" }, - - { "event-popup-move", - NULL, - "event-move" }, - - { "event-popup-occurrence-movable", - NULL, - "event-occurrence-movable" }, - - { "event-popup-open", - NULL, - "event-open" }, - - { "event-popup-reply", - NULL, - "event-reply" }, - - { "event-popup-reply-all", - NULL, - "event-reply-all" }, - - { "event-popup-save-as", - NULL, - "event-save-as" }, - - { "event-popup-schedule", - NULL, - "event-schedule" } -}; - -static GtkRadioActionEntry calendar_view_entries[] = { - - { "calendar-view-day", - "view-calendar-day", - N_("Day"), - NULL, - N_("Show one day"), - GNOME_CAL_DAY_VIEW }, - - { "calendar-view-list", - "view-calendar-list", - N_("List"), - NULL, - N_("Show as list"), - GNOME_CAL_LIST_VIEW }, - - { "calendar-view-month", - "view-calendar-month", - N_("Month"), - NULL, - N_("Show one month"), - GNOME_CAL_MONTH_VIEW }, - - { "calendar-view-week", - "view-calendar-week", - N_("Week"), - NULL, - N_("Show one week"), - GNOME_CAL_WEEK_VIEW }, - - { "calendar-view-workweek", - "view-calendar-workweek", - N_("Work Week"), - NULL, - N_("Show one work week"), - GNOME_CAL_WORK_WEEK_VIEW } -}; - -static GtkRadioActionEntry calendar_filter_entries[] = { - - { "calendar-filter-active-appointments", - NULL, - N_("Active Appointements"), - NULL, - NULL, /* XXX Add a tooltip! */ - CALENDAR_FILTER_ACTIVE_APPOINTMENTS }, - - { "calendar-filter-any-category", - NULL, - N_("Any Category"), - NULL, - NULL, /* XXX Add a tooltip! */ - CALENDAR_FILTER_ANY_CATEGORY }, - - { "calendar-filter-next-7-days-appointments", - NULL, - N_("Next 7 Days' Appointments"), - NULL, - NULL, /* XXX Add a tooltip! */ - CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS }, - - { "calendar-filter-unmatched", - NULL, - N_("Unmatched"), - NULL, - NULL, /* XXX Add a tooltip! */ - CALENDAR_FILTER_UNMATCHED } -}; - -static GtkRadioActionEntry calendar_search_entries[] = { - - { "calendar-search-any-field-contains", - NULL, - N_("Any field contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - CALENDAR_SEARCH_ANY_FIELD_CONTAINS }, - - { "calendar-search-description-contains", - NULL, - N_("Description contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - CALENDAR_SEARCH_DESCRIPTION_CONTAINS }, - - { "calendar-search-summary-contains", - NULL, - N_("Summary contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - CALENDAR_SEARCH_SUMMARY_CONTAINS } -}; - -static GtkActionEntry lockdown_printing_entries[] = { - - { "calendar-print", - GTK_STOCK_PRINT, - NULL, - "p", - N_("Print this calendar"), - G_CALLBACK (action_calendar_print_cb) }, - - { "calendar-print-preview", - GTK_STOCK_PRINT_PREVIEW, - NULL, - NULL, - N_("Preview the calendar to be printed"), - G_CALLBACK (action_calendar_print_preview_cb) }, - - { "event-print", - GTK_STOCK_PRINT, - NULL, - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_print_cb) } -}; - -static EPopupActionEntry lockdown_printing_popup_entries[] = { - - { "event-popup-print", - NULL, - "event-print" } -}; - -void -e_cal_shell_view_actions_init (ECalShellView *cal_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - GtkActionGroup *action_group; - GtkAction *action; - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - /* Calendar Actions */ - action_group = ACTION_GROUP (CALENDAR); - gtk_action_group_add_actions ( - action_group, calendar_entries, - G_N_ELEMENTS (calendar_entries), cal_shell_view); - e_action_group_add_popup_actions ( - action_group, calendar_popup_entries, - G_N_ELEMENTS (calendar_popup_entries)); - gtk_action_group_add_radio_actions ( - action_group, calendar_view_entries, - G_N_ELEMENTS (calendar_view_entries), GNOME_CAL_DAY_VIEW, - G_CALLBACK (action_calendar_view_cb), cal_shell_view); - gtk_action_group_add_radio_actions ( - action_group, calendar_search_entries, - G_N_ELEMENTS (calendar_search_entries), - CALENDAR_SEARCH_SUMMARY_CONTAINS, - G_CALLBACK (action_calendar_search_cb), cal_shell_view); - - /* Lockdown Printing Actions */ - action_group = ACTION_GROUP (LOCKDOWN_PRINTING); - gtk_action_group_add_actions ( - action_group, lockdown_printing_entries, - G_N_ELEMENTS (lockdown_printing_entries), cal_shell_view); - e_action_group_add_popup_actions ( - action_group, lockdown_printing_popup_entries, - G_N_ELEMENTS (lockdown_printing_popup_entries)); - - /* Fine tuning. */ - - action = ACTION (CALENDAR_GO_TODAY); - g_object_set (action, "short-label", _("Today"), NULL); - - action = ACTION (CALENDAR_JUMP_TO); - g_object_set (action, "short-label", _("Go To"), NULL); - - action = ACTION (EVENT_DELETE); - g_object_set (action, "short-label", _("Delete"), NULL); - - g_signal_connect ( - ACTION (GAL_SAVE_CUSTOM_VIEW), "activate", - G_CALLBACK (action_gal_save_custom_view_cb), cal_shell_view); - - g_signal_connect ( - ACTION (SEARCH_EXECUTE), "activate", - G_CALLBACK (action_search_execute_cb), cal_shell_view); - - /* Initialize the memo and task pad actions. */ - e_cal_shell_view_memopad_actions_init (cal_shell_view); - e_cal_shell_view_taskpad_actions_init (cal_shell_view); -} - -void -e_cal_shell_view_update_search_filter (ECalShellView *cal_shell_view) -{ - EShellContent *shell_content; - EShellWindow *shell_window; - EShellView *shell_view; - GtkActionGroup *action_group; - GtkRadioAction *radio_action; - GList *list, *iter; - GSList *group; - gint ii; - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - action_group = ACTION_GROUP (CALENDAR_FILTER); - e_action_group_remove_all_actions (action_group); - - /* Add the standard filter actions. */ - gtk_action_group_add_radio_actions ( - action_group, calendar_filter_entries, - G_N_ELEMENTS (calendar_filter_entries), - CALENDAR_FILTER_ANY_CATEGORY, - G_CALLBACK (action_search_filter_cb), - cal_shell_view); - - /* Retrieve the radio group from an action we just added. */ - list = gtk_action_group_list_actions (action_group); - radio_action = GTK_RADIO_ACTION (list->data); - group = gtk_radio_action_get_group (radio_action); - g_list_free (list); - - /* Build the category actions. */ - - list = e_categories_get_list (); - for (iter = list, ii = 0; iter != NULL; iter = iter->next, ii++) { - const gchar *category_name = iter->data; - const gchar *filename; - GtkAction *action; - gchar *action_name; - - action_name = g_strdup_printf ( - "calendar-filter-category-%d", ii); - radio_action = gtk_radio_action_new ( - action_name, category_name, NULL, NULL, ii); - g_free (action_name); - - /* Convert the category icon file to a themed icon name. */ - filename = e_categories_get_icon_file_for (category_name); - if (filename != NULL && *filename != '\0') { - gchar *basename; - gchar *cp; - - basename = g_path_get_basename (filename); - - /* Lose the file extension. */ - if ((cp = strrchr (basename, '.')) != NULL) - *cp = '\0'; - - g_object_set ( - radio_action, "icon-name", basename, NULL); - - g_free (basename); - } - - gtk_radio_action_set_group (radio_action, group); - group = gtk_radio_action_get_group (radio_action); - - /* The action group takes ownership of the action. */ - action = GTK_ACTION (radio_action); - gtk_action_group_add_action (action_group, action); - g_object_unref (radio_action); - } - g_list_free (list); - - /* Use any action in the group; doesn't matter which. */ - e_shell_content_set_filter_action (shell_content, radio_action); - - ii = CALENDAR_FILTER_UNMATCHED; - e_shell_content_add_filter_separator_after (shell_content, ii); - - ii = CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS; - e_shell_content_add_filter_separator_after (shell_content, ii); -} diff --git a/calendar/module/e-cal-shell-view-actions.h b/calendar/module/e-cal-shell-view-actions.h deleted file mode 100644 index b02906f179..0000000000 --- a/calendar/module/e-cal-shell-view-actions.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * e-cal-shell-view-actions.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_CAL_SHELL_VIEW_ACTIONS_H -#define E_CAL_SHELL_VIEW_ACTIONS_H - -#include - -/* Calendar Actions */ -#define E_SHELL_WINDOW_ACTION_CALENDAR_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-copy") -#define E_SHELL_WINDOW_ACTION_CALENDAR_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-delete") -#define E_SHELL_WINDOW_ACTION_CALENDAR_GO_BACK(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-go-back") -#define E_SHELL_WINDOW_ACTION_CALENDAR_GO_FORWARD(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-go-forward") -#define E_SHELL_WINDOW_ACTION_CALENDAR_GO_TODAY(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-go-today") -#define E_SHELL_WINDOW_ACTION_CALENDAR_JUMP_TO(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-jump-to") -#define E_SHELL_WINDOW_ACTION_CALENDAR_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-new") -#define E_SHELL_WINDOW_ACTION_CALENDAR_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-print") -#define E_SHELL_WINDOW_ACTION_CALENDAR_PRINT_PREVIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-print-preview") -#define E_SHELL_WINDOW_ACTION_CALENDAR_PROPERTIES(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-properties") -#define E_SHELL_WINDOW_ACTION_CALENDAR_PURGE(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-purge") -#define E_SHELL_WINDOW_ACTION_CALENDAR_RENAME(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-rename") -#define E_SHELL_WINDOW_ACTION_CALENDAR_SELECT_ONE(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-select-one") -#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_DAY(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-view-day") -#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_LIST(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-view-list") -#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_MONTH(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-view-month") -#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_WEEK(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-view-week") -#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_WORKWEEK(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-view-workweek") - -/* Event Actions */ -#define E_SHELL_WINDOW_ACTION_EVENT_CLIPBOARD_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-clipboard-copy") -#define E_SHELL_WINDOW_ACTION_EVENT_CLIPBOARD_CUT(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-clipboard-cut") -#define E_SHELL_WINDOW_ACTION_EVENT_CLIPBOARD_PASTE(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-clipboard-paste") -#define E_SHELL_WINDOW_ACTION_EVENT_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-delete") -#define E_SHELL_WINDOW_ACTION_EVENT_DELETE_OCCURRENCE(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-delete-occurrence") -#define E_SHELL_WINDOW_ACTION_EVENT_DELETE_OCCURRENCE_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-delete-occurrence-all") -#define E_SHELL_WINDOW_ACTION_EVENT_OPEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-open") - -/* Memo Pad Actions */ -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_CLIPBOARD_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-clipboard-copy") -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_CLIPBOARD_CUT(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-clipboard-cut") -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_CLIPBOARD_PASTE(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-clipboard-paste") -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-delete") -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_FORWARD(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-forward") -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-new") -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_OPEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-open") -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_OPEN_URL(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-open-url") -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-print") -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_SAVE_AS(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-save-as") - -/* Task Pad Actions */ -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_ASSIGN(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-assign") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_CLIPBOARD_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-clipboard-copy") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_CLIPBOARD_CUT(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-clipboard-cut") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_CLIPBOARD_PASTE(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-clipboard-paste") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-delete") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_FORWARD(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-forward") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_MARK_COMPLETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-mark-complete") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_MARK_INCOMPLETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-mark-incomplete") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-new") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_OPEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-open") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_OPEN_URL(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-open-url") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-print") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_SAVE_AS(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-save-as") - -/* Calendar Query Actions */ -#define E_SHELL_WINDOW_ACTION_CALENDAR_FILTER_ACTIVE_APPOINTMENTS(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-filter-active-appointments") -#define E_SHELL_WINDOW_ACTION_CALENDAR_FILTER_ANY_CATEGORY(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-filter-any-category") -#define E_SHELL_WINDOW_ACTION_CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-filter-next-7-days-appointments") -#define E_SHELL_WINDOW_ACTION_CALENDAR_FILTER_UNMATCHED(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-filter-unmatched") -#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_ANY_FIELD_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-search-any-field-contains") -#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_DESCRIPTION_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-search-description-contains") -#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_SUMMARY_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-search-summary-contains") - -/* Action Groups */ -#define E_SHELL_WINDOW_ACTION_GROUP_CALENDAR(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "calendar") -#define E_SHELL_WINDOW_ACTION_GROUP_CALENDAR_FILTER(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "calendar-filter") - -#endif /* E_CAL_SHELL_VIEW_ACTIONS_H */ diff --git a/calendar/module/e-cal-shell-view-memopad.c b/calendar/module/e-cal-shell-view-memopad.c deleted file mode 100644 index ecee72d8b5..0000000000 --- a/calendar/module/e-cal-shell-view-memopad.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - * e-cal-shell-view-memopad.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-cal-shell-view-private.h" - -/* Much of this file is based on e-memo-shell-view-actions.c. */ - -static void -action_calendar_memopad_clipboard_copy_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - EMemoTable *memo_table; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - - e_memo_table_copy_clipboard (memo_table); -} - -static void -action_calendar_memopad_clipboard_cut_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - EMemoTable *memo_table; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - - e_memo_table_cut_clipboard (memo_table); -} - -static void -action_calendar_memopad_clipboard_paste_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - EMemoTable *memo_table; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - - e_memo_table_paste_clipboard (memo_table); -} - -static void -action_calendar_memopad_delete_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - EMemoTable *memo_table; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - - e_cal_shell_view_memopad_set_status_message ( - cal_shell_view, _("Deleting selected memos..."), -1.0); - e_memo_table_delete_selected (memo_table); - e_cal_shell_view_memopad_set_status_message ( - cal_shell_view, NULL, -1.0); -} - -static void -action_calendar_memopad_forward_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - EMemoTable *memo_table; - ECalModelComponent *comp_data; - ECalComponent *comp; - icalcomponent *clone; - GSList *list; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - - list = e_memo_table_get_selected (memo_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - /* XXX We only forward the first selected memo. */ - comp = e_cal_component_new (); - clone = icalcomponent_new_clone (comp_data->icalcomp); - e_cal_component_set_icalcomponent (comp, clone); - itip_send_comp ( - E_CAL_COMPONENT_METHOD_PUBLISH, comp, - comp_data->client, NULL, NULL, NULL, TRUE); - g_object_unref (comp); -} - -static void -action_calendar_memopad_new_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - EShell *shell; - EShellView *shell_view; - EShellWindow *shell_window; - ECalShellContent *cal_shell_content; - EMemoTable *memo_table; - ECalModelComponent *comp_data; - ECal *client; - ECalComponent *comp; - CompEditor *editor; - GSList *list; - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell = e_shell_window_get_shell (shell_window); - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - - list = e_memo_table_get_selected (memo_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - client = comp_data->client; - editor = memo_editor_new (client, shell, COMP_EDITOR_NEW_ITEM); - comp = cal_comp_memo_new_with_defaults (client); - comp_editor_edit_comp (editor, comp); - - gtk_window_present (GTK_WINDOW (editor)); - - g_object_unref (comp); - g_object_unref (client); -} - -static void -action_calendar_memopad_open_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - EMemoTable *memo_table; - ECalModelComponent *comp_data; - GSList *list; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - - list = e_memo_table_get_selected (memo_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - /* XXX We only open the first selected memo. */ - e_cal_shell_view_memopad_open_memo (cal_shell_view, comp_data); -} - -static void -action_calendar_memopad_open_url_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - ECalShellContent *cal_shell_content; - EMemoTable *memo_table; - ECalModelComponent *comp_data; - icalproperty *prop; - const gchar *uri; - GSList *list; - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - - list = e_memo_table_get_selected (memo_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - /* XXX We only open the URI of the first selected memo. */ - prop = icalcomponent_get_first_property ( - comp_data->icalcomp, ICAL_URL_PROPERTY); - g_return_if_fail (prop == NULL); - - uri = icalproperty_get_url (prop); - e_show_uri (GTK_WINDOW (shell_window), uri); -} - -static void -action_calendar_memopad_print_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - EMemoTable *memo_table; - ECalModelComponent *comp_data; - ECalComponent *comp; - icalcomponent *clone; - GtkPrintOperationAction print_action; - GSList *list; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - - list = e_memo_table_get_selected (memo_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - /* XXX We only print the first selected memo. */ - comp = e_cal_component_new (); - clone = icalcomponent_new_clone (comp_data->icalcomp); - print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; - e_cal_component_set_icalcomponent (comp, clone); - print_comp (comp, comp_data->client, print_action); - g_object_unref (comp); -} - -static void -action_calendar_memopad_save_as_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - EMemoTable *memo_table; - ECalModelComponent *comp_data; - GSList *list; - gchar *filename; - gchar *string; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - - list = e_memo_table_get_selected (memo_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - filename = e_file_dialog_save (_("Save as..."), NULL); - if (filename == NULL) - return; - - /* XXX We only save the first selected memo. */ - string = e_cal_get_component_as_string ( - comp_data->client, comp_data->icalcomp); - if (string == NULL) { - g_warning ("Could not convert memo to a string."); - return; - } - - e_write_file_uri (filename, string); - - g_free (filename); - g_free (string); -} - -static GtkActionEntry calendar_memopad_entries[] = { - - { "calendar-memopad-clipboard-copy", - GTK_STOCK_COPY, - NULL, - NULL, - N_("Copy selected memo"), - G_CALLBACK (action_calendar_memopad_clipboard_copy_cb) }, - - { "calendar-memopad-clipboard-cut", - GTK_STOCK_CUT, - NULL, - NULL, - N_("Cut selected memo"), - G_CALLBACK (action_calendar_memopad_clipboard_cut_cb) }, - - { "calendar-memopad-clipboard-paste", - GTK_STOCK_PASTE, - NULL, - NULL, - N_("Paste memo from the clipboard"), - G_CALLBACK (action_calendar_memopad_clipboard_paste_cb) }, - - { "calendar-memopad-delete", - GTK_STOCK_DELETE, - N_("_Delete Memo"), - NULL, - N_("Delete selected memos"), - G_CALLBACK (action_calendar_memopad_delete_cb) }, - - { "calendar-memopad-forward", - "mail-forward", - N_("_Forward as iCalendar..."), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_memopad_forward_cb) }, - - { "calendar-memopad-new", - "stock_insert-note", - N_("New _Memo"), - NULL, - N_("Create a new memo"), - G_CALLBACK (action_calendar_memopad_new_cb) }, - - { "calendar-memopad-open", - GTK_STOCK_OPEN, - N_("_Open Memo"), - NULL, - N_("View the selected memo"), - G_CALLBACK (action_calendar_memopad_open_cb) }, - - { "calendar-memopad-open-url", - "applications-internet", - N_("Open _Web Page"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_memopad_open_url_cb) }, - - { "calendar-memopad-save-as", - GTK_STOCK_SAVE_AS, - NULL, - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_memopad_save_as_cb) } -}; - -static GtkActionEntry lockdown_printing_entries[] = { - - { "calendar-memopad-print", - GTK_STOCK_PRINT, - NULL, - NULL, - N_("Print the selected memo"), - G_CALLBACK (action_calendar_memopad_print_cb) } -}; - -void -e_cal_shell_view_memopad_actions_init (ECalShellView *cal_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - GtkActionGroup *action_group; - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - /* Calendar Actions */ - action_group = ACTION_GROUP (CALENDAR); - gtk_action_group_add_actions ( - action_group, calendar_memopad_entries, - G_N_ELEMENTS (calendar_memopad_entries), cal_shell_view); - - /* Lockdown Printing Actions */ - action_group = ACTION_GROUP (LOCKDOWN_PRINTING); - gtk_action_group_add_actions ( - action_group, lockdown_printing_entries, - G_N_ELEMENTS (lockdown_printing_entries), cal_shell_view); -} - -void -e_cal_shell_view_memopad_actions_update (ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - EShellWindow *shell_window; - EShellView *shell_view; - EMemoTable *memo_table; - ETable *table; - GtkAction *action; - GSList *list, *iter; - const gchar *label; - gboolean editable = TRUE; - gboolean has_url = FALSE; - gboolean sensitive; - gint n_selected; - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - - table = e_memo_table_get_table (memo_table); - n_selected = e_table_selected_count (table); - - list = e_memo_table_get_selected (memo_table); - for (iter = list; iter != NULL; iter = iter->next) { - ECalModelComponent *comp_data = iter->data; - icalproperty *prop; - gboolean read_only; - - e_cal_is_read_only (comp_data->client, &read_only, NULL); - editable &= !read_only; - - prop = icalcomponent_get_first_property ( - comp_data->icalcomp, ICAL_URL_PROPERTY); - has_url |= (prop != NULL); - } - g_slist_free (list); - - action = ACTION (CALENDAR_MEMOPAD_CLIPBOARD_COPY); - sensitive = (n_selected > 0); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_MEMOPAD_CLIPBOARD_CUT); - sensitive = (n_selected > 0) && editable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_MEMOPAD_CLIPBOARD_PASTE); - sensitive = editable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_MEMOPAD_DELETE); - sensitive = (n_selected > 0) && editable; - gtk_action_set_sensitive (action, sensitive); - label = ngettext ("Delete Memo", "Delete Memos", n_selected); - g_object_set (action, "label", label, NULL); - - action = ACTION (CALENDAR_MEMOPAD_FORWARD); - sensitive = (n_selected == 1); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_MEMOPAD_OPEN); - sensitive = (n_selected == 1); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_MEMOPAD_OPEN_URL); - sensitive = (n_selected == 1) && has_url; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_MEMOPAD_PRINT); - sensitive = (n_selected == 1); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_MEMOPAD_SAVE_AS); - sensitive = (n_selected == 1); - gtk_action_set_sensitive (action, sensitive); -} - -void -e_cal_shell_view_memopad_open_memo (ECalShellView *cal_shell_view, - ECalModelComponent *comp_data) -{ - EShell *shell; - EShellView *shell_view; - EShellWindow *shell_window; - CompEditor *editor; - CompEditorFlags flags = 0; - ECalComponent *comp; - icalcomponent *clone; - const gchar *uid; - - g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); - g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data)); - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell = e_shell_window_get_shell (shell_window); - - uid = icalcomponent_get_uid (comp_data->icalcomp); - editor = comp_editor_find_instance (uid); - - if (editor != NULL) - goto exit; - - comp = e_cal_component_new (); - clone = icalcomponent_new_clone (comp_data->icalcomp); - e_cal_component_set_icalcomponent (comp, clone); - - if (e_cal_component_has_organizer (comp)) - flags |= COMP_EDITOR_IS_SHARED; - - if (itip_organizer_is_user (comp, comp_data->client)) - flags |= COMP_EDITOR_USER_ORG; - - editor = memo_editor_new (comp_data->client, shell, flags); - comp_editor_edit_comp (editor, comp); - - g_object_unref (comp); - -exit: - gtk_window_present (GTK_WINDOW (editor)); -} - -void -e_cal_shell_view_memopad_set_status_message (ECalShellView *cal_shell_view, - const gchar *status_message, - gdouble percent) -{ - EActivity *activity; - EShellView *shell_view; - EShellBackend *shell_backend; - - g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_backend = e_shell_view_get_shell_backend (shell_view); - - activity = cal_shell_view->priv->memopad_activity; - - if (status_message == NULL || *status_message == '\0') { - if (activity != NULL) { - e_activity_complete (activity); - g_object_unref (activity); - activity = NULL; - } - - } else if (activity == NULL) { - activity = e_activity_new (status_message); - e_activity_set_percent (activity, percent); - e_shell_backend_add_activity (shell_backend, activity); - - } else { - e_activity_set_percent (activity, percent); - e_activity_set_primary_text (activity, status_message); - } - - cal_shell_view->priv->memopad_activity = activity; -} diff --git a/calendar/module/e-cal-shell-view-private.c b/calendar/module/e-cal-shell-view-private.c deleted file mode 100644 index f681a2c2f3..0000000000 --- a/calendar/module/e-cal-shell-view-private.c +++ /dev/null @@ -1,650 +0,0 @@ -/* - * e-cal-shell-view-private.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-cal-shell-view-private.h" - -#include "calendar/gui/calendar-view-factory.h" -#include "widgets/menus/gal-view-factory-etable.h" - -static void -cal_shell_view_process_completed_tasks (ECalShellView *cal_shell_view, - gboolean config_changed) -{ -#if 0 - ECalShellContent *cal_shell_content; - ECalendarTable *task_table; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - e_calendar_table_process_completed_tasks ( - task_table, clients, config_changed); -#endif -} - -static void -cal_shell_view_config_timezone_changed_cb (GConfClient *client, - guint id, - GConfEntry *entry, - gpointer user_data) -{ - ECalShellView *cal_shell_view = user_data; - - e_cal_shell_view_update_timezone (cal_shell_view); -} - -static struct tm -cal_shell_view_get_current_time (ECalendarItem *calitem, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - struct icaltimetype tt; - icaltimezone *timezone; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - timezone = e_cal_shell_content_get_timezone (cal_shell_content); - - tt = icaltime_from_timet_with_zone (time (NULL), FALSE, timezone); - - return icaltimetype_to_tm (&tt); -} - -static void -cal_shell_view_mini_calendar_date_range_changed_cb (ECalShellView *cal_shell_view, - ECalendarItem *calitem) -{ - /* FIXME gnome-calendar.c calls update_query() here. */ -} - -static void -cal_shell_view_mini_calendar_selection_changed_cb (ECalShellView *cal_shell_view, - ECalendarItem *calitem) -{ - /* FIXME */ -} - -static void -cal_shell_view_mini_calendar_scroll_event_cb (ECalShellView *cal_shell_view, - GdkEventScroll *event, - ECalendar *mini_calendar) -{ - ECalendarItem *calitem; - GDate start_date, end_date; - - calitem = mini_calendar->calitem; - if (!e_calendar_item_get_selection (calitem, &start_date, &end_date)) - return; - - switch (event->direction) { - case GDK_SCROLL_UP: - g_date_subtract_months (&start_date, 1); - g_date_subtract_months (&end_date, 1); - break; - - case GDK_SCROLL_DOWN: - g_date_add_months (&start_date, 1); - g_date_add_months (&end_date, 1); - break; - - default: - g_return_if_reached (); - } - - /* XXX Does ECalendarItem emit a signal for this? If so, maybe - * we could move this handler into ECalShellSidebar. */ - e_calendar_item_set_selection (calitem, &start_date, &end_date); - - cal_shell_view_mini_calendar_date_range_changed_cb ( - cal_shell_view, calitem); -} - -static gboolean -cal_shell_view_selector_popup_event_cb (EShellView *shell_view, - ESource *primary_source, - GdkEventButton *event) -{ - const gchar *widget_path; - - widget_path = "/calendar-popup"; - e_shell_view_show_popup_menu (shell_view, widget_path, event); - - return TRUE; -} - -static void -cal_shell_view_memopad_popup_event_cb (EShellView *shell_view, - GdkEventButton *event) -{ - const gchar *widget_path; - - widget_path = "/calendar-memopad-popup"; - e_shell_view_show_popup_menu (shell_view, widget_path, event); -} - -static void -cal_shell_view_taskpad_popup_event_cb (EShellView *shell_view, - GdkEventButton *event) -{ - const gchar *widget_path; - - widget_path = "/calendar-taskpad-popup"; - e_shell_view_show_popup_menu (shell_view, widget_path, event); -} - -static void -cal_shell_view_load_view_collection (EShellViewClass *shell_view_class) -{ - GalViewCollection *collection; - GalViewFactory *factory; - ETableSpecification *spec; - const gchar *base_dir; - gchar *filename; - - collection = shell_view_class->view_collection; - - base_dir = EVOLUTION_ETSPECDIR; - spec = e_table_specification_new (); - filename = g_build_filename (base_dir, ETSPEC_FILENAME, NULL); - if (!e_table_specification_load_from_file (spec, filename)) - g_critical ("Unable to load ETable specification file " - "for calendars"); - g_free (filename); - - factory = calendar_view_factory_new (GNOME_CAL_DAY_VIEW); - gal_view_collection_add_factory (collection, factory); - g_object_unref (factory); - - factory = calendar_view_factory_new (GNOME_CAL_WORK_WEEK_VIEW); - gal_view_collection_add_factory (collection, factory); - g_object_unref (factory); - - factory = calendar_view_factory_new (GNOME_CAL_WEEK_VIEW); - gal_view_collection_add_factory (collection, factory); - g_object_unref (factory); - - factory = calendar_view_factory_new (GNOME_CAL_MONTH_VIEW); - gal_view_collection_add_factory (collection, factory); - g_object_unref (factory); - - factory = gal_view_factory_etable_new (spec); - gal_view_collection_add_factory (collection, factory); - g_object_unref (factory); - g_object_unref (spec); - - gal_view_collection_load (collection); -} - -static void -cal_shell_view_notify_view_id_cb (ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - GalViewInstance *view_instance; - const gchar *view_id; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - view_instance = - e_cal_shell_content_get_view_instance (cal_shell_content); - view_id = e_shell_view_get_view_id (E_SHELL_VIEW (cal_shell_view)); - - /* A NULL view ID implies we're in a custom view. But you can - * only get to a custom view via the "Define Views" dialog, which - * would have already modified the view instance appropriately. - * Furthermore, there's no way to refer to a custom view by ID - * anyway, since custom views have no IDs. */ - if (view_id == NULL) - return; - - gal_view_instance_set_current_view_id (view_instance, view_id); -} - -void -e_cal_shell_view_private_init (ECalShellView *cal_shell_view, - EShellViewClass *shell_view_class) -{ - if (!gal_view_collection_loaded (shell_view_class->view_collection)) - cal_shell_view_load_view_collection (shell_view_class); - - g_signal_connect ( - cal_shell_view, "notify::view-id", - G_CALLBACK (cal_shell_view_notify_view_id_cb), NULL); -} - -void -e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) -{ - ECalShellViewPrivate *priv = cal_shell_view->priv; - ECalShellContent *cal_shell_content; - ECalShellSidebar *cal_shell_sidebar; - EShellBackend *shell_backend; - EShellContent *shell_content; - EShellSidebar *shell_sidebar; - EShellWindow *shell_window; - EShellView *shell_view; - GnomeCalendar *calendar; - ECalendar *mini_calendar; - EMemoTable *memo_table; - ECalendarTable *task_table; - ESourceSelector *selector; - guint id; - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_backend = e_shell_view_get_shell_backend (shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - e_shell_window_add_action_group (shell_window, "calendar"); - e_shell_window_add_action_group (shell_window, "calendar-filter"); - - /* Cache these to avoid lots of awkward casting. */ - priv->cal_shell_backend = g_object_ref (shell_backend); - priv->cal_shell_content = g_object_ref (shell_content); - priv->cal_shell_sidebar = g_object_ref (shell_sidebar); - - cal_shell_content = E_CAL_SHELL_CONTENT (shell_content); - calendar = e_cal_shell_content_get_calendar (cal_shell_content); - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - cal_shell_sidebar = E_CAL_SHELL_SIDEBAR (shell_sidebar); - selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); - mini_calendar = e_cal_shell_sidebar_get_mini_calendar (cal_shell_sidebar); - - e_calendar_item_set_get_time_callback ( - mini_calendar->calitem, (ECalendarItemGetTimeCallback) - cal_shell_view_get_current_time, cal_shell_view, NULL); - -#if 0 /* KILL-BONOBO */ - g_signal_connect_swapped ( - calendar, "dates-shown-changed", - G_CALLBACK (e_cal_shell_view_update_sidebar), - cal_shell_view); -#endif - - g_signal_connect_swapped ( - mini_calendar, "scroll-event", - G_CALLBACK (cal_shell_view_mini_calendar_scroll_event_cb), - cal_shell_view); - - g_signal_connect_swapped ( - mini_calendar->calitem, "date-range-changed", - G_CALLBACK (cal_shell_view_mini_calendar_date_range_changed_cb), - cal_shell_view); - - g_signal_connect_swapped ( - mini_calendar->calitem, "selection-changed", - G_CALLBACK (cal_shell_view_mini_calendar_selection_changed_cb), - cal_shell_view); - - g_signal_connect_swapped ( - selector, "popup-event", - G_CALLBACK (cal_shell_view_selector_popup_event_cb), - cal_shell_view); - - g_signal_connect_swapped ( - memo_table, "popup-event", - G_CALLBACK (cal_shell_view_memopad_popup_event_cb), - cal_shell_view); - - g_signal_connect_swapped ( - memo_table, "status-message", - G_CALLBACK (e_cal_shell_view_memopad_set_status_message), - cal_shell_view); - - g_signal_connect_swapped ( - task_table, "popup-event", - G_CALLBACK (cal_shell_view_taskpad_popup_event_cb), - cal_shell_view); - - g_signal_connect_swapped ( - task_table, "status-message", - G_CALLBACK (e_cal_shell_view_taskpad_set_status_message), - cal_shell_view); - - g_signal_connect_swapped ( - e_memo_table_get_table (memo_table), "selection-change", - G_CALLBACK (e_cal_shell_view_memopad_actions_update), - cal_shell_view); - - g_signal_connect_swapped ( - e_calendar_table_get_table (task_table), "selection-change", - G_CALLBACK (e_cal_shell_view_taskpad_actions_update), - cal_shell_view); - - e_categories_register_change_listener ( - G_CALLBACK (e_cal_shell_view_update_search_filter), - cal_shell_view); - - /* Listen for configuration changes. */ - - /* Timezone */ - id = calendar_config_add_notification_timezone ( - cal_shell_view_config_timezone_changed_cb, cal_shell_view); - priv->notifications = g_list_prepend ( - priv->notifications, GUINT_TO_POINTER (id)); - - e_cal_shell_view_actions_init (cal_shell_view); - e_cal_shell_view_update_sidebar (cal_shell_view); - e_cal_shell_view_update_search_filter (cal_shell_view); - e_cal_shell_view_update_timezone (cal_shell_view); -} - -void -e_cal_shell_view_private_dispose (ECalShellView *cal_shell_view) -{ - ECalShellViewPrivate *priv = cal_shell_view->priv; - GList *iter; - - DISPOSE (priv->cal_shell_backend); - DISPOSE (priv->cal_shell_content); - DISPOSE (priv->cal_shell_sidebar); - - if (priv->calendar_activity != NULL) { - /* XXX Activity is not cancellable. */ - e_activity_complete (priv->calendar_activity); - g_object_unref (priv->calendar_activity); - priv->calendar_activity = NULL; - } - - if (priv->memopad_activity != NULL) { - /* XXX Activity is not cancellable. */ - e_activity_complete (priv->memopad_activity); - g_object_unref (priv->memopad_activity); - priv->memopad_activity = NULL; - } - - if (priv->taskpad_activity != NULL) { - /* XXX Activity is not cancellable. */ - e_activity_complete (priv->taskpad_activity); - g_object_unref (priv->taskpad_activity); - priv->taskpad_activity = NULL; - } - - for (iter = priv->notifications; iter != NULL; iter = iter->next) { - guint notification_id = GPOINTER_TO_UINT (iter->data); - calendar_config_remove_notification (notification_id); - } - g_list_free (priv->notifications); - priv->notifications = NULL; -} - -void -e_cal_shell_view_private_finalize (ECalShellView *cal_shell_view) -{ - /* XXX Nothing to do? */ -} - -void -e_cal_shell_view_execute_search (ECalShellView *cal_shell_view) -{ - /* FIXME */ -} - -void -e_cal_shell_view_open_event (ECalShellView *cal_shell_view, - ECalModelComponent *comp_data) -{ - EShell *shell; - EShellView *shell_view; - EShellWindow *shell_window; - CompEditor *editor; - CompEditorFlags flags = 0; - ECalComponent *comp; - icalcomponent *clone; - icalproperty *prop; - const gchar *uid; - - g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); - g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data)); - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell = e_shell_window_get_shell (shell_window); - - uid = icalcomponent_get_uid (comp_data->icalcomp); - editor = comp_editor_find_instance (uid); - - if (editor != NULL) - goto exit; - - comp = e_cal_component_new (); - clone = icalcomponent_new_clone (comp_data->icalcomp); - e_cal_component_set_icalcomponent (comp, clone); - - prop = icalcomponent_get_first_property ( - comp_data->icalcomp, ICAL_ATTENDEE_PROPERTY); - if (prop != NULL) - flags |= COMP_EDITOR_MEETING; - - if (itip_organizer_is_user (comp, comp_data->client)) - flags |= COMP_EDITOR_USER_ORG; - - if (itip_sentby_is_user (comp, comp_data->client)) - flags |= COMP_EDITOR_USER_ORG; - - if (!e_cal_component_has_attendees (comp)) - flags |= COMP_EDITOR_USER_ORG; - - editor = event_editor_new (comp_data->client, shell, flags); - comp_editor_edit_comp (editor, comp); - - g_object_ref (comp); - -exit: - gtk_window_present (GTK_WINDOW (editor)); -} - -void -e_cal_shell_view_set_status_message (ECalShellView *cal_shell_view, - const gchar *status_message, - gdouble percent) -{ - EActivity *activity; - EShellView *shell_view; - EShellBackend *shell_backend; - - g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_backend = e_shell_view_get_shell_backend (shell_view); - - activity = cal_shell_view->priv->calendar_activity; - - if (status_message == NULL || *status_message == '\0') { - if (activity != NULL) { - e_activity_complete (activity); - g_object_unref (activity); - activity = NULL; - } - - } else if (activity == NULL) { - activity = e_activity_new (status_message); - e_activity_set_percent (activity, percent); - e_shell_backend_add_activity (shell_backend, activity); - - } else { - e_activity_set_percent (activity, percent); - e_activity_set_primary_text (activity, status_message); - } - - cal_shell_view->priv->calendar_activity = activity; -} - -void -e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view) -{ -#if 0 /* KILL-BONOBO */ - EShellView *shell_view; - EShellSidebar *shell_sidebar; - GnomeCalendar *calendar; - GnomeCalendarViewType view; - time_t start_time, end_time; - struct tm start_tm, end_tm; - struct icaltimetype start_tt, end_tt; - icaltimezone *timezone; - gchar buffer[512]; - gchar end_buffer[512]; - - g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - - calendar = e_cal_shell_view_get_calendar (cal_shell_view); - - gnome_calendar_get_visible_time_range ( - calendar, &start_time, &end_time); - timezone = gnome_calendar_get_timezone (calendar); - view = gnome_calendar_get_view (calendar); - - start_tt = icaltime_from_timet_with_zone (start_time, FALSE, timezone); - start_tm.tm_year = start_tt.year - 1900; - start_tm.tm_mon = start_tt.month - 1; - start_tm.tm_mday = start_tt.day; - start_tm.tm_hour = start_tt.hour; - start_tm.tm_min = start_tt.minute; - start_tm.tm_sec = start_tt.second; - start_tm.tm_isdst = -1; - start_tm.tm_wday = time_day_of_week ( - start_tt.day, start_tt.month - 1, start_tt.year); - - /* Subtract one from end_time so we don't get an extra day. */ - end_tt = icaltime_from_timet_with_zone (end_time - 1, FALSE, timezone); - end_tm.tm_year = end_tt.year - 1900; - end_tm.tm_mon = end_tt.month - 1; - end_tm.tm_mday = end_tt.day; - end_tm.tm_hour = end_tt.hour; - end_tm.tm_min = end_tt.minute; - end_tm.tm_sec = end_tt.second; - end_tm.tm_isdst = -1; - end_tm.tm_wday = time_day_of_week ( - end_tt.day, end_tt.month - 1, end_tt.year); - - switch (view) { - case GNOME_CAL_DAY_VIEW: - case GNOME_CAL_WORK_WEEK_VIEW: - case GNOME_CAL_WEEK_VIEW: - if (start_tm.tm_year == end_tm.tm_year && - start_tm.tm_mon == end_tm.tm_mon && - start_tm.tm_mday == end_tm.tm_mday) { - e_utf8_strftime ( - buffer, sizeof (buffer), - _("%A %d %b %Y"), &start_tm); - } else if (start_tm.tm_year == end_tm.tm_year) { - e_utf8_strftime ( - buffer, sizeof (buffer), - _("%a %d %b"), &start_tm); - e_utf8_strftime ( - end_buffer, sizeof (end_buffer), - _("%a %d %b %Y"), &end_tm); - strcat (buffer, " - "); - strcat (buffer, end_buffer); - } else { - e_utf8_strftime ( - buffer, sizeof (buffer), - _("%a %d %b %Y"), &start_tm); - e_utf8_strftime ( - end_buffer, sizeof (end_buffer), - _("%a %d %b %Y"), &end_tm); - strcat (buffer, " - "); - strcat (buffer, end_buffer); - } - break; - - case GNOME_CAL_MONTH_VIEW: - case GNOME_CAL_LIST_VIEW: - if (start_tm.tm_year == end_tm.tm_year) { - if (start_tm.tm_mon == end_tm.tm_mon) { - e_utf8_strftime ( - buffer, - sizeof (buffer), - "%d", &start_tm); - e_utf8_strftime ( - end_buffer, - sizeof (end_buffer), - _("%d %b %Y"), &end_tm); - strcat (buffer, " - "); - strcat (buffer, end_buffer); - } else { - e_utf8_strftime ( - buffer, - sizeof (buffer), - _("%d %b"), &start_tm); - e_utf8_strftime ( - end_buffer, - sizeof (end_buffer), - _("%d %b %Y"), &end_tm); - strcat (buffer, " - "); - strcat (buffer, end_buffer); - } - } else { - e_utf8_strftime ( - buffer, sizeof (buffer), - _("%d %b %Y"), &start_tm); - e_utf8_strftime ( - end_buffer, sizeof (end_buffer), - _("%d %b %Y"), &end_tm); - strcat (buffer, " - "); - strcat (buffer, end_buffer); - } - break; - - default: - g_return_if_reached (); - } - - e_shell_sidebar_set_secondary_text (shell_sidebar, buffer); -#endif -} - -void -e_cal_shell_view_update_timezone (ECalShellView *cal_shell_view) -{ -#if 0 - ECalShellContent *cal_shell_content; - ECalShellSidebar *cal_shell_sidebar; - GnomeCalendarViewType view_type; - ECalendarView *calendar_view; - icaltimezone *timezone; - GList *clients, *iter; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - view_type = e_cal_shell_content_get_current_view (cal_shell_content); - calendar_view = e_cal_shell_content_get_calendar_view ( - cal_shell_content, view_type); - - cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; - clients = e_cal_shell_sidebar_get_clients (cal_shell_sidebar); - - timezone = calendar_config_get_icaltimezone (); - - for (iter = clients; iter != NULL; iter = iter->next) { - ECal *client = iter->data; - - if (e_cal_get_load_state (client) == E_CAL_LOAD_LOADED) - e_cal_set_default_timezone (client, timezone, NULL); - } - - e_calendar_view_set_icaltimezone (calendar_view, timezone); - - g_list_free (clients); -#endif -} diff --git a/calendar/module/e-cal-shell-view-private.h b/calendar/module/e-cal-shell-view-private.h deleted file mode 100644 index 8308e0bf7f..0000000000 --- a/calendar/module/e-cal-shell-view-private.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * e-cal-shell-view-private.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_CAL_SHELL_VIEW_PRIVATE_H -#define E_CAL_SHELL_VIEW_PRIVATE_H - -#include "e-cal-shell-view.h" - -#include -#include -#include -#include -#include - -#include "e-util/e-util.h" -#include "e-util/e-dialog-utils.h" -#include "widgets/misc/e-popup-action.h" - -#include "calendar/gui/calendar-config.h" -#include "calendar/gui/comp-util.h" -#include "calendar/gui/e-cal-list-view.h" -#include "calendar/gui/e-cal-model-tasks.h" -#include "calendar/gui/e-calendar-view.h" -#include "calendar/gui/gnome-cal.h" -/*#include "calendar/gui/goto.h"*/ -#include "calendar/gui/print.h" -#include "calendar/gui/dialogs/copy-source-dialog.h" -#include "calendar/gui/dialogs/event-editor.h" -#include "calendar/gui/dialogs/memo-editor.h" -#include "calendar/gui/dialogs/task-editor.h" - -#include "e-cal-shell-backend.h" -#include "e-cal-shell-content.h" -#include "e-cal-shell-sidebar.h" -#include "e-cal-shell-view-actions.h" - -#define E_CAL_SHELL_VIEW_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_CAL_SHELL_VIEW, ECalShellViewPrivate)) - -/* Shorthand, requires a variable named "shell_window". */ -#define ACTION(name) \ - (E_SHELL_WINDOW_ACTION_##name (shell_window)) -#define ACTION_GROUP(name) \ - (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) - -/* For use in dispose() methods. */ -#define DISPOSE(obj) \ - G_STMT_START { \ - if ((obj) != NULL) { g_object_unref (obj); (obj) = NULL; } \ - } G_STMT_END - -/* ETable Specifications */ -#define ETSPEC_FILENAME "e-calendar-table.etspec" - -G_BEGIN_DECLS - -/* Filter items are displayed in ascending order. - * Non-negative values are reserved for categories. */ -enum { - CALENDAR_FILTER_ANY_CATEGORY = -4, - CALENDAR_FILTER_UNMATCHED = -3, - CALENDAR_FILTER_ACTIVE_APPOINTMENTS = -2, - CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS = -1 -}; - -/* Search items are displayed in ascending order. */ -enum { - CALENDAR_SEARCH_SUMMARY_CONTAINS, - CALENDAR_SEARCH_DESCRIPTION_CONTAINS, - CALENDAR_SEARCH_ANY_FIELD_CONTAINS -}; - -struct _ECalShellViewPrivate { - - /* These are just for convenience. */ - ECalShellBackend *cal_shell_backend; - ECalShellContent *cal_shell_content; - ECalShellSidebar *cal_shell_sidebar; - - /* The last time explicitly selected by the user. */ - time_t base_view_time; - - EActivity *calendar_activity; - EActivity *memopad_activity; - EActivity *taskpad_activity; - - /* GConf notification IDs */ - GList *notifications; -}; - -void e_cal_shell_view_private_init - (ECalShellView *cal_shell_view, - EShellViewClass *shell_view_class); -void e_cal_shell_view_private_constructed - (ECalShellView *cal_shell_view); -void e_cal_shell_view_private_dispose - (ECalShellView *cal_shell_view); -void e_cal_shell_view_private_finalize - (ECalShellView *cal_shell_view); - -/* Private Utilities */ - -void e_cal_shell_view_actions_init - (ECalShellView *cal_shell_view); -void e_cal_shell_view_execute_search - (ECalShellView *cal_shell_view); -void e_cal_shell_view_open_event - (ECalShellView *cal_shell_view, - ECalModelComponent *comp_data); -void e_cal_shell_view_set_status_message - (ECalShellView *cal_shell_view, - const gchar *status_message, - gdouble percent); -void e_cal_shell_view_update_sidebar - (ECalShellView *cal_shell_view); -void e_cal_shell_view_update_search_filter - (ECalShellView *cal_shell_view); -void e_cal_shell_view_update_timezone - (ECalShellView *cal_shell_view); - -/* Memo Pad Utilities */ - -void e_cal_shell_view_memopad_actions_init - (ECalShellView *cal_shell_view); -void e_cal_shell_view_memopad_actions_update - (ECalShellView *cal_shell_view); -void e_cal_shell_view_memopad_open_memo - (ECalShellView *cal_shell_view, - ECalModelComponent *comp_data); -void e_cal_shell_view_memopad_set_status_message - (ECalShellView *cal_shell_view, - const gchar *status_message, - gdouble percent); - -/* Task Pad Utilities */ - -void e_cal_shell_view_taskpad_actions_init - (ECalShellView *cal_shell_view); -void e_cal_shell_view_taskpad_actions_update - (ECalShellView *cal_shell_view); -void e_cal_shell_view_taskpad_open_task - (ECalShellView *cal_shell_view, - ECalModelComponent *comp_data); -void e_cal_shell_view_taskpad_set_status_message - (ECalShellView *cal_shell_view, - const gchar *status_message, - gdouble percent); - -G_END_DECLS - -#endif /* E_CAL_SHELL_VIEW_PRIVATE_H */ diff --git a/calendar/module/e-cal-shell-view-taskpad.c b/calendar/module/e-cal-shell-view-taskpad.c deleted file mode 100644 index bdd136b6f7..0000000000 --- a/calendar/module/e-cal-shell-view-taskpad.c +++ /dev/null @@ -1,654 +0,0 @@ -/* - * e-cal-shell-view-taskpad.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-cal-shell-view-private.h" - -/* Much of this file is based on e-task-shell-view-actions.c. */ - -static void -action_calendar_taskpad_assign_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - ECalendarTable *task_table; - ECalModelComponent *comp_data; - GSList *list; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - list = e_calendar_table_get_selected (task_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - /* XXX We only open the first selected task. */ - e_cal_shell_view_taskpad_open_task (cal_shell_view, comp_data); - - /* FIXME Need to actually assign the task. */ -} - -static void -action_calendar_taskpad_clipboard_copy_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - ECalendarTable *task_table; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - e_calendar_table_copy_clipboard (task_table); -} - -static void -action_calendar_taskpad_clipboard_cut_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - ECalendarTable *task_table; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - e_calendar_table_cut_clipboard (task_table); -} - -static void -action_calendar_taskpad_clipboard_paste_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - ECalendarTable *task_table; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - e_calendar_table_paste_clipboard (task_table); -} - -static void -action_calendar_taskpad_delete_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - ECalendarTable *task_table; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - e_cal_shell_view_taskpad_set_status_message ( - cal_shell_view, _("Deleting selected tasks..."), -1.0); - e_calendar_table_delete_selected (task_table); - e_cal_shell_view_taskpad_set_status_message ( - cal_shell_view, NULL, -1.0); -} - -static void -action_calendar_taskpad_forward_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - ECalendarTable *task_table; - ECalModelComponent *comp_data; - ECalComponent *comp; - icalcomponent *clone; - GSList *list; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - list = e_calendar_table_get_selected (task_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - /* XXX We only forward the first selected task. */ - comp = e_cal_component_new (); - clone = icalcomponent_new_clone (comp_data->icalcomp); - e_cal_component_set_icalcomponent (comp, clone); - itip_send_comp ( - E_CAL_COMPONENT_METHOD_PUBLISH, comp, - comp_data->client, NULL, NULL, NULL, TRUE); - g_object_unref (comp); -} - -static void -action_calendar_taskpad_mark_complete_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - ECalendarTable *task_table; - ECalModel *model; - GSList *list, *iter; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - list = e_calendar_table_get_selected (task_table); - model = e_calendar_table_get_model (task_table); - - for (iter = list; iter != NULL; iter = iter->next) { - ECalModelComponent *comp_data = iter->data; - e_cal_model_tasks_mark_comp_complete ( - E_CAL_MODEL_TASKS (model), comp_data); - } - - g_slist_free (list); -} - -static void -action_calendar_taskpad_mark_incomplete_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - ECalendarTable *task_table; - ECalModel *model; - GSList *list, *iter; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - list = e_calendar_table_get_selected (task_table); - model = e_calendar_table_get_model (task_table); - - for (iter = list; iter != NULL; iter = iter->next) { - ECalModelComponent *comp_data = iter->data; - e_cal_model_tasks_mark_comp_incomplete ( - E_CAL_MODEL_TASKS (model), comp_data); - } - - g_slist_free (list); -} - -static void -action_calendar_taskpad_new_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - EShell *shell; - EShellView *shell_view; - EShellWindow *shell_window; - ECalShellContent *cal_shell_content; - ECalendarTable *task_table; - ECalModelComponent *comp_data; - ECal *client; - ECalComponent *comp; - CompEditor *editor; - GSList *list; - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell = e_shell_window_get_shell (shell_window); - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - list = e_calendar_table_get_selected (task_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - client = comp_data->client; - editor = task_editor_new (client, shell, COMP_EDITOR_NEW_ITEM); - comp = cal_comp_task_new_with_defaults (client); - comp_editor_edit_comp (editor, comp); - - gtk_window_present (GTK_WINDOW (editor)); - - g_object_unref (comp); - g_object_unref (client); -} - -static void -action_calendar_taskpad_open_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - ECalendarTable *task_table; - ECalModelComponent *comp_data; - GSList *list; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - list = e_calendar_table_get_selected (task_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - /* XXX We only open the first selected task. */ - e_cal_shell_view_taskpad_open_task (cal_shell_view, comp_data); -} - -static void -action_calendar_taskpad_open_url_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - ECalShellContent *cal_shell_content; - ECalendarTable *task_table; - ECalModelComponent *comp_data; - icalproperty *prop; - const gchar *uri; - GSList *list; - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - list = e_calendar_table_get_selected (task_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - - /* XXX We only open the URI of the first selected task. */ - prop = icalcomponent_get_first_property ( - comp_data->icalcomp, ICAL_URL_PROPERTY); - g_return_if_fail (prop == NULL); - - uri = icalproperty_get_url (prop); - e_show_uri (GTK_WINDOW (shell_window), uri); -} - -static void -action_calendar_taskpad_print_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - ECalendarTable *task_table; - ECalModelComponent *comp_data; - ECalComponent *comp; - icalcomponent *clone; - GtkPrintOperationAction print_action; - GSList *list; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - list = e_calendar_table_get_selected (task_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - /* XXX We only print the first selected task. */ - comp = e_cal_component_new (); - clone = icalcomponent_new_clone (comp_data->icalcomp); - print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; - e_cal_component_set_icalcomponent (comp, clone); - print_comp (comp, comp_data->client, print_action); - g_object_unref (comp); -} - -static void -action_calendar_taskpad_save_as_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - ECalendarTable *task_table; - ECalModelComponent *comp_data; - GSList *list; - gchar *filename; - gchar *string; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - list = e_calendar_table_get_selected (task_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - filename = e_file_dialog_save (_("Save as..."), NULL); - if (filename == NULL) - return; - - string = e_cal_get_component_as_string ( - comp_data->client, comp_data->icalcomp); - if (string == NULL) { - g_warning ("Could not convert task to a string"); - return; - } - - e_write_file_uri (filename, string); - - g_free (filename); - g_free (string); -} - -static GtkActionEntry calendar_taskpad_entries[] = { - - { "calendar-taskpad-assign", - NULL, - N_("_Assign Task"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_taskpad_assign_cb) }, - - { "calendar-taskpad-clipboard-copy", - GTK_STOCK_COPY, - NULL, - NULL, - N_("Copy selected tasks"), - G_CALLBACK (action_calendar_taskpad_clipboard_copy_cb) }, - - { "calendar-taskpad-clipboard-cut", - GTK_STOCK_CUT, - NULL, - NULL, - N_("Cut selected tasks"), - G_CALLBACK (action_calendar_taskpad_clipboard_cut_cb) }, - - { "calendar-taskpad-clipboard-paste", - GTK_STOCK_PASTE, - NULL, - NULL, - N_("Paste tasks from the clipboard"), - G_CALLBACK (action_calendar_taskpad_clipboard_paste_cb) }, - - { "calendar-taskpad-delete", - GTK_STOCK_DELETE, - N_("_Delete Task"), - NULL, - N_("Delete selected tasks"), - G_CALLBACK (action_calendar_taskpad_delete_cb) }, - - { "calendar-taskpad-forward", - "mail-forward", - N_("_Forward as iCalendar..."), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_taskpad_forward_cb) }, - - { "calendar-taskpad-mark-complete", - NULL, - N_("_Mark as Complete"), - NULL, - N_("Mark selected tasks as complete"), - G_CALLBACK (action_calendar_taskpad_mark_complete_cb) }, - - { "calendar-taskpad-mark-incomplete", - NULL, - N_("_Mar_k as Incomplete"), - NULL, - N_("Mark selected tasks as incomplete"), - G_CALLBACK (action_calendar_taskpad_mark_incomplete_cb) }, - - { "calendar-taskpad-new", - "stock_task", - N_("New _Task"), - NULL, - N_("Create a new task"), - G_CALLBACK (action_calendar_taskpad_new_cb) }, - - { "calendar-taskpad-open", - GTK_STOCK_OPEN, - N_("_Open Task"), - NULL, - N_("View the selected task"), - G_CALLBACK (action_calendar_taskpad_open_cb) }, - - { "calendar-taskpad-open-url", - "applications-internet", - N_("Open _Web Page"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_taskpad_open_url_cb) }, - - { "calendar-taskpad-save-as", - GTK_STOCK_SAVE_AS, - N_("_Save as iCalendar..."), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_taskpad_save_as_cb) } -}; - -static GtkActionEntry lockdown_printing_entries[] = { - - { "calendar-taskpad-print", - GTK_STOCK_PRINT, - NULL, - NULL, - N_("Print the selected task"), - G_CALLBACK (action_calendar_taskpad_print_cb) } -}; - -void -e_cal_shell_view_taskpad_actions_init (ECalShellView *cal_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - GtkActionGroup *action_group; - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - /* Calendar Actions */ - action_group = ACTION_GROUP (CALENDAR); - gtk_action_group_add_actions ( - action_group, calendar_taskpad_entries, - G_N_ELEMENTS (calendar_taskpad_entries), cal_shell_view); - - /* Lockdown Printing Actions */ - action_group = ACTION_GROUP (LOCKDOWN_PRINTING); - gtk_action_group_add_actions ( - action_group, lockdown_printing_entries, - G_N_ELEMENTS (lockdown_printing_entries), cal_shell_view); -} - -void -e_cal_shell_view_taskpad_actions_update (ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - EShellWindow *shell_window; - EShellView *shell_view; - ECalendarTable *task_table; - ETable *table; - GtkAction *action; - GSList *list, *iter; - const gchar *label; - gboolean assignable = TRUE; - gboolean editable = TRUE; - gboolean has_url = FALSE; - gboolean sensitive; - gint n_selected; - gint n_complete = 0; - gint n_incomplete = 0; - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - table = e_calendar_table_get_table (task_table); - n_selected = e_table_selected_count (table); - - list = e_calendar_table_get_selected (task_table); - for (iter = list; iter != NULL; iter = iter->next) { - ECalModelComponent *comp_data = iter->data; - icalproperty *prop; - const gchar *cap; - gboolean read_only; - - e_cal_is_read_only (comp_data->client, &read_only, NULL); - editable &= !read_only; - - cap = CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT; - if (e_cal_get_static_capability (comp_data->client, cap)) - assignable = FALSE; - - cap = CAL_STATIC_CAPABILITY_NO_CONV_TO_ASSIGN_TASK; - if (e_cal_get_static_capability (comp_data->client, cap)) - assignable = FALSE; - - prop = icalcomponent_get_first_property ( - comp_data->icalcomp, ICAL_URL_PROPERTY); - has_url |= (prop != NULL); - - prop = icalcomponent_get_first_property ( - comp_data->icalcomp, ICAL_COMPLETED_PROPERTY); - if (prop != NULL) - n_complete++; - else - n_incomplete++; - } - g_slist_free (list); - - action = ACTION (CALENDAR_TASKPAD_ASSIGN); - sensitive = (n_selected == 1) && editable && assignable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_TASKPAD_CLIPBOARD_COPY); - sensitive = (n_selected > 0); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_TASKPAD_CLIPBOARD_CUT); - sensitive = (n_selected > 0) && editable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_TASKPAD_CLIPBOARD_PASTE); - sensitive = editable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_TASKPAD_DELETE); - sensitive = (n_selected > 0) && editable; - gtk_action_set_sensitive (action, sensitive); - label = ngettext ("Delete Task", "Delete Tasks", n_selected); - g_object_set (action, "label", label, NULL); - - action = ACTION (CALENDAR_TASKPAD_FORWARD); - sensitive = (n_selected == 1); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_TASKPAD_MARK_COMPLETE); - sensitive = (n_selected > 0) && editable && (n_incomplete > 0); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_TASKPAD_MARK_INCOMPLETE); - sensitive = (n_selected > 0) && editable && (n_complete > 0); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_TASKPAD_OPEN); - sensitive = (n_selected == 1); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_TASKPAD_OPEN_URL); - sensitive = (n_selected == 1) && has_url; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_TASKPAD_PRINT); - sensitive = (n_selected == 1); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_TASKPAD_SAVE_AS); - sensitive = (n_selected == 1); - gtk_action_set_sensitive (action, sensitive); -} - -void -e_cal_shell_view_taskpad_open_task (ECalShellView *cal_shell_view, - ECalModelComponent *comp_data) -{ - EShell *shell; - EShellView *shell_view; - EShellWindow *shell_window; - CompEditor *editor; - CompEditorFlags flags = 0; - ECalComponent *comp; - icalcomponent *clone; - icalproperty *prop; - const gchar *uid; - - g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); - g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data)); - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell = e_shell_window_get_shell (shell_window); - - uid = icalcomponent_get_uid (comp_data->icalcomp); - editor = comp_editor_find_instance (uid); - - if (editor != NULL) - goto exit; - - comp = e_cal_component_new (); - clone = icalcomponent_new_clone (comp_data->icalcomp); - e_cal_component_set_icalcomponent (comp, clone); - - prop = icalcomponent_get_first_property ( - comp_data->icalcomp, ICAL_ATTENDEE_PROPERTY); - if (prop != NULL) - flags |= COMP_EDITOR_IS_ASSIGNED; - - if (itip_organizer_is_user (comp, comp_data->client)) - flags |= COMP_EDITOR_USER_ORG; - - if (!e_cal_component_has_attendees (comp)) - flags |= COMP_EDITOR_USER_ORG; - - editor = task_editor_new (comp_data->client, shell, flags); - comp_editor_edit_comp (editor, comp); - - g_object_ref (comp); - - if (flags & COMP_EDITOR_IS_ASSIGNED) - task_editor_show_assignment (TASK_EDITOR (editor)); - -exit: - gtk_window_present (GTK_WINDOW (editor)); -} - -void -e_cal_shell_view_taskpad_set_status_message (ECalShellView *cal_shell_view, - const gchar *status_message, - gdouble percent) -{ - EActivity *activity; - EShellView *shell_view; - EShellBackend *shell_backend; - - g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_backend = e_shell_view_get_shell_backend (shell_view); - - activity = cal_shell_view->priv->taskpad_activity; - - if (status_message == NULL || *status_message == '\0') { - if (activity != NULL) { - e_activity_complete (activity); - g_object_unref (activity); - activity = NULL; - } - - } else if (activity == NULL) { - activity = e_activity_new (status_message); - e_activity_set_percent (activity, percent); - e_shell_backend_add_activity (shell_backend, activity); - - } else { - e_activity_set_percent (activity, percent); - e_activity_set_primary_text (activity, status_message); - } - - cal_shell_view->priv->taskpad_activity = activity; -} diff --git a/calendar/module/e-cal-shell-view.c b/calendar/module/e-cal-shell-view.c deleted file mode 100644 index 5bf1c749a1..0000000000 --- a/calendar/module/e-cal-shell-view.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * e-cal-shell-view.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-cal-shell-view-private.h" - -static gpointer parent_class; -static GType cal_shell_view_type; - -static void -cal_shell_view_dispose (GObject *object) -{ - e_cal_shell_view_private_dispose (E_CAL_SHELL_VIEW (object)); - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -cal_shell_view_finalize (GObject *object) -{ - e_cal_shell_view_private_finalize (E_CAL_SHELL_VIEW (object)); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -cal_shell_view_constructed (GObject *object) -{ - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (parent_class)->constructed (object); - - e_cal_shell_view_private_constructed (E_CAL_SHELL_VIEW (object)); -} - -static void -cal_shell_view_update_actions (EShellView *shell_view) -{ -#if 0 - ECalShellViewPrivate *priv; - ECalShellContent *cal_shell_content; - ECalShellSidebar *cal_shell_sidebar; - EShellWindow *shell_window; - GnomeCalendar *calendar; - ECalModel *model; - ESourceSelector *selector; - ESource *source; - GtkAction *action; - GtkWidget *widget; - GList *list, *iter; - const gchar *uri = NULL; - gboolean user_created_source; - gboolean editable = TRUE; - gboolean recurring = FALSE; - gboolean sensitive; - gint n_selected; - - priv = E_CAL_SHELL_VIEW_GET_PRIVATE (shell_view); - - shell_window = e_shell_view_get_shell_window (shell_view); - - cal_shell_content = priv->cal_shell_content; - calendar = e_cal_shell_content_get_calendar (cal_shell_content); - widget = gnome_calendar_get_current_view_widget (calendar); - model = e_calendar_view_get_model (E_CALENDAR_VIEW (widget)); - - cal_shell_sidebar = priv->cal_shell_sidebar; - selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); - - list = e_calendar_view_get_selected_events (E_CALENDAR_VIEW (widget)); - n_selected = g_list_length (list); - - for (iter = list; iter != NULL; iter = iter->next) { - ECalModelComponent *comp_data = iter->data; - gboolean read_only; - - e_cal_is_read_only (comp_data->client, &read_only, NULL); - editable &= !read_only; - - if (e_cal_util_component_has_recurrences (comp_data->icalcomp)) - recurring |= TRUE; - else if (e_cal_util_component_is_instance (comp_data->icalcomp)) - recurring |= TRUE; - } - - source = e_source_selector_peek_primary_selection (selector); - if (source != NULL) - uri = e_source_peek_relative_uri (source); - user_created_source = (uri != NULL && strcmp (uri, "system") != 0); - - action = ACTION (CALENDAR_COPY); - sensitive = (source != NULL); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_DELETE); - sensitive = user_created_source; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_PROPERTIES); - sensitive = (source != NULL); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_RENAME); - sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (EVENT_CLIPBOARD_COPY); - sensitive = (n_selected > 0); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (EVENT_CLIPBOARD_CUT); - sensitive = (n_selected > 0) && editable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (EVENT_CLIPBOARD_PASTE); - sensitive = editable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (EVENT_DELETE); - sensitive = (n_selected > 0) && editable && !recurring; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (EVENT_DELETE_OCCURRENCE); - sensitive = (n_selected > 0) && editable && recurring; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (EVENT_DELETE_OCCURRENCE_ALL); - sensitive = (n_selected > 0) && editable && recurring; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (EVENT_OPEN); - sensitive = (n_selected == 1); - gtk_action_set_sensitive (action, sensitive); -#endif -} - -static void -cal_shell_view_class_init (ECalShellViewClass *class, - GTypeModule *type_module) -{ - GObjectClass *object_class; - EShellViewClass *shell_view_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (ECalShellViewPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->dispose = cal_shell_view_dispose; - object_class->finalize = cal_shell_view_finalize; - object_class->constructed = cal_shell_view_constructed; - - shell_view_class = E_SHELL_VIEW_CLASS (class); - shell_view_class->label = _("Calendar"); - shell_view_class->icon_name = "x-office-calendar"; - shell_view_class->ui_definition = "evolution-calendars.ui"; - shell_view_class->ui_manager_id = "org.gnome.evolution.calendars"; - shell_view_class->search_options = "/calendar-search-options"; - shell_view_class->search_rules = "caltypes.xml"; - shell_view_class->new_shell_content = e_cal_shell_content_new; - shell_view_class->new_shell_sidebar = e_cal_shell_sidebar_new; - shell_view_class->update_actions = cal_shell_view_update_actions; -} - -static void -cal_shell_view_init (ECalShellView *cal_shell_view, - EShellViewClass *shell_view_class) -{ - cal_shell_view->priv = - E_CAL_SHELL_VIEW_GET_PRIVATE (cal_shell_view); - - e_cal_shell_view_private_init (cal_shell_view, shell_view_class); -} - -GType -e_cal_shell_view_get_type (void) -{ - return cal_shell_view_type; -} - -void -e_cal_shell_view_register_type (GTypeModule *type_module) -{ - const GTypeInfo type_info = { - sizeof (ECalShellViewClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) cal_shell_view_class_init, - (GClassFinalizeFunc) NULL, - type_module, - sizeof (ECalShellView), - 0, /* n_preallocs */ - (GInstanceInitFunc) cal_shell_view_init, - NULL /* value_table */ - }; - - cal_shell_view_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_VIEW, - "ECalShellView", &type_info, 0); -} - -GnomeCalendar * -e_cal_shell_view_get_calendar (ECalShellView *cal_shell_view) -{ - g_return_val_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view), NULL); - - /* FIXME */ - return NULL; -} diff --git a/calendar/module/e-cal-shell-view.h b/calendar/module/e-cal-shell-view.h deleted file mode 100644 index 67fa15220c..0000000000 --- a/calendar/module/e-cal-shell-view.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * e-cal-shell-view.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_CAL_SHELL_VIEW_H -#define E_CAL_SHELL_VIEW_H - -#include -#include -#include - -/* Standard GObject macros */ -#define E_TYPE_CAL_SHELL_VIEW \ - (e_cal_shell_view_get_type ()) -#define E_CAL_SHELL_VIEW(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_CAL_SHELL_VIEW, ECalShellView)) -#define E_CAL_SHELL_VIEW_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_CAL_SHELL_VIEW, ECalShellViewClass)) -#define E_IS_CAL_SHELL_VIEW(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_CAL_SHELL_VIEW)) -#define E_IS_CAL_SHELL_VIEW_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_CAL_SHELL_VIEW)) -#define E_CAL_SHELL_VIEW_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_CAL_SHELL_VIEW, ECalShellViewClass)) - -G_BEGIN_DECLS - -typedef struct _ECalShellView ECalShellView; -typedef struct _ECalShellViewClass ECalShellViewClass; -typedef struct _ECalShellViewPrivate ECalShellViewPrivate; - -struct _ECalShellView { - EShellView parent; - ECalShellViewPrivate *priv; -}; - -struct _ECalShellViewClass { - EShellViewClass parent_class; -}; - -GType e_cal_shell_view_get_type (void); -void e_cal_shell_view_register_type (GTypeModule *type_module); -GnomeCalendar * e_cal_shell_view_get_calendar (ECalShellView *cal_shell_view); - -G_END_DECLS - -#endif /* E_CAL_SHELL_VIEW_H */ diff --git a/calendar/module/e-memo-shell-backend.c b/calendar/module/e-memo-shell-backend.c deleted file mode 100644 index d2734e066a..0000000000 --- a/calendar/module/e-memo-shell-backend.c +++ /dev/null @@ -1,613 +0,0 @@ -/* - * e-memo-shell-backend.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-memo-shell-backend.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "shell/e-shell.h" -#include "shell/e-shell-backend.h" -#include "shell/e-shell-window.h" - -#include "calendar/common/authentication.h" -#include "calendar/gui/calendar-config.h" -#include "calendar/gui/comp-util.h" -#include "calendar/gui/dialogs/calendar-setup.h" -#include "calendar/gui/dialogs/memo-editor.h" - -#include "e-memo-shell-migrate.h" -#include "e-memo-shell-view.h" - -#define E_MEMO_SHELL_BACKEND_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_MEMO_SHELL_BACKEND, EMemoShellBackendPrivate)) - -#define WEB_BASE_URI "webcal://" -#define PERSONAL_RELATIVE_URI "system" - -struct _EMemoShellBackendPrivate { - ESourceList *source_list; -}; - -enum { - PROP_0, - PROP_SOURCE_LIST -}; - -static gpointer parent_class; -static GType memo_shell_backend_type; - -static void -memo_module_ensure_sources (EShellBackend *shell_backend) -{ - /* XXX This is basically the same algorithm across all modules. - * Maybe we could somehow integrate this into EShellBackend? */ - - EMemoShellBackendPrivate *priv; - ESourceGroup *on_this_computer; - ESourceGroup *on_the_web; - ESource *personal; - GSList *groups, *iter; - const gchar *data_dir; - const gchar *name; - gchar *base_uri; - gchar *filename; - - on_this_computer = NULL; - on_the_web = NULL; - personal = NULL; - - priv = E_MEMO_SHELL_BACKEND_GET_PRIVATE (shell_backend); - - if (!e_cal_get_sources (&priv->source_list, E_CAL_SOURCE_TYPE_JOURNAL, NULL)) { - g_warning ("Could not get memo sources from GConf!"); - return; - } - - data_dir = e_shell_backend_get_data_dir (shell_backend); - filename = g_build_filename (data_dir, "local", NULL); - base_uri = g_filename_to_uri (filename, NULL, NULL); - g_free (filename); - - groups = e_source_list_peek_groups (priv->source_list); - for (iter = groups; iter != NULL; iter = iter->next) { - ESourceGroup *source_group = iter->data; - const gchar *group_base_uri; - - group_base_uri = e_source_group_peek_base_uri (source_group); - - /* Compare only "file://" part. If the user's home - * changes, we do not want to create another group. */ - if (on_this_computer == NULL && - strncmp (base_uri, group_base_uri, 7) == 0) - on_this_computer = source_group; - - else if (on_the_web == NULL && - strcmp (WEB_BASE_URI, group_base_uri) == 0) - on_the_web = source_group; - } - - name = _("On This Computer"); - - if (on_this_computer != NULL) { - GSList *sources; - const gchar *group_base_uri; - - /* Force the group name to the current locale. */ - e_source_group_set_name (on_this_computer, name); - - sources = e_source_group_peek_sources (on_this_computer); - group_base_uri = e_source_group_peek_base_uri (on_this_computer); - - /* Make sure this group includes a "Personal" source. */ - for (iter = sources; iter != NULL; iter = iter->next) { - ESource *source = iter->data; - const gchar *relative_uri; - - relative_uri = e_source_peek_relative_uri (source); - if (relative_uri == NULL) - continue; - - if (strcmp (PERSONAL_RELATIVE_URI, relative_uri) != 0) - continue; - - personal = source; - break; - } - - /* Make sure we have the correct base URI. This can - * change when the user's home directory changes. */ - if (strcmp (base_uri, group_base_uri) != 0) { - e_source_group_set_base_uri ( - on_this_computer, base_uri); - - /* XXX We shouldn't need this sync call here as - * set_base_uri() results in synching to GConf, - * but that happens in an idle loop and too late - * to prevent the user from seeing a "Cannot - * Open ... because of invalid URI" error. */ - e_source_list_sync (priv->source_list, NULL); - } - - } else { - ESourceGroup *source_group; - - source_group = e_source_group_new (name, base_uri); - e_source_list_add_group (priv->source_list, source_group, -1); - g_object_unref (source_group); - } - - name = _("Personal"); - - if (personal == NULL) { - ESource *source; - GSList *selected; - gchar *primary; - - source = e_source_new (name, PERSONAL_RELATIVE_URI); - e_source_group_add_source (on_this_computer, source, -1); - g_object_unref (source); - - primary = calendar_config_get_primary_memos (); - selected = calendar_config_get_memos_selected (); - - if (primary == NULL && selected == NULL) { - const gchar *uid; - - uid = e_source_peek_uid (source); - selected = g_slist_prepend (NULL, g_strdup (uid)); - - calendar_config_set_primary_memos (uid); - calendar_config_set_memos_selected (selected); - } - - g_slist_foreach (selected, (GFunc) g_free, NULL); - g_slist_free (selected); - g_free (primary); - } else { - /* Force the source name to the current locale. */ - e_source_set_name (personal, name); - } - - name = _("On The Web"); - - if (on_the_web == NULL) { - ESourceGroup *source_group; - - source_group = e_source_group_new (name, WEB_BASE_URI); - e_source_list_add_group (priv->source_list, source_group, -1); - g_object_unref (source_group); - } else { - /* Force the group name to the current locale. */ - e_source_group_set_name (on_the_web, name); - } - - g_free (base_uri); -} - -static void -memo_module_cal_opened_cb (ECal *cal, - ECalendarStatus status, - GtkAction *action) -{ - EShell *shell; - ECalComponent *comp; - CompEditor *editor; - CompEditorFlags flags = 0; - const gchar *action_name; - - /* FIXME Pass this in. */ - shell = e_shell_get_default (); - - /* XXX Handle errors better. */ - if (status != E_CALENDAR_STATUS_OK) - return; - - action_name = gtk_action_get_name (action); - - flags |= COMP_EDITOR_NEW_ITEM; - if (strcmp (action_name, "memo-shared-new") == 0) { - flags |= COMP_EDITOR_IS_SHARED; - flags |= COMP_EDITOR_USER_ORG; - } - - editor = memo_editor_new (cal, shell, flags); - comp = cal_comp_memo_new_with_defaults (cal); - comp_editor_edit_comp (editor, comp); - - gtk_window_present (GTK_WINDOW (editor)); - - g_object_unref (comp); - g_object_unref (cal); -} - -static void -action_memo_new_cb (GtkAction *action, - EShellWindow *shell_window) -{ - ECal *cal = NULL; - ECalSourceType source_type; - ESourceList *source_list; - gchar *uid; - - /* This callback is used for both memos and shared memos. */ - - source_type = E_CAL_SOURCE_TYPE_JOURNAL; - - if (!e_cal_get_sources (&source_list, source_type, NULL)) { - g_warning ("Could not get memo sources from GConf!"); - return; - } - - uid = calendar_config_get_primary_memos (); - - if (uid != NULL) { - ESource *source; - - source = e_source_list_peek_source_by_uid (source_list, uid); - if (source != NULL) - cal = auth_new_cal_from_source (source, source_type); - g_free (uid); - } - - if (cal == NULL) - cal = auth_new_cal_from_default (source_type); - - g_return_if_fail (cal != NULL); - - g_signal_connect ( - cal, "cal-opened", - G_CALLBACK (memo_module_cal_opened_cb), action); - - e_cal_open_async (cal, FALSE); -} - -static void -action_memo_list_new_cb (GtkAction *action, - EShellWindow *shell_window) -{ - calendar_setup_new_memo_list (GTK_WINDOW (shell_window)); -} - -static GtkActionEntry item_entries[] = { - - { "memo-new", - "stock_insert-note", - NC_("New", "Mem_o"), - "o", - N_("Create a new memo"), - G_CALLBACK (action_memo_new_cb) }, - - { "memo-shared-new", - "stock_insert-note", - N_("_Shared Memo"), - "h", - N_("Create a new shared memo"), - G_CALLBACK (action_memo_new_cb) } -}; - -static GtkActionEntry source_entries[] = { - - { "memo-list-new", - "stock_notes", - NC_("New", "Memo Li_st"), - NULL, - N_("Create a new memo list"), - G_CALLBACK (action_memo_list_new_cb) } -}; - -static gboolean -memo_module_handle_uri_cb (EShellBackend *shell_backend, - const gchar *uri) -{ - EShell *shell; - CompEditor *editor; - CompEditorFlags flags = 0; - ECal *client; - ECalComponent *comp; - ESource *source; - ESourceList *source_list; - ECalSourceType source_type; - EUri *euri; - icalcomponent *icalcomp; - const gchar *cp; - gchar *source_uid = NULL; - gchar *comp_uid = NULL; - gchar *comp_rid = NULL; - gboolean handled = FALSE; - GError *error = NULL; - - source_type = E_CAL_SOURCE_TYPE_JOURNAL; - shell = e_shell_backend_get_shell (shell_backend); - - if (strncmp (uri, "memo:", 5) != 0) - return FALSE; - - euri = e_uri_new (uri); - cp = euri->query; - if (cp == NULL) - goto exit; - - while (*cp != '\0') { - gchar *header; - gchar *content; - gsize header_len; - gsize content_len; - - header_len = strcspn (cp, "=&"); - - /* If it's malformed, give up. */ - if (cp[header_len] != '=') - break; - - header = (gchar *) cp; - header[header_len] = '\0'; - cp += header_len + 1; - - content_len = strcspn (cp, "&"); - - content = g_strndup (cp, content_len); - if (g_ascii_strcasecmp (header, "source-uid") == 0) - source_uid = g_strdup (content); - else if (g_ascii_strcasecmp (header, "comp-uid") == 0) - comp_uid = g_strdup (content); - else if (g_ascii_strcasecmp (header, "comp-rid") == 0) - comp_rid = g_strdup (content); - g_free (content); - - cp += content_len; - if (*cp == '&') { - cp++; - if (strcmp (cp, "amp;") == 0) - cp += 4; - } - } - - if (source_uid == NULL || comp_uid == NULL) - goto exit; - - /* URI is valid, so consider it handled. Whether - * we successfully open it is another matter... */ - handled = TRUE; - - if (!e_cal_get_sources (&source_list, source_type, NULL)) { - g_printerr ("Could not get memo sources from GConf!\n"); - goto exit; - } - - source = e_source_list_peek_source_by_uid (source_list, source_uid); - if (source == NULL) { - g_printerr ("No source for UID `%s'\n", source_uid); - g_object_unref (source_list); - goto exit; - } - - client = auth_new_cal_from_source (source, source_type); - if (client == NULL || !e_cal_open (client, TRUE, &error)) { - g_printerr ("%s\n", error->message); - g_object_unref (source_list); - g_error_free (error); - goto exit; - } - - /* XXX Copied from e_memo_shell_view_open_memo(). - * Clearly a new utility function is needed. */ - - editor = comp_editor_find_instance (comp_uid); - - if (editor != NULL) - goto present; - - if (!e_cal_get_object (client, comp_uid, comp_rid, &icalcomp, &error)) { - g_printerr ("%s\n", error->message); - g_object_unref (source_list); - g_error_free (error); - goto exit; - } - - comp = e_cal_component_new (); - e_cal_component_set_icalcomponent (comp, icalcomp); - - if (e_cal_component_has_organizer (comp)) - flags |= COMP_EDITOR_IS_SHARED; - - if (itip_organizer_is_user (comp, client)) - flags |= COMP_EDITOR_USER_ORG; - - editor = memo_editor_new (client, shell, flags); - comp_editor_edit_comp (editor, comp); - - g_object_unref (comp); - -present: - gtk_window_present (GTK_WINDOW (editor)); - - g_object_unref (source_list); - g_object_unref (client); - -exit: - g_free (source_uid); - g_free (comp_uid); - g_free (comp_rid); - - e_uri_free (euri); - - return handled; -} - -static void -memo_module_window_created_cb (EShellBackend *shell_backend, - GtkWindow *window) -{ - const gchar *module_name; - - if (!E_IS_SHELL_WINDOW (window)) - return; - - module_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name; - - e_shell_window_register_new_item_actions ( - E_SHELL_WINDOW (window), module_name, - item_entries, G_N_ELEMENTS (item_entries)); - - e_shell_window_register_new_source_actions ( - E_SHELL_WINDOW (window), module_name, - source_entries, G_N_ELEMENTS (source_entries)); -} - -static void -memo_shell_backend_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_SOURCE_LIST: - g_value_set_object ( - value, - e_memo_shell_backend_get_source_list ( - E_MEMO_SHELL_BACKEND (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -memo_shell_backend_dispose (GObject *object) -{ - EMemoShellBackendPrivate *priv; - - priv = E_MEMO_SHELL_BACKEND_GET_PRIVATE (object); - - if (priv->source_list != NULL) { - g_object_unref (priv->source_list); - priv->source_list = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -memo_shell_backend_constructed (GObject *object) -{ - EShell *shell; - EShellBackend *shell_backend; - - shell_backend = E_SHELL_BACKEND (object); - shell = e_shell_backend_get_shell (shell_backend); - - memo_module_ensure_sources (shell_backend); - - g_signal_connect_swapped ( - shell, "handle-uri", - G_CALLBACK (memo_module_handle_uri_cb), shell_backend); - - g_signal_connect_swapped ( - shell, "window-created", - G_CALLBACK (memo_module_window_created_cb), shell_backend); -} - -static void -memo_shell_backend_class_init (EMemoShellBackendClass *class) -{ - GObjectClass *object_class; - EShellBackendClass *shell_backend_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (EMemoShellBackendPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->get_property = memo_shell_backend_get_property; - object_class->dispose = memo_shell_backend_dispose; - object_class->constructed = memo_shell_backend_constructed; - - shell_backend_class = E_SHELL_BACKEND_CLASS (class); - shell_backend_class->shell_view_type = E_TYPE_MEMO_SHELL_VIEW; - shell_backend_class->name = "memos"; - shell_backend_class->aliases = ""; - shell_backend_class->schemes = "memo"; - shell_backend_class->sort_order = 500; - shell_backend_class->start = NULL; - shell_backend_class->is_busy = NULL; - shell_backend_class->shutdown = NULL; - shell_backend_class->migrate = e_memo_shell_backend_migrate; - - g_object_class_install_property ( - object_class, - PROP_SOURCE_LIST, - g_param_spec_object ( - "source-list", - _("Source List"), - _("The registry of memo lists"), - E_TYPE_SOURCE_LIST, - G_PARAM_READABLE)); -} - -static void -memo_shell_backend_init (EMemoShellBackend *memo_shell_backend) -{ - memo_shell_backend->priv = - E_MEMO_SHELL_BACKEND_GET_PRIVATE (memo_shell_backend); -} - -GType -e_memo_shell_backend_get_type (void) -{ - return memo_shell_backend_type; -} - -void -e_memo_shell_backend_register_type (GTypeModule *type_module) -{ - const GTypeInfo type_info = { - sizeof (EMemoShellBackendClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) memo_shell_backend_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (EMemoShellBackend), - 0, /* n_preallocs */ - (GInstanceInitFunc) memo_shell_backend_init, - NULL /* value_table */ - }; - - memo_shell_backend_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_BACKEND, - "EMemoShellBackend", &type_info, 0); -} - -ESourceList * -e_memo_shell_backend_get_source_list (EMemoShellBackend *memo_shell_backend) -{ - g_return_val_if_fail ( - E_IS_MEMO_SHELL_BACKEND (memo_shell_backend), NULL); - - return memo_shell_backend->priv->source_list; -} diff --git a/calendar/module/e-memo-shell-backend.h b/calendar/module/e-memo-shell-backend.h deleted file mode 100644 index 37fe41a784..0000000000 --- a/calendar/module/e-memo-shell-backend.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * e-memo-shell-backend.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_MEMO_SHELL_BACKEND_H -#define E_MEMO_SHELL_BACKEND_H - -#include -#include - -/* Standard GObject macros */ -#define E_TYPE_MEMO_SHELL_BACKEND \ - (e_memo_shell_backend_get_type ()) -#define E_MEMO_SHELL_BACKEND(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_MEMO_SHELL_BACKEND, EMemoShellBackend)) -#define E_MEMO_SHELL_BACKEND_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_MEMO_SHELL_BACKEND, EMemoShellBackendClass)) -#define E_IS_MEMO_SHELL_BACKEND(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_MEMO_SHELL_BACKEND)) -#define E_IS_MEMO_SHELL_BACKEND_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_MEMO_SHELL_BACKEND)) -#define E_MEMO_SHELL_BACKEND_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_MEMO_SHELL_BACKEND, EMemoShellBackendClass)) - -G_BEGIN_DECLS - -typedef struct _EMemoShellBackend EMemoShellBackend; -typedef struct _EMemoShellBackendClass EMemoShellBackendClass; -typedef struct _EMemoShellBackendPrivate EMemoShellBackendPrivate; - -struct _EMemoShellBackend { - EShellBackend parent; - EMemoShellBackendPrivate *priv; -}; - -struct _EMemoShellBackendClass { - EShellBackendClass parent_class; -}; - -GType e_memo_shell_backend_get_type (void); -void e_memo_shell_backend_register_type - (GTypeModule *type_module); -ESourceList * e_memo_shell_backend_get_source_list - (EMemoShellBackend *memo_shell_backend); - -G_END_DECLS - -#endif /* E_MEMO_SHELL_BACKEND_H */ diff --git a/calendar/module/e-memo-shell-content.c b/calendar/module/e-memo-shell-content.c deleted file mode 100644 index ce020158ae..0000000000 --- a/calendar/module/e-memo-shell-content.c +++ /dev/null @@ -1,676 +0,0 @@ -/* - * e-memo-shell-content.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-memo-shell-content.h" - -#include - -#include "e-util/gconf-bridge.h" - -#include "calendar/gui/calendar-config.h" -#include "calendar/gui/comp-util.h" -#include "calendar/gui/e-cal-model-memos.h" -#include "calendar/gui/e-memo-table.h" -#include "calendar/gui/e-memo-table-config.h" - -#include "widgets/menus/gal-view-etable.h" - -#define E_MEMO_SHELL_CONTENT_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_MEMO_SHELL_CONTENT, EMemoShellContentPrivate)) - -#define E_MEMO_TABLE_DEFAULT_STATE \ - "" \ - "" \ - " " \ - " " \ - " " \ - " " \ - "" - -struct _EMemoShellContentPrivate { - GtkWidget *paned; - GtkWidget *memo_table; - GtkWidget *memo_preview; - - ECalModel *memo_model; - EMemoTableConfig *table_config; - GalViewInstance *view_instance; - - gchar *current_uid; -}; - -enum { - PROP_0, - PROP_MODEL, - PROP_PREVIEW_VISIBLE -}; - -enum { - TARGET_VCALENDAR -}; - -static GtkTargetEntry drag_types[] = { - { (gchar *) "text/calendar", 0, TARGET_VCALENDAR }, - { (gchar *) "text/x-calendar", 0, TARGET_VCALENDAR } -}; - -static gpointer parent_class; -static GType memo_shell_content_type; - -static void -memo_shell_content_display_view_cb (EMemoShellContent *memo_shell_content, - GalView *gal_view) -{ - EMemoTable *memo_table; - ETable *table; - - if (!GAL_IS_VIEW_ETABLE (gal_view)) - return; - - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - table = e_memo_table_get_table (memo_table); - - gal_view_etable_attach_table (GAL_VIEW_ETABLE (gal_view), table); -} - -static void -memo_shell_content_table_foreach_cb (gint model_row, - gpointer user_data) -{ - ECalModelComponent *comp_data; - icalcomponent *clone; - icalcomponent *vcal; - gchar *string; - - struct { - ECalModel *model; - GSList *list; - } *foreach_data = user_data; - - comp_data = e_cal_model_get_component_at ( - foreach_data->model, model_row); - - vcal = e_cal_util_new_top_level (); - clone = icalcomponent_new_clone (comp_data->icalcomp); - e_cal_util_add_timezones_from_component (vcal, comp_data->icalcomp); - icalcomponent_add_component (vcal, clone); - - /* String is owned by libical; do not free. */ - string = icalcomponent_as_ical_string (vcal); - if (string != NULL) { - ESource *source; - const gchar *source_uid; - - source = e_cal_get_source (comp_data->client); - source_uid = e_source_peek_uid (source); - - foreach_data->list = g_slist_prepend ( - foreach_data->list, - g_strdup_printf ("%s\n%s", source_uid, string)); - } - - icalcomponent_free (vcal); -} - -static void -memo_shell_content_table_drag_data_get_cb (EMemoShellContent *memo_shell_content, - gint row, - gint col, - GdkDragContext *context, - GtkSelectionData *selection_data, - guint info, - guint time) -{ - EMemoTable *memo_table; - ETable *table; - - struct { - ECalModel *model; - GSList *list; - } foreach_data; - - if (info != TARGET_VCALENDAR) - return; - - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - table = e_memo_table_get_table (memo_table); - - foreach_data.model = e_memo_table_get_model (memo_table); - foreach_data.list = NULL; - - e_table_selected_row_foreach ( - table, memo_shell_content_table_foreach_cb, - &foreach_data); - - if (foreach_data.list != NULL) { - cal_comp_selection_set_string_list ( - selection_data, foreach_data.list); - g_slist_foreach (foreach_data.list, (GFunc) g_free, NULL); - g_slist_free (foreach_data.list); - } -} - -static void -memo_shell_content_table_drag_data_delete_cb (EMemoShellContent *memo_shell_content, - gint row, - gint col, - GdkDragContext *context) -{ - /* Moved components are deleted from source immediately when moved, - * because some of them can be part of destination source, and we - * don't want to delete not-moved memos. There is no such information - * which event has been moved and which not, so skip this method. */ -} - -static void -memo_shell_content_cursor_change_cb (EMemoShellContent *memo_shell_content, - gint row, - ETable *table) -{ - ECalComponentPreview *memo_preview; - EMemoTable *memo_table; - ECalModel *memo_model; - ECalModelComponent *comp_data; - ECalComponent *comp; - const gchar *uid; - - memo_model = e_memo_shell_content_get_memo_model (memo_shell_content); - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - memo_preview = e_memo_shell_content_get_memo_preview (memo_shell_content); - - if (e_table_selected_count (table) != 1) { - e_cal_component_preview_clear (memo_preview); - return; - } - - row = e_table_get_cursor_row (table); - comp_data = e_cal_model_get_component_at (memo_model, row); - - comp = e_cal_component_new (); - e_cal_component_set_icalcomponent ( - comp, icalcomponent_new_clone (comp_data->icalcomp)); - e_cal_component_preview_display ( - memo_preview, comp_data->client, comp); - - e_cal_component_get_uid (comp, &uid); - g_free (memo_shell_content->priv->current_uid); - memo_shell_content->priv->current_uid = g_strdup (uid); - - g_object_unref (comp); -} - -static void -memo_shell_content_selection_change_cb (EMemoShellContent *memo_shell_content, - ETable *table) -{ - ECalComponentPreview *memo_preview; - - memo_preview = e_memo_shell_content_get_memo_preview (memo_shell_content); - - /* XXX Old code emits a "selection-changed" signal here. */ - - if (e_table_selected_count (table) != 1) - e_cal_component_preview_clear (memo_preview); -} - -static void -memo_shell_content_model_row_changed_cb (EMemoShellContent *memo_shell_content, - gint row, - ETableModel *model) -{ - ECalModelComponent *comp_data; - EMemoTable *memo_table; - ETable *table; - const gchar *current_uid; - const gchar *uid; - - current_uid = memo_shell_content->priv->current_uid; - if (current_uid == NULL) - return; - - comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row); - if (comp_data == NULL) - return; - - uid = icalcomponent_get_uid (comp_data->icalcomp); - if (g_strcmp0 (uid, current_uid) != 0) - return; - - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - table = e_memo_table_get_table (memo_table); - - memo_shell_content_cursor_change_cb (memo_shell_content, 0, table); -} - -static void -memo_shell_content_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_PREVIEW_VISIBLE: - e_memo_shell_content_set_preview_visible ( - E_MEMO_SHELL_CONTENT (object), - g_value_get_boolean (value)); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -memo_shell_content_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_MODEL: - g_value_set_object ( - value, e_memo_shell_content_get_memo_model ( - E_MEMO_SHELL_CONTENT (object))); - return; - - case PROP_PREVIEW_VISIBLE: - g_value_set_boolean ( - value, e_memo_shell_content_get_preview_visible ( - E_MEMO_SHELL_CONTENT (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -memo_shell_content_dispose (GObject *object) -{ - EMemoShellContentPrivate *priv; - - priv = E_MEMO_SHELL_CONTENT_GET_PRIVATE (object); - - if (priv->paned != NULL) { - g_object_unref (priv->paned); - priv->paned = NULL; - } - - if (priv->memo_table != NULL) { - g_object_unref (priv->memo_table); - priv->memo_table = NULL; - } - - if (priv->memo_preview != NULL) { - g_object_unref (priv->memo_preview); - priv->memo_preview = NULL; - } - - if (priv->memo_model != NULL) { - g_object_unref (priv->memo_model); - priv->memo_model = NULL; - } - - if (priv->table_config != NULL) { - g_object_unref (priv->table_config); - priv->table_config = NULL; - } - - if (priv->view_instance != NULL) { - g_object_unref (priv->view_instance); - priv->view_instance = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -memo_shell_content_finalize (GObject *object) -{ - EMemoShellContentPrivate *priv; - - priv = E_MEMO_SHELL_CONTENT_GET_PRIVATE (object); - - g_free (priv->current_uid); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -memo_shell_content_constructed (GObject *object) -{ - EMemoShellContentPrivate *priv; - EShellContent *shell_content; - EShellView *shell_view; - GalViewInstance *view_instance; - ETable *table; - GConfBridge *bridge; - GtkWidget *container; - GtkWidget *widget; - const gchar *key; - - priv = E_MEMO_SHELL_CONTENT_GET_PRIVATE (object); - - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (parent_class)->constructed (object); - - shell_content = E_SHELL_CONTENT (object); - shell_view = e_shell_content_get_shell_view (shell_content); - - /* Build content widgets. */ - - container = GTK_WIDGET (object); - - widget = gtk_vpaned_new (); - gtk_container_add (GTK_CONTAINER (container), widget); - priv->paned = g_object_ref (widget); - gtk_widget_show (widget); - - container = widget; - - widget = e_memo_table_new (shell_view, priv->memo_model); - gtk_paned_add1 (GTK_PANED (container), widget); - priv->memo_table = g_object_ref (widget); - gtk_widget_show (widget); - - widget = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy ( - GTK_SCROLLED_WINDOW (widget), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type ( - GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); - gtk_paned_add2 (GTK_PANED (container), widget); - gtk_widget_show (widget); - - container = widget; - - widget = e_cal_component_preview_new (); - e_cal_component_preview_set_default_timezone ( - E_CAL_COMPONENT_PREVIEW (widget), - calendar_config_get_icaltimezone ()); - gtk_container_add (GTK_CONTAINER (container), widget); - priv->memo_preview = g_object_ref (widget); - gtk_widget_show (widget); - - /* Configure the memo table. */ - - widget = E_MEMO_TABLE (priv->memo_table)->etable; - table = e_table_scrolled_get_table (E_TABLE_SCROLLED (widget)); - - priv->table_config = e_memo_table_config_new ( - E_MEMO_TABLE (priv->memo_table)); - - e_table_set_state (table, E_MEMO_TABLE_DEFAULT_STATE); - - e_table_drag_source_set ( - table, GDK_BUTTON1_MASK, - drag_types, G_N_ELEMENTS (drag_types), - GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_ASK); - - g_signal_connect_swapped ( - table, "table-drag-data-get", - G_CALLBACK (memo_shell_content_table_drag_data_get_cb), - object); - - g_signal_connect_swapped ( - table, "table-drag-data-delete", - G_CALLBACK (memo_shell_content_table_drag_data_delete_cb), - object); - - g_signal_connect_swapped ( - table, "cursor-change", - G_CALLBACK (memo_shell_content_cursor_change_cb), - object); - - g_signal_connect_swapped ( - table, "selection-change", - G_CALLBACK (memo_shell_content_selection_change_cb), - object); - - g_signal_connect_swapped ( - priv->memo_model, "model-row-changed", - G_CALLBACK (memo_shell_content_model_row_changed_cb), - object); - - /* Load the view instance. */ - - view_instance = e_shell_view_new_view_instance (shell_view, NULL); - g_signal_connect_swapped ( - view_instance, "display-view", - G_CALLBACK (memo_shell_content_display_view_cb), - object); - gal_view_instance_load (view_instance); - priv->view_instance = view_instance; - - /* Bind GObject properties to GConf keys. */ - - bridge = gconf_bridge_get (); - - object = G_OBJECT (priv->paned); - key = "/apps/evolution/calendar/display/memo_vpane_position"; - gconf_bridge_bind_property_delayed (bridge, key, object, "position"); -} - -static guint32 -memo_shell_content_check_state (EShellContent *shell_content) -{ - EMemoShellContent *memo_shell_content; - EMemoTable *memo_table; - ETable *table; - GSList *list, *iter; - gboolean editable = TRUE; - gboolean has_url = FALSE; - gint n_selected; - guint32 state = 0; - - memo_shell_content = E_MEMO_SHELL_CONTENT (shell_content); - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - - table = e_memo_table_get_table (memo_table); - n_selected = e_table_selected_count (table); - - list = e_memo_table_get_selected (memo_table); - for (iter = list; iter != NULL; iter = iter->next) { - ECalModelComponent *comp_data = iter->data; - icalproperty *prop; - gboolean read_only; - - e_cal_is_read_only (comp_data->client, &read_only, NULL); - editable &= !read_only; - - prop = icalcomponent_get_first_property ( - comp_data->icalcomp, ICAL_URL_PROPERTY); - has_url |= (prop != NULL); - } - g_slist_free (list); - - if (n_selected == 1) - state |= E_MEMO_SHELL_CONTENT_SELECTION_SINGLE; - if (n_selected > 1) - state |= E_MEMO_SHELL_CONTENT_SELECTION_MULTIPLE; - if (editable) - state |= E_MEMO_SHELL_CONTENT_SELECTION_CAN_EDIT; - if (has_url) - state |= E_MEMO_SHELL_CONTENT_SELECTION_HAS_URL; - - return state; -} - -static void -memo_shell_content_class_init (EMemoShellContentClass *class) -{ - GObjectClass *object_class; - EShellContentClass *shell_content_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (EMemoShellContentPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->set_property = memo_shell_content_set_property; - object_class->get_property = memo_shell_content_get_property; - object_class->dispose = memo_shell_content_dispose; - object_class->finalize = memo_shell_content_finalize; - object_class->constructed = memo_shell_content_constructed; - - shell_content_class = E_SHELL_CONTENT_CLASS (class); - shell_content_class->check_state = memo_shell_content_check_state; - - g_object_class_install_property ( - object_class, - PROP_MODEL, - g_param_spec_object ( - "model", - _("Model"), - _("The memo table model"), - E_TYPE_CAL_MODEL, - G_PARAM_READABLE)); - - g_object_class_install_property ( - object_class, - PROP_PREVIEW_VISIBLE, - g_param_spec_boolean ( - "preview-visible", - _("Preview is Visible"), - _("Whether the preview pane is visible"), - TRUE, - G_PARAM_READWRITE)); -} - -static void -memo_shell_content_init (EMemoShellContent *memo_shell_content) -{ - memo_shell_content->priv = - E_MEMO_SHELL_CONTENT_GET_PRIVATE (memo_shell_content); - - memo_shell_content->priv->memo_model = e_cal_model_memos_new (); - - /* Postpone widget construction until we have a shell view. */ -} - -GType -e_memo_shell_content_get_type (void) -{ - return memo_shell_content_type; -} - -void -e_memo_shell_content_register_type (GTypeModule *type_module) -{ - static const GTypeInfo type_info = { - sizeof (EMemoShellContentClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) memo_shell_content_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (EMemoShellContent), - 0, /* n_preallocs */ - (GInstanceInitFunc) memo_shell_content_init, - NULL /* value_table */ - }; - - memo_shell_content_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_CONTENT, - "EMemoShellContent", &type_info, 0); -} - -GtkWidget * -e_memo_shell_content_new (EShellView *shell_view) -{ - g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - - return g_object_new ( - E_TYPE_MEMO_SHELL_CONTENT, - "shell-view", shell_view, NULL); -} - -ECalModel * -e_memo_shell_content_get_memo_model (EMemoShellContent *memo_shell_content) -{ - g_return_val_if_fail ( - E_IS_MEMO_SHELL_CONTENT (memo_shell_content), NULL); - - return memo_shell_content->priv->memo_model; -} - -ECalComponentPreview * -e_memo_shell_content_get_memo_preview (EMemoShellContent *memo_shell_content) -{ - g_return_val_if_fail ( - E_IS_MEMO_SHELL_CONTENT (memo_shell_content), NULL); - - return E_CAL_COMPONENT_PREVIEW ( - memo_shell_content->priv->memo_preview); -} - -EMemoTable * -e_memo_shell_content_get_memo_table (EMemoShellContent *memo_shell_content) -{ - g_return_val_if_fail ( - E_IS_MEMO_SHELL_CONTENT (memo_shell_content), NULL); - - return E_MEMO_TABLE (memo_shell_content->priv->memo_table); -} - -GalViewInstance * -e_memo_shell_content_get_view_instance (EMemoShellContent *memo_shell_content) -{ - g_return_val_if_fail ( - E_IS_MEMO_SHELL_CONTENT (memo_shell_content), NULL); - - return memo_shell_content->priv->view_instance; -} - -gboolean -e_memo_shell_content_get_preview_visible (EMemoShellContent *memo_shell_content) -{ - GtkPaned *paned; - GtkWidget *child; - - g_return_val_if_fail ( - E_IS_MEMO_SHELL_CONTENT (memo_shell_content), FALSE); - - paned = GTK_PANED (memo_shell_content->priv->paned); - child = gtk_paned_get_child2 (paned); - - return GTK_WIDGET_VISIBLE (child); -} - -void -e_memo_shell_content_set_preview_visible (EMemoShellContent *memo_shell_content, - gboolean preview_visible) -{ - GtkPaned *paned; - GtkWidget *child; - - g_return_if_fail (E_IS_MEMO_SHELL_CONTENT (memo_shell_content)); - - paned = GTK_PANED (memo_shell_content->priv->paned); - child = gtk_paned_get_child2 (paned); - - if (preview_visible) - gtk_widget_show (child); - else - gtk_widget_hide (child); - - g_object_notify (G_OBJECT (memo_shell_content), "preview-visible"); -} diff --git a/calendar/module/e-memo-shell-content.h b/calendar/module/e-memo-shell-content.h deleted file mode 100644 index 84c22d6ce4..0000000000 --- a/calendar/module/e-memo-shell-content.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * e-memo-shell-content.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_MEMO_SHELL_CONTENT_H -#define E_MEMO_SHELL_CONTENT_H - -#include -#include - -#include -#include - -#include - -/* Standard GObject macros */ -#define E_TYPE_MEMO_SHELL_CONTENT \ - (e_memo_shell_content_get_type ()) -#define E_MEMO_SHELL_CONTENT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_MEMO_SHELL_CONTENT, EMemoShellContent)) -#define E_MEMO_SHELL_CONTENT_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_MEMO_SHELL_CONTENT, EMemoShellContentClass)) -#define E_IS_MEMO_SHELL_CONTENT(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_MEMO_SHELL_CONTENT)) -#define E_IS_MEMO_SHELL_CONTENT_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_MEMO_SHELL_CONTENT)) -#define E_MEMO_SHELL_CONTENT_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_MEMO_SHELL_CONTENT, EMemoShellContentClass)) - -G_BEGIN_DECLS - -typedef struct _EMemoShellContent EMemoShellContent; -typedef struct _EMemoShellContentClass EMemoShellContentClass; -typedef struct _EMemoShellContentPrivate EMemoShellContentPrivate; - -enum { - E_MEMO_SHELL_CONTENT_SELECTION_SINGLE = 1 << 0, - E_MEMO_SHELL_CONTENT_SELECTION_MULTIPLE = 1 << 1, - E_MEMO_SHELL_CONTENT_SELECTION_CAN_EDIT = 1 << 2, - E_MEMO_SHELL_CONTENT_SELECTION_HAS_URL = 1 << 3 -}; - -struct _EMemoShellContent { - EShellContent parent; - EMemoShellContentPrivate *priv; -}; - -struct _EMemoShellContentClass { - EShellContentClass parent_class; -}; - -GType e_memo_shell_content_get_type (void); -void e_memo_shell_content_register_type - (GTypeModule *type_module); -GtkWidget * e_memo_shell_content_new(EShellView *shell_view); -ECalModel * e_memo_shell_content_get_memo_model - (EMemoShellContent *memo_shell_conent); -ECalComponentPreview * - e_memo_shell_content_get_memo_preview - (EMemoShellContent *memo_shell_content); -EMemoTable * e_memo_shell_content_get_memo_table - (EMemoShellContent *memo_shell_content); -GalViewInstance * - e_memo_shell_content_get_view_instance - (EMemoShellContent *memo_shell_content); -gboolean e_memo_shell_content_get_preview_visible - (EMemoShellContent *memo_shell_content); -void e_memo_shell_content_set_preview_visible - (EMemoShellContent *memo_shell_content, - gboolean preview_visible); - -G_END_DECLS - -#endif /* E_MEMO_SHELL_CONTENT_H */ diff --git a/calendar/module/e-memo-shell-migrate.c b/calendar/module/e-memo-shell-migrate.c deleted file mode 100644 index d2e7df6d1b..0000000000 --- a/calendar/module/e-memo-shell-migrate.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * e-memo-shell-migrate.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-memo-shell-migrate.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "calendar/gui/calendar-config.h" -#include "calendar/gui/calendar-config-keys.h" - -#define WEBCAL_BASE_URI "webcal://" -#define PERSONAL_RELATIVE_URI "system" -#define GROUPWISE_BASE_URI "groupwise://" - -static void -create_memo_sources (EShellBackend *shell_backend, - ESourceList *source_list, - ESourceGroup **on_this_computer, - ESourceGroup **on_the_web, - ESource **personal_source) -{ - GSList *groups; - ESourceGroup *group; - gchar *base_uri, *base_uri_proto; - const gchar *base_dir; - - *on_this_computer = NULL; - *on_the_web = NULL; - *personal_source = NULL; - - base_dir = e_shell_backend_get_config_dir (shell_backend); - base_uri = g_build_filename (base_dir, "local", NULL); - - base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL); - - groups = e_source_list_peek_groups (source_list); - if (groups) { - /* groups are already there, we need to search for things... */ - GSList *g; - - for (g = groups; g; g = g->next) { - - group = E_SOURCE_GROUP (g->data); - - if (!*on_this_computer && !strcmp (base_uri_proto, e_source_group_peek_base_uri (group))) - *on_this_computer = g_object_ref (group); - else if (!*on_the_web && !strcmp (WEBCAL_BASE_URI, e_source_group_peek_base_uri (group))) - *on_the_web = g_object_ref (group); - } - } - - if (*on_this_computer) { - /* make sure "Personal" shows up as a source under - this group */ - GSList *sources = e_source_group_peek_sources (*on_this_computer); - GSList *s; - for (s = sources; s; s = s->next) { - ESource *source = E_SOURCE (s->data); - const gchar *relative_uri; - - relative_uri = e_source_peek_relative_uri (source); - if (relative_uri == NULL) - continue; - if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) { - *personal_source = g_object_ref (source); - break; - } - } - } else { - /* create the local source group */ - group = e_source_group_new (_("On This Computer"), base_uri_proto); - e_source_list_add_group (source_list, group, -1); - - *on_this_computer = group; - } - - if (!*personal_source) { - /* Create the default Person task list */ - ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); - e_source_group_add_source (*on_this_computer, source, -1); - - if (!calendar_config_get_primary_memos () && !calendar_config_get_memos_selected ()) { - GSList selected; - - calendar_config_set_primary_memos (e_source_peek_uid (source)); - - selected.data = (gpointer)e_source_peek_uid (source); - selected.next = NULL; - calendar_config_set_memos_selected (&selected); - } - - e_source_set_color_spec (source, "#BECEDD"); - *personal_source = source; - } - - if (!*on_the_web) { - /* Create the Webcal source group */ - group = e_source_group_new (_("On The Web"), WEBCAL_BASE_URI); - e_source_list_add_group (source_list, group, -1); - - *on_the_web = group; - } - - g_free (base_uri_proto); - g_free (base_uri); -} - -static gboolean -is_groupwise_account (EAccount *account) -{ - if (account->source->url != NULL) { - return g_str_has_prefix (account->source->url, GROUPWISE_BASE_URI); - } else { - return FALSE; - } -} - -static void -add_gw_esource (ESourceList *source_list, const gchar *group_name, const gchar *source_name, CamelURL *url, GConfClient *client) -{ - ESourceGroup *group; - ESource *source; - GSList *ids, *temp; - GError *error = NULL; - gchar *relative_uri; - const gchar *soap_port; - const gchar * use_ssl; - const gchar *poa_address; - const gchar *offline_sync; - - - poa_address = url->host; - if (!poa_address || strlen (poa_address) ==0) - return; - soap_port = camel_url_get_param (url, "soap_port"); - - if (!soap_port || strlen (soap_port) == 0) - soap_port = "7191"; - - use_ssl = camel_url_get_param (url, "use_ssl"); - offline_sync = camel_url_get_param (url, "offline_sync"); - - group = e_source_group_new (group_name, GROUPWISE_BASE_URI); - if (!e_source_list_add_group (source_list, group, -1)) - return; - relative_uri = g_strdup_printf ("%s@%s/", url->user, poa_address); - - source = e_source_new (source_name, relative_uri); - e_source_set_property (source, "auth", "1"); - e_source_set_property (source, "username", url->user); - e_source_set_property (source, "port", camel_url_get_param (url, "soap_port")); - e_source_set_property (source, "auth-domain", "Groupwise"); - e_source_set_property (source, "use_ssl", use_ssl); - e_source_set_property (source, "offline_sync", offline_sync ? "1" : "0" ); - - e_source_set_color_spec (source, "#EEBC60"); - e_source_group_add_source (group, source, -1); - - ids = gconf_client_get_list (client, CALENDAR_CONFIG_MEMOS_SELECTED_MEMOS, GCONF_VALUE_STRING, &error); - if ( error != NULL ) { - g_warning("%s (%s) %s\n", G_STRLOC, G_STRFUNC, error->message); - g_error_free(error); - } - ids = g_slist_append (ids, g_strdup (e_source_peek_uid (source))); - gconf_client_set_list (client, CALENDAR_CONFIG_MEMOS_SELECTED_MEMOS, GCONF_VALUE_STRING, ids, NULL); - temp = ids; - for (; temp != NULL; temp = g_slist_next (temp)) - g_free (temp->data); - - g_slist_free (ids); - g_object_unref (source); - g_object_unref (group); - g_free (relative_uri); -} - -gboolean -e_memo_shell_backend_migrate (EShellBackend *shell_backend, - gint major, - gint minor, - gint revision, - GError **error) -{ - ESourceGroup *on_this_computer = NULL; - ESourceGroup *on_the_web = NULL; - ESource *personal_source = NULL; - ESourceList *source_list = NULL; - gboolean retval = FALSE; - - source_list = g_object_get_data ( - G_OBJECT (shell_backend), "source-list"); - - /* we call this unconditionally now - create_groups either - creates the groups/sources or it finds the necessary - groups/sources. */ - create_memo_sources ( - shell_backend, source_list, &on_this_computer, - &on_the_web, &personal_source); - - /* Migration for Gw accounts between versions < 2.8 */ - if (major == 2 && minor < 8) { - EAccountList *al; - EAccount *a; - CamelURL *url; - EIterator *it; - GConfClient *gconf_client = gconf_client_get_default (); - al = e_account_list_new (gconf_client); - for (it = e_list_get_iterator((EList *)al); - e_iterator_is_valid(it); - e_iterator_next(it)) { - a = (EAccount *) e_iterator_get(it); - if (!a->enabled || !is_groupwise_account (a)) - continue; - url = camel_url_new (a->source->url, NULL); - add_gw_esource (source_list, a->name, _("Notes"), url, gconf_client); - camel_url_free (url); - } - g_object_unref (al); - g_object_unref (gconf_client); - } - - e_source_list_sync (source_list, NULL); - retval = TRUE; - - if (on_this_computer) - g_object_unref (on_this_computer); - if (on_the_web) - g_object_unref (on_the_web); - if (personal_source) - g_object_unref (personal_source); - - return retval; -} diff --git a/calendar/module/e-memo-shell-migrate.h b/calendar/module/e-memo-shell-migrate.h deleted file mode 100644 index ba163c6950..0000000000 --- a/calendar/module/e-memo-shell-migrate.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * e-memo-shell-backend-migrate.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_MEMO_SHELL_BACKEND_MIGRATE_H -#define E_MEMO_SHELL_BACKEND_MIGRATE_H - -#include -#include - -G_BEGIN_DECLS - -gboolean e_memo_shell_backend_migrate (EShellBackend *shell_backend, - gint major, - gint minor, - gint micro, - GError **error); - -G_END_DECLS - -#endif /* E_MEMO_SHELL_BACKEND_MIGRATE_H */ diff --git a/calendar/module/e-memo-shell-sidebar.c b/calendar/module/e-memo-shell-sidebar.c deleted file mode 100644 index ca5d05c40b..0000000000 --- a/calendar/module/e-memo-shell-sidebar.c +++ /dev/null @@ -1,718 +0,0 @@ -/* - * e-memo-shell-sidebar.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-memo-shell-sidebar.h" - -#include -#include -#include - -#include "e-util/e-error.h" -#include "e-util/e-util.h" -#include "calendar/common/authentication.h" -#include "calendar/gui/calendar-config.h" -#include "calendar/gui/e-memo-list-selector.h" -#include "calendar/gui/misc.h" - -#include "e-memo-shell-view.h" -#include "e-memo-shell-backend.h" - -#define E_MEMO_SHELL_SIDEBAR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_MEMO_SHELL_SIDEBAR, EMemoShellSidebarPrivate)) - -struct _EMemoShellSidebarPrivate { - GtkWidget *selector; - - /* UID -> Client */ - GHashTable *client_table; -}; - -enum { - PROP_0, - PROP_SELECTOR -}; - -enum { - CLIENT_ADDED, - CLIENT_REMOVED, - STATUS_MESSAGE, - LAST_SIGNAL -}; - -static gpointer parent_class; -static guint signals[LAST_SIGNAL]; -static GType memo_shell_sidebar_type; - -static void -memo_shell_sidebar_emit_client_added (EMemoShellSidebar *memo_shell_sidebar, - ECal *client) -{ - guint signal_id = signals[CLIENT_ADDED]; - - g_signal_emit (memo_shell_sidebar, signal_id, 0, client); -} - -static void -memo_shell_sidebar_emit_client_removed (EMemoShellSidebar *memo_shell_sidebar, - ECal *client) -{ - guint signal_id = signals[CLIENT_REMOVED]; - - g_signal_emit (memo_shell_sidebar, signal_id, 0, client); -} - -static void -memo_shell_sidebar_emit_status_message (EMemoShellSidebar *memo_shell_sidebar, - const gchar *status_message) -{ - guint signal_id = signals[STATUS_MESSAGE]; - - g_signal_emit (memo_shell_sidebar, signal_id, 0, status_message, -1.0); -} - -static void -memo_shell_sidebar_update_timezone (EMemoShellSidebar *memo_shell_sidebar) -{ - GHashTable *client_table; - icaltimezone *zone; - GList *values; - - zone = calendar_config_get_icaltimezone (); - client_table = memo_shell_sidebar->priv->client_table; - values = g_hash_table_get_values (client_table); - - while (values != NULL) { - ECal *client = values->data; - - if (e_cal_get_load_state (client) == E_CAL_LOAD_LOADED) - e_cal_set_default_timezone (client, zone, NULL); - - values = g_list_delete_link (values, values); - } - - /* XXX Need to call e_cal_component_preview_set_default_timezone() - * here but the sidebar is not really supposed to access content - * stuff. I guess we could emit an "update-timezone" signal - * here, but that feels wrong. Maybe this whole thing should - * be in EMemoShellView instead. */ -} - -static void -memo_shell_sidebar_backend_died_cb (EMemoShellSidebar *memo_shell_sidebar, - ECal *client) -{ - EShellView *shell_view; - EShellWindow *shell_window; - EShellSidebar *shell_sidebar; - GHashTable *client_table; - ESource *source; - const gchar *uid; - - client_table = memo_shell_sidebar->priv->client_table; - - shell_sidebar = E_SHELL_SIDEBAR (memo_shell_sidebar); - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - shell_window = e_shell_view_get_shell_window (shell_view); - - source = e_cal_get_source (client); - uid = e_source_peek_uid (source); - - g_object_ref (source); - - g_hash_table_remove (client_table, uid); - memo_shell_sidebar_emit_status_message (memo_shell_sidebar, NULL); - - e_error_run ( - GTK_WINDOW (shell_window), - "calendar:memos-crashed", NULL); - - g_object_unref (source); -} - -static void -memo_shell_sidebar_backend_error_cb (EMemoShellSidebar *memo_shell_sidebar, - const gchar *message, - ECal *client) -{ - EShellView *shell_view; - EShellWindow *shell_window; - EShellSidebar *shell_sidebar; - GtkWidget *dialog; - const gchar *uri; - gchar *uri_no_passwd; - - shell_sidebar = E_SHELL_SIDEBAR (memo_shell_sidebar); - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - shell_window = e_shell_view_get_shell_window (shell_view); - - uri = e_cal_get_uri (client); - uri_no_passwd = get_uri_without_password (uri); - - dialog = gtk_message_dialog_new ( - GTK_WINDOW (shell_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, - _("Error on %s\n%s"), - uri_no_passwd, message); - - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - - g_free (uri_no_passwd); -} - -static void -memo_shell_sidebar_client_opened_cb (EMemoShellSidebar *memo_shell_sidebar, - ECalendarStatus status, - ECal *client) -{ - EShellView *shell_view; - EShellWindow *shell_window; - EShellSidebar *shell_sidebar; - ESource *source; - - source = e_cal_get_source (client); - - shell_sidebar = E_SHELL_SIDEBAR (memo_shell_sidebar); - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - shell_window = e_shell_view_get_shell_window (shell_view); - - if (status == E_CALENDAR_STATUS_AUTHENTICATION_FAILED || - status == E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED) - auth_cal_forget_password (client); - - switch (status) { - case E_CALENDAR_STATUS_OK: - g_signal_handlers_disconnect_matched ( - client, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, - memo_shell_sidebar_client_opened_cb, NULL); - - memo_shell_sidebar_emit_status_message ( - memo_shell_sidebar, _("Loading memos")); - memo_shell_sidebar_emit_client_added ( - memo_shell_sidebar, client); - memo_shell_sidebar_emit_status_message ( - memo_shell_sidebar, NULL); - break; - - case E_CALENDAR_STATUS_AUTHENTICATION_FAILED: - e_cal_open_async (client, FALSE); - break; - - case E_CALENDAR_STATUS_BUSY: - break; - - case E_CALENDAR_STATUS_REPOSITORY_OFFLINE: - e_error_run ( - GTK_WINDOW (shell_window), - "calendar:prompt-no-contents-offline-memos", - NULL); - break; - - default: - memo_shell_sidebar_emit_client_removed ( - memo_shell_sidebar, client); - break; - } -} - -static void -memo_shell_sidebar_row_changed_cb (EMemoShellSidebar *memo_shell_sidebar, - GtkTreePath *tree_path, - GtkTreeIter *tree_iter, - GtkTreeModel *tree_model) -{ - ESourceSelector *selector; - ESource *source; - - /* XXX ESourceSelector's underlying tree store has only one - * column: ESource objects. While we're not supposed to - * know this, listening for "row-changed" signals from - * the model is easier to deal with than the selector's - * "selection-changed" signal, which doesn't tell you - * _which_ row changed. */ - - selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); - gtk_tree_model_get (tree_model, tree_iter, 0, &source, -1); - - /* XXX This signal gets emitted a lot while the model is being - * rebuilt, during which time we won't get a valid ESource. - * ESourceSelector should probably block this signal while - * rebuilding the model, but we'll be forgiving and not - * emit a warning. */ - if (!E_IS_SOURCE (source)) - return; - - if (e_source_selector_source_is_selected (selector, source)) - e_memo_shell_sidebar_add_source (memo_shell_sidebar, source); - else - e_memo_shell_sidebar_remove_source (memo_shell_sidebar, source); -} - -static void -memo_shell_sidebar_selection_changed_cb (EMemoShellSidebar *memo_shell_sidebar, - ESourceSelector *selector) -{ - GSList *list, *iter; - - /* This signal is emitted less frequently than "row-changed", - * especially when the model is being rebuilt. So we'll take - * it easy on poor GConf. */ - - list = e_source_selector_get_selection (selector); - - for (iter = list; iter != NULL; iter = iter->next) { - ESource *source = iter->data; - - iter->data = (gpointer) e_source_peek_uid (source); - g_object_unref (source); - } - - calendar_config_set_memos_selected (list); - - g_slist_free (list); -} - -static void -memo_shell_sidebar_primary_selection_changed_cb (EMemoShellSidebar *memo_shell_sidebar, - ESourceSelector *selector) -{ - ESource *source; - const gchar *uid; - - /* XXX ESourceSelector needs a "primary-selection-uid" property - * so we can just bind the property with GConfBridge. */ - - source = e_source_selector_peek_primary_selection (selector); - if (source == NULL) - return; - - uid = e_source_peek_uid (source); - calendar_config_set_primary_memos (uid); -} - -static void -memo_shell_sidebar_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_SELECTOR: - g_value_set_object ( - value, e_memo_shell_sidebar_get_selector ( - E_MEMO_SHELL_SIDEBAR (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -memo_shell_sidebar_dispose (GObject *object) -{ - EMemoShellSidebarPrivate *priv; - - priv = E_MEMO_SHELL_SIDEBAR_GET_PRIVATE (object); - - if (priv->selector != NULL) { - g_object_unref (priv->selector); - priv->selector = NULL; - } - - g_hash_table_remove_all (priv->client_table); - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -memo_shell_sidebar_finalize (GObject *object) -{ - EMemoShellSidebarPrivate *priv; - - priv = E_MEMO_SHELL_SIDEBAR_GET_PRIVATE (object); - - g_hash_table_destroy (priv->client_table); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -memo_shell_sidebar_constructed (GObject *object) -{ - EMemoShellSidebarPrivate *priv; - EShellView *shell_view; - EShellBackend *shell_backend; - EShellSidebar *shell_sidebar; - ESourceSelector *selector; - ESourceList *source_list; - ESource *source; - GtkContainer *container; - GtkTreeModel *model; - GtkWidget *widget; - AtkObject *a11y; - GSList *list, *iter; - gchar *uid; - - priv = E_MEMO_SHELL_SIDEBAR_GET_PRIVATE (object); - - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (parent_class)->constructed (object); - - shell_sidebar = E_SHELL_SIDEBAR (object); - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - shell_backend = e_shell_view_get_shell_backend (shell_view); - - source_list = e_memo_shell_backend_get_source_list ( - E_MEMO_SHELL_BACKEND (shell_backend)); - - container = GTK_CONTAINER (shell_sidebar); - - widget = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy ( - GTK_SCROLLED_WINDOW (widget), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type ( - GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); - gtk_container_add (container, widget); - gtk_widget_show (widget); - - container = GTK_CONTAINER (widget); - - widget = e_memo_list_selector_new (source_list); - e_source_selector_set_select_new (E_SOURCE_SELECTOR (widget), TRUE); - gtk_container_add (container, widget); - a11y = gtk_widget_get_accessible (widget); - atk_object_set_name (a11y, _("Memo List Selector")); - priv->selector = g_object_ref (widget); - gtk_widget_show (widget); - - /* Restore the selector state from the last session. */ - - selector = E_SOURCE_SELECTOR (priv->selector); - model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); - - g_signal_connect_swapped ( - model, "row-changed", - G_CALLBACK (memo_shell_sidebar_row_changed_cb), - object); - - source = NULL; - uid = calendar_config_get_primary_memos (); - if (uid != NULL) - source = e_source_list_peek_source_by_uid (source_list, uid); - if (source == NULL) - source = e_source_list_peek_source_any (source_list); - if (source != NULL) - e_source_selector_set_primary_selection (selector, source); - g_free (uid); - - list = calendar_config_get_memos_selected (); - for (iter = list; iter != NULL; iter = iter->next) { - uid = iter->data; - source = e_source_list_peek_source_by_uid (source_list, uid); - g_free (uid); - - if (source == NULL) - continue; - - e_source_selector_select_source (selector, source); - } - g_slist_free (list); - - /* Listen for subsequent changes to the selector. */ - - g_signal_connect_swapped ( - widget, "selection-changed", - G_CALLBACK (memo_shell_sidebar_selection_changed_cb), - object); - - g_signal_connect_swapped ( - widget, "primary-selection-changed", - G_CALLBACK (memo_shell_sidebar_primary_selection_changed_cb), - object); -} - -static guint32 -memo_shell_sidebar_check_state (EShellSidebar *shell_sidebar) -{ - EMemoShellSidebar *memo_shell_sidebar; - ESourceSelector *selector; - ESource *source; - gboolean is_system = FALSE; - guint32 state = 0; - - memo_shell_sidebar = E_MEMO_SHELL_SIDEBAR (shell_sidebar); - selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); - source = e_source_selector_peek_primary_selection (selector); - - if (source != NULL) { - const gchar *uri; - - uri = e_source_peek_relative_uri (source); - is_system = (uri == NULL || strcmp (uri, "system") == 0); - } - - if (source != NULL) - state |= E_MEMO_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE; - if (is_system) - state |= E_MEMO_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM; - - return state; -} - -static void -memo_shell_sidebar_client_added (EMemoShellSidebar *memo_shell_sidebar, - ECal *client) -{ - memo_shell_sidebar_update_timezone (memo_shell_sidebar); -} - -static void -memo_shell_sidebar_client_removed (EMemoShellSidebar *memo_shell_sidebar, - ECal *client) -{ - ESourceSelector *selector; - GHashTable *client_table; - ESource *source; - const gchar *uid; - - client_table = memo_shell_sidebar->priv->client_table; - selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); - - g_signal_handlers_disconnect_matched ( - client, G_SIGNAL_MATCH_DATA, 0, 0, - NULL, NULL, memo_shell_sidebar); - - source = e_cal_get_source (client); - e_source_selector_unselect_source (selector, source); - - uid = e_source_peek_uid (source); - g_hash_table_remove (client_table, uid); - - memo_shell_sidebar_emit_status_message (memo_shell_sidebar, NULL); -} - -static void -memo_shell_sidebar_class_init (EMemoShellSidebarClass *class) -{ - GObjectClass *object_class; - EShellSidebarClass *shell_sidebar_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (EMemoShellSidebarPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->get_property = memo_shell_sidebar_get_property; - object_class->dispose = memo_shell_sidebar_dispose; - object_class->finalize = memo_shell_sidebar_finalize; - object_class->constructed = memo_shell_sidebar_constructed; - - shell_sidebar_class = E_SHELL_SIDEBAR_CLASS (class); - shell_sidebar_class->check_state = memo_shell_sidebar_check_state; - - class->client_added = memo_shell_sidebar_client_added; - class->client_removed = memo_shell_sidebar_client_removed; - - g_object_class_install_property ( - object_class, - PROP_SELECTOR, - g_param_spec_object ( - "selector", - _("Source Selector Widget"), - _("This widget displays groups of memo lists"), - E_TYPE_SOURCE_SELECTOR, - G_PARAM_READABLE)); - - signals[CLIENT_ADDED] = g_signal_new ( - "client-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EMemoShellSidebarClass, client_added), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - E_TYPE_CAL); - - signals[CLIENT_REMOVED] = g_signal_new ( - "client-removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EMemoShellSidebarClass, client_removed), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - E_TYPE_CAL); - - signals[STATUS_MESSAGE] = g_signal_new ( - "status-message", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (EMemoShellSidebarClass, status_message), - NULL, NULL, - e_marshal_VOID__STRING_DOUBLE, - G_TYPE_NONE, 2, - G_TYPE_STRING, - G_TYPE_DOUBLE); -} - -static void -memo_shell_sidebar_init (EMemoShellSidebar *memo_shell_sidebar) -{ - GHashTable *client_table; - - client_table = g_hash_table_new_full ( - g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_object_unref); - - memo_shell_sidebar->priv = - E_MEMO_SHELL_SIDEBAR_GET_PRIVATE (memo_shell_sidebar); - - memo_shell_sidebar->priv->client_table = client_table; - - /* Postpone widget construction until we have a shell view. */ -} - -GType -e_memo_shell_sidebar_get_type (void) -{ - return memo_shell_sidebar_type; -} - -void -e_memo_shell_sidebar_register_type (GTypeModule *type_module) -{ - static const GTypeInfo type_info = { - sizeof (EMemoShellSidebarClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) memo_shell_sidebar_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (EMemoShellSidebar), - 0, /* n_preallocs */ - (GInstanceInitFunc) memo_shell_sidebar_init, - NULL /* value_table */ - }; - - memo_shell_sidebar_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_SIDEBAR, - "EMemoShellSidebar", &type_info, 0); -} - -GtkWidget * -e_memo_shell_sidebar_new (EShellView *shell_view) -{ - g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - - return g_object_new ( - E_TYPE_MEMO_SHELL_SIDEBAR, - "shell-view", shell_view, NULL); -} - -ESourceSelector * -e_memo_shell_sidebar_get_selector (EMemoShellSidebar *memo_shell_sidebar) -{ - g_return_val_if_fail ( - E_IS_MEMO_SHELL_SIDEBAR (memo_shell_sidebar), NULL); - - return E_SOURCE_SELECTOR (memo_shell_sidebar->priv->selector); -} - -void -e_memo_shell_sidebar_add_source (EMemoShellSidebar *memo_shell_sidebar, - ESource *source) -{ - ESourceSelector *selector; - GHashTable *client_table; - ECal *client; - const gchar *uid; - const gchar *uri; - gchar *message; - - g_return_if_fail (E_IS_MEMO_SHELL_SIDEBAR (memo_shell_sidebar)); - g_return_if_fail (E_IS_SOURCE (source)); - - client_table = memo_shell_sidebar->priv->client_table; - selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); - - uid = e_source_peek_uid (source); - client = g_hash_table_lookup (client_table, uid); - - if (client != NULL) - return; - - client = auth_new_cal_from_source (source, E_CAL_SOURCE_TYPE_JOURNAL); - g_return_if_fail (client != NULL); - - g_signal_connect_swapped ( - client, "backend-died", - G_CALLBACK (memo_shell_sidebar_backend_died_cb), - memo_shell_sidebar); - - g_signal_connect_swapped ( - client, "backend-error", - G_CALLBACK (memo_shell_sidebar_backend_error_cb), - memo_shell_sidebar); - - g_hash_table_insert (client_table, g_strdup (uid), client); - e_source_selector_select_source (selector, source); - - uri = e_cal_get_uri (client); - message = g_strdup_printf (_("Opening memos at %s"), uri); - memo_shell_sidebar_emit_status_message (memo_shell_sidebar, message); - g_free (message); - - g_signal_connect_swapped ( - client, "cal-opened", - G_CALLBACK (memo_shell_sidebar_client_opened_cb), - memo_shell_sidebar); - - e_cal_open_async (client, FALSE); -} - -void -e_memo_shell_sidebar_remove_source (EMemoShellSidebar *memo_shell_sidebar, - ESource *source) -{ - ESourceSelector *selector; - GHashTable *client_table; - ECal *client; - const gchar *uid; - - g_return_if_fail (E_IS_MEMO_SHELL_SIDEBAR (memo_shell_sidebar)); - g_return_if_fail (E_IS_SOURCE (source)); - - client_table = memo_shell_sidebar->priv->client_table; - selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); - - uid = e_source_peek_uid (source); - client = g_hash_table_lookup (client_table, uid); - - if (client == NULL) - return; - - memo_shell_sidebar_emit_client_removed (memo_shell_sidebar, client); -} diff --git a/calendar/module/e-memo-shell-sidebar.h b/calendar/module/e-memo-shell-sidebar.h deleted file mode 100644 index 665c8f218a..0000000000 --- a/calendar/module/e-memo-shell-sidebar.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * e-memo-shell-sidebar.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_MEMO_SHELL_SIDEBAR_H -#define E_MEMO_SHELL_SIDEBAR_H - -#include -#include - -#include -#include - -/* Standard GObject macros */ -#define E_TYPE_MEMO_SHELL_SIDEBAR \ - (e_memo_shell_sidebar_get_type ()) -#define E_MEMO_SHELL_SIDEBAR(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_MEMO_SHELL_SIDEBAR, EMemoShellSidebar)) -#define E_MEMO_SHELL_SIDEBAR_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_MEMO_SHELL_SIDEBAR, EMemoShellSidebarClass)) -#define E_IS_MEMO_SHELL_SIDEBAR(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_MEMO_SHELL_SIDEBAR)) -#define E_IS_MEMO_SHELL_SIDEBAR_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_MEMO_SHELL_SIDEBAR)) -#define E_MEMO_SHELL_SIDEBAR_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_MEMO_SHELL_SIDEBAR, EMemoShellSidebarClass)) - -G_BEGIN_DECLS - -typedef struct _EMemoShellSidebar EMemoShellSidebar; -typedef struct _EMemoShellSidebarClass EMemoShellSidebarClass; -typedef struct _EMemoShellSidebarPrivate EMemoShellSidebarPrivate; - -enum { - E_MEMO_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE = 1 << 0, - E_MEMO_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM = 1 << 1 -}; - -struct _EMemoShellSidebar { - EShellSidebar parent; - EMemoShellSidebarPrivate *priv; -}; - -struct _EMemoShellSidebarClass { - EShellSidebarClass parent_class; - - /* Signals */ - void (*client_added) (EMemoShellSidebar *memo_shell_sidebar, - ECal *client); - void (*client_removed) (EMemoShellSidebar *memo_shell_sidebar, - ECal *client); - void (*status_message) (EMemoShellSidebar *memo_shell_sidebar, - const gchar *status_message, - gdouble percent); -}; - -GType e_memo_shell_sidebar_get_type (void); -void e_memo_shell_sidebar_register_type - (GTypeModule *type_module); -GtkWidget * e_memo_shell_sidebar_new(EShellView *shell_view); -ESourceSelector * - e_memo_shell_sidebar_get_selector - (EMemoShellSidebar *memo_shell_sidebar); -void e_memo_shell_sidebar_add_source - (EMemoShellSidebar *memo_shell_sidebar, - ESource *source); -void e_memo_shell_sidebar_remove_source - (EMemoShellSidebar *memo_shell_sidebar, - ESource *source); - -G_END_DECLS - -#endif /* E_MEMO_SHELL_SIDEBAR_H */ diff --git a/calendar/module/e-memo-shell-view-actions.c b/calendar/module/e-memo-shell-view-actions.c deleted file mode 100644 index 1736606abe..0000000000 --- a/calendar/module/e-memo-shell-view-actions.c +++ /dev/null @@ -1,949 +0,0 @@ -/* - * e-memo-shell-view-actions.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-memo-shell-view-private.h" - -static void -action_gal_save_custom_view_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - EShellView *shell_view; - GalViewInstance *view_instance; - - /* All shell views respond to the activation of this action, - * which is defined by EShellWindow. But only the currently - * active shell view proceeds with saving the custom view. */ - shell_view = E_SHELL_VIEW (memo_shell_view); - if (!e_shell_view_is_active (shell_view)) - return; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - view_instance = e_memo_shell_content_get_view_instance (memo_shell_content); - gal_view_instance_save_as (view_instance); -} - -static void -action_memo_clipboard_copy_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - EMemoTable *memo_table; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - - e_memo_table_copy_clipboard (memo_table); -} - -static void -action_memo_clipboard_cut_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - EMemoTable *memo_table; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - - e_memo_table_cut_clipboard (memo_table); -} - -static void -action_memo_clipboard_paste_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - EMemoTable *memo_table; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - - e_memo_table_paste_clipboard (memo_table); -} - -static void -action_memo_delete_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - ECalComponentPreview *memo_preview; - EMemoTable *memo_table; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - memo_preview = e_memo_shell_content_get_memo_preview (memo_shell_content); - - e_memo_shell_view_set_status_message ( - memo_shell_view, _("Deleting selected memos..."), -1.0); - e_memo_table_delete_selected (memo_table); - e_memo_shell_view_set_status_message (memo_shell_view, NULL, -1.0); - - e_cal_component_preview_clear (memo_preview); -} - -static void -action_memo_forward_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - EMemoTable *memo_table; - ECalModelComponent *comp_data; - ECalComponent *comp; - icalcomponent *clone; - GSList *list; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - - list = e_memo_table_get_selected (memo_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - /* XXX We only forward the first selected memo. */ - comp = e_cal_component_new (); - clone = icalcomponent_new_clone (comp_data->icalcomp); - e_cal_component_set_icalcomponent (comp, clone); - itip_send_comp ( - E_CAL_COMPONENT_METHOD_PUBLISH, comp, - comp_data->client, NULL, NULL, NULL, TRUE); - g_object_unref (comp); -} - -static void -action_memo_list_copy_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellSidebar *memo_shell_sidebar; - EShellWindow *shell_window; - EShellView *shell_view; - ESourceSelector *selector; - ESource *source; - - shell_view = E_SHELL_VIEW (memo_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; - selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); - source = e_source_selector_peek_primary_selection (selector); - g_return_if_fail (E_IS_SOURCE (source)); - - copy_source_dialog ( - GTK_WINDOW (shell_window), - source, E_CAL_SOURCE_TYPE_JOURNAL); -} - -static void -action_memo_list_delete_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellBackend *memo_shell_backend; - EMemoShellContent *memo_shell_content; - EMemoShellSidebar *memo_shell_sidebar; - EShellWindow *shell_window; - EShellView *shell_view; - EMemoTable *memo_table; - ECal *client; - ECalModel *model; - ESourceSelector *selector; - ESourceGroup *source_group; - ESourceList *source_list; - ESource *source; - gint response; - gchar *uri; - GError *error = NULL; - - shell_view = E_SHELL_VIEW (memo_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - memo_shell_backend = memo_shell_view->priv->memo_shell_backend; - source_list = e_memo_shell_backend_get_source_list (memo_shell_backend); - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - model = e_memo_table_get_model (memo_table); - - memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; - selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); - source = e_source_selector_peek_primary_selection (selector); - g_return_if_fail (E_IS_SOURCE (source)); - - /* Ask for confirmation. */ - response = e_error_run ( - GTK_WINDOW (shell_window), - "calendar:prompt-delete-memo-list", - e_source_peek_name (source)); - if (response != GTK_RESPONSE_YES) - return; - - uri = e_source_get_uri (source); - client = e_cal_model_get_client_for_uri (model, uri); - if (client == NULL) - client = e_cal_new_from_uri (uri, E_CAL_SOURCE_TYPE_JOURNAL); - g_free (uri); - - g_return_if_fail (client != NULL); - - if (!e_cal_remove (client, &error)) { - g_warning ("%s", error->message); - g_error_free (error); - return; - } - - if (e_source_selector_source_is_selected (selector, source)) { - e_memo_shell_sidebar_remove_source ( - memo_shell_sidebar, source); - e_source_selector_unselect_source (selector, source); - } - - source_group = e_source_peek_group (source); - e_source_group_remove_source (source_group, source); - - if (!e_source_list_sync (source_list, &error)) { - g_warning ("%s", error->message); - g_error_free (error); - } -} - -static void -action_memo_list_new_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - - shell_view = E_SHELL_VIEW (memo_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - calendar_setup_new_memo_list (GTK_WINDOW (shell_window)); -} - -static void -action_memo_list_print_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - EMemoTable *memo_table; - ETable *table; - GtkPrintOperationAction print_action; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - table = e_memo_table_get_table (memo_table); - - print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; - print_table (table, _("Print Memos"), _("Memos"), print_action); -} - -static void -action_memo_list_print_preview_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - EMemoTable *memo_table; - ETable *table; - GtkPrintOperationAction print_action; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - table = e_memo_table_get_table (memo_table); - - print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW; - print_table (table, _("Print Memos"), _("Memos"), print_action); -} - -static void -action_memo_list_properties_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellSidebar *memo_shell_sidebar; - EShellView *shell_view; - EShellWindow *shell_window; - ESource *source; - ESourceSelector *selector; - - shell_view = E_SHELL_VIEW (memo_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; - selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); - source = e_source_selector_peek_primary_selection (selector); - g_return_if_fail (E_IS_SOURCE (source)); - - calendar_setup_edit_memo_list (GTK_WINDOW (shell_window), source); -} - -static void -action_memo_list_rename_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellSidebar *memo_shell_sidebar; - ESourceSelector *selector; - - memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; - selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); - - e_source_selector_edit_primary_selection (selector); -} - -static void -action_memo_list_select_one_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellSidebar *memo_shell_sidebar; - ESourceSelector *selector; - ESource *primary; - GSList *list, *iter; - - /* XXX ESourceSelector should provide a function for this. */ - - memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; - selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); - primary = e_source_selector_peek_primary_selection (selector); - g_return_if_fail (primary != NULL); - - list = e_source_selector_get_selection (selector); - for (iter = list; iter != NULL; iter = iter->next) { - ESource *source = iter->data; - - if (source == primary) - continue; - - e_source_selector_unselect_source (selector, source); - } - e_source_selector_free_selection (list); - - e_source_selector_select_source (selector, primary); -} - -static void -action_memo_new_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EShell *shell; - EShellView *shell_view; - EShellWindow *shell_window; - EMemoShellContent *memo_shell_content; - EMemoTable *memo_table; - ECalModelComponent *comp_data; - ECal *client; - ECalComponent *comp; - CompEditor *editor; - GSList *list; - - shell_view = E_SHELL_VIEW (memo_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell = e_shell_window_get_shell (shell_window); - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - - list = e_memo_table_get_selected (memo_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - client = comp_data->client; - editor = memo_editor_new (client, shell, COMP_EDITOR_NEW_ITEM); - comp = cal_comp_memo_new_with_defaults (client); - comp_editor_edit_comp (editor, comp); - - gtk_window_present (GTK_WINDOW (editor)); - - g_object_unref (comp); - g_object_unref (client); -} - -static void -action_memo_open_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - EMemoTable *memo_table; - ECalModelComponent *comp_data; - GSList *list; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - - list = e_memo_table_get_selected (memo_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - /* XXX We only open the first selected memo. */ - e_memo_shell_view_open_memo (memo_shell_view, comp_data); -} - -static void -action_memo_open_url_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - EMemoShellContent *memo_shell_content; - EMemoTable *memo_table; - ECalModelComponent *comp_data; - icalproperty *prop; - const gchar *uri; - GSList *list; - - shell_view = E_SHELL_VIEW (memo_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - - list = e_memo_table_get_selected (memo_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - /* XXX We only open the URI of the first selected memo. */ - prop = icalcomponent_get_first_property ( - comp_data->icalcomp, ICAL_URL_PROPERTY); - g_return_if_fail (prop == NULL); - - uri = icalproperty_get_url (prop); - e_show_uri (GTK_WINDOW (shell_window), uri); -} - -static void -action_memo_preview_cb (GtkToggleAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - gboolean visible; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - visible = gtk_toggle_action_get_active (action); - e_memo_shell_content_set_preview_visible (memo_shell_content, visible); -} - -static void -action_memo_print_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - EMemoTable *memo_table; - ECalModelComponent *comp_data; - ECalComponent *comp; - icalcomponent *clone; - GtkPrintOperationAction print_action; - GSList *list; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - - list = e_memo_table_get_selected (memo_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - /* XXX We only print the first selected memo. */ - comp = e_cal_component_new (); - clone = icalcomponent_new_clone (comp_data->icalcomp); - print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; - e_cal_component_set_icalcomponent (comp, clone); - print_comp (comp, comp_data->client, print_action); - g_object_unref (comp); -} - -static void -action_memo_save_as_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - EMemoTable *memo_table; - ECalModelComponent *comp_data; - GSList *list; - gchar *filename; - gchar *string; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - - list = e_memo_table_get_selected (memo_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - filename = e_file_dialog_save (_("Save as..."), NULL); - if (filename == NULL) - return; - - /* XXX We only save the first selected memo. */ - string = e_cal_get_component_as_string ( - comp_data->client, comp_data->icalcomp); - if (string == NULL) { - g_warning ("Could not convert memo to a string"); - return; - } - - e_write_file_uri (filename, string); - - g_free (filename); - g_free (string); -} - -static void -action_memo_search_cb (GtkRadioAction *action, - GtkRadioAction *current, - EMemoShellView *memo_shell_view) -{ - EShellView *shell_view; - EShellContent *shell_content; - const gchar *search_hint; - - /* XXX Figure out a way to handle this in EShellContent - * instead of every shell view having to handle it. - * The problem is EShellContent does not know what - * the search option actions are for this view. It - * would have to dig up the popup menu and retrieve - * the action for each menu item. Seems messy. */ - - shell_view = E_SHELL_VIEW (memo_shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - - search_hint = gtk_action_get_label (GTK_ACTION (current)); - e_shell_content_set_search_hint (shell_content, search_hint); -} - -static void -action_search_execute_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EShellView *shell_view; - - /* All shell views respond to the activation of this action, - * which is defined by EShellWindow. But only the currently - * active shell view proceeds with executing the search. */ - shell_view = E_SHELL_VIEW (memo_shell_view); - if (!e_shell_view_is_active (shell_view)) - return; - - e_memo_shell_view_execute_search (memo_shell_view); -} - -static void -action_search_filter_cb (GtkRadioAction *action, - GtkRadioAction *current, - EMemoShellView *memo_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - - shell_view = E_SHELL_VIEW (memo_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - gtk_action_activate (ACTION (SEARCH_EXECUTE)); -} - -static GtkActionEntry memo_entries[] = { - - { "memo-clipboard-copy", - GTK_STOCK_COPY, - NULL, - NULL, - N_("Copy selected memo"), - G_CALLBACK (action_memo_clipboard_copy_cb) }, - - { "memo-clipboard-cut", - GTK_STOCK_CUT, - NULL, - NULL, - N_("Cut selected memo"), - G_CALLBACK (action_memo_clipboard_cut_cb) }, - - { "memo-clipboard-paste", - GTK_STOCK_PASTE, - NULL, - NULL, - N_("Paste memo from the clipboard"), - G_CALLBACK (action_memo_clipboard_paste_cb) }, - - { "memo-delete", - GTK_STOCK_DELETE, - N_("_Delete Memo"), - NULL, - N_("Delete selected memos"), - G_CALLBACK (action_memo_delete_cb) }, - - { "memo-forward", - "mail-forward", - N_("_Forward as iCalendar..."), - "f", - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_memo_forward_cb) }, - - { "memo-list-copy", - GTK_STOCK_COPY, - N_("_Copy..."), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_memo_list_copy_cb) }, - - { "memo-list-delete", - GTK_STOCK_DELETE, - N_("_Delete"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_memo_list_delete_cb) }, - - { "memo-list-new", - "stock_notes", - N_("_New Memo List"), - NULL, - N_("Create a new memo list"), - G_CALLBACK (action_memo_list_new_cb) }, - - { "memo-list-properties", - GTK_STOCK_PROPERTIES, - NULL, - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_memo_list_properties_cb) }, - - { "memo-list-rename", - NULL, - N_("_Rename..."), - "F2", - N_("Rename the selected memo list"), - G_CALLBACK (action_memo_list_rename_cb) }, - - { "memo-list-select-one", - "stock_check-filled", - N_("Show _Only This Memo List"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_memo_list_select_one_cb) }, - - { "memo-new", - "stock_insert-note", - N_("New _Memo"), - NULL, - N_("Create a new memo"), - G_CALLBACK (action_memo_new_cb) }, - - { "memo-open", - GTK_STOCK_OPEN, - N_("_Open Memo"), - "o", - N_("View the selected memo"), - G_CALLBACK (action_memo_open_cb) }, - - { "memo-open-url", - "applications-internet", - N_("Open _Web Page"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_memo_open_url_cb) }, - - { "memo-save-as", - GTK_STOCK_SAVE_AS, - N_("_Save as iCalendar..."), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_memo_save_as_cb) } -}; - -static EPopupActionEntry memo_popup_entries[] = { - - { "memo-list-popup-copy", - NULL, - "memo-list-copy" }, - - { "memo-list-popup-delete", - NULL, - "memo-list-delete" }, - - { "memo-list-popup-properties", - NULL, - "memo-list-properties" }, - - { "memo-list-popup-rename", - NULL, - "memo-list-rename" }, - - { "memo-list-popup-select-one", - NULL, - "memo-list-select-one" }, - - { "memo-popup-clipboard-copy", - NULL, - "memo-clipboard-copy" }, - - { "memo-popup-clipboard-cut", - NULL, - "memo-clipboard-cut" }, - - { "memo-popup-clipboard-paste", - NULL, - "memo-clipboard-paste" }, - - { "memo-popup-delete", - NULL, - "memo-delete" }, - - { "memo-popup-forward", - NULL, - "memo-forward" }, - - { "memo-popup-open", - NULL, - "memo-open" }, - - { "memo-popup-open-url", - NULL, - "memo-open-url" }, - - { "memo-popup-save-as", - NULL, - "memo-save-as" } -}; - -static GtkToggleActionEntry memo_toggle_entries[] = { - - { "memo-preview", - NULL, - N_("Memo _Preview"), - "m", - N_("Show memo preview pane"), - G_CALLBACK (action_memo_preview_cb), - TRUE } -}; - -static GtkRadioActionEntry memo_filter_entries[] = { - - { "memo-filter-any-category", - NULL, - N_("Any Category"), - NULL, - NULL, - MEMO_FILTER_ANY_CATEGORY }, - - { "memo-filter-unmatched", - NULL, - N_("Unmatched"), - NULL, - NULL, - MEMO_FILTER_UNMATCHED } -}; - -static GtkRadioActionEntry memo_search_entries[] = { - - { "memo-search-any-field-contains", - NULL, - N_("Any field contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - MEMO_SEARCH_ANY_FIELD_CONTAINS }, - - { "memo-search-description-contains", - NULL, - N_("Description contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - MEMO_SEARCH_DESCRIPTION_CONTAINS }, - - { "memo-search-summary-contains", - NULL, - N_("Summary contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - MEMO_SEARCH_SUMMARY_CONTAINS } -}; - -static GtkActionEntry lockdown_printing_entries[] = { - - { "memo-list-print", - GTK_STOCK_PRINT, - NULL, - "p", - N_("Print the list of memos"), - G_CALLBACK (action_memo_list_print_cb) }, - - { "memo-list-print-preview", - GTK_STOCK_PRINT_PREVIEW, - NULL, - NULL, - N_("Preview the list of memos to be printed"), - G_CALLBACK (action_memo_list_print_preview_cb) }, - - { "memo-print", - GTK_STOCK_PRINT, - NULL, - NULL, - N_("Print the selected memo"), - G_CALLBACK (action_memo_print_cb) } -}; - -static EPopupActionEntry lockdown_printing_popup_entries[] = { - - { "memo-popup-print", - NULL, - "memo-print" } -}; - -void -e_memo_shell_view_actions_init (EMemoShellView *memo_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - GtkActionGroup *action_group; - GConfBridge *bridge; - GtkAction *action; - GObject *object; - const gchar *key; - - shell_view = E_SHELL_VIEW (memo_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - /* Memo Actions */ - action_group = ACTION_GROUP (MEMOS); - gtk_action_group_add_actions ( - action_group, memo_entries, - G_N_ELEMENTS (memo_entries), memo_shell_view); - e_action_group_add_popup_actions ( - action_group, memo_popup_entries, - G_N_ELEMENTS (memo_popup_entries)); - gtk_action_group_add_toggle_actions ( - action_group, memo_toggle_entries, - G_N_ELEMENTS (memo_toggle_entries), memo_shell_view); - gtk_action_group_add_radio_actions ( - action_group, memo_search_entries, - G_N_ELEMENTS (memo_search_entries), - MEMO_SEARCH_SUMMARY_CONTAINS, - G_CALLBACK (action_memo_search_cb), memo_shell_view); - - /* Lockdown Printing Actions */ - action_group = ACTION_GROUP (LOCKDOWN_PRINTING); - gtk_action_group_add_actions ( - action_group, lockdown_printing_entries, - G_N_ELEMENTS (lockdown_printing_entries), memo_shell_view); - e_action_group_add_popup_actions ( - action_group, lockdown_printing_popup_entries, - G_N_ELEMENTS (lockdown_printing_popup_entries)); - - /* Bind GObject properties to GConf keys. */ - - bridge = gconf_bridge_get (); - - object = G_OBJECT (ACTION (MEMO_PREVIEW)); - key = "/apps/evolution/calendar/display/show_memo_preview"; - gconf_bridge_bind_property (bridge, key, object, "active"); - - /* Fine tuning. */ - - action = ACTION (MEMO_DELETE); - g_object_set (action, "short-label", _("Delete"), NULL); - - g_signal_connect ( - ACTION (GAL_SAVE_CUSTOM_VIEW), "activate", - G_CALLBACK (action_gal_save_custom_view_cb), memo_shell_view); - - g_signal_connect ( - ACTION (SEARCH_EXECUTE), "activate", - G_CALLBACK (action_search_execute_cb), memo_shell_view); -} - -void -e_memo_shell_view_update_search_filter (EMemoShellView *memo_shell_view) -{ - EShellContent *shell_content; - EShellWindow *shell_window; - EShellView *shell_view; - GtkActionGroup *action_group; - GtkRadioAction *radio_action; - GList *list, *iter; - GSList *group; - gint ii; - - shell_view = E_SHELL_VIEW (memo_shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - action_group = ACTION_GROUP (MEMOS_FILTER); - e_action_group_remove_all_actions (action_group); - - /* Add the standard filter actions. */ - gtk_action_group_add_radio_actions ( - action_group, memo_filter_entries, - G_N_ELEMENTS (memo_filter_entries), - MEMO_FILTER_ANY_CATEGORY, - G_CALLBACK (action_search_filter_cb), - memo_shell_view); - - /* Retrieve the radio group from an action we just added. */ - list = gtk_action_group_list_actions (action_group); - radio_action = GTK_RADIO_ACTION (list->data); - group = gtk_radio_action_get_group (radio_action); - g_list_free (list); - - /* Build the category actions. */ - - list = e_categories_get_list (); - for (iter = list, ii = 0; iter != NULL; iter = iter->next, ii++) { - const gchar *category_name = iter->data; - const gchar *filename; - GtkAction *action; - gchar *action_name; - - action_name = g_strdup_printf ( - "memo-filter-category-%d", ii); - radio_action = gtk_radio_action_new ( - action_name, category_name, NULL, NULL, ii); - g_free (action_name); - - /* Convert the category icon file to a themed icon name. */ - filename = e_categories_get_icon_file_for (category_name); - if (filename != NULL && *filename != '\0') { - gchar *basename; - gchar *cp; - - basename = g_path_get_basename (filename); - - /* Lose the file extension. */ - if ((cp = strrchr (basename, '.')) != NULL) - *cp = '\0'; - - g_object_set ( - radio_action, "icon-name", basename, NULL); - - g_free (basename); - } - - gtk_radio_action_set_group (radio_action, group); - group = gtk_radio_action_get_group (radio_action); - - /* The action group takes ownership of the action. */ - action = GTK_ACTION (radio_action); - gtk_action_group_add_action (action_group, action); - g_object_unref (radio_action); - } - g_list_free (list); - - /* Use any action in the group; doesn't matter which. */ - e_shell_content_set_filter_action (shell_content, radio_action); - - ii = MEMO_FILTER_UNMATCHED; - e_shell_content_add_filter_separator_after (shell_content, ii); -} diff --git a/calendar/module/e-memo-shell-view-actions.h b/calendar/module/e-memo-shell-view-actions.h deleted file mode 100644 index d6fd3ca514..0000000000 --- a/calendar/module/e-memo-shell-view-actions.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * e-memo-shell-view-actions.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_MEMO_SHELL_VIEW_ACTIONS_H -#define E_MEMO_SHELL_VIEW_ACTIONS_H - -#include - -/* Memo Actions */ -#define E_SHELL_WINDOW_ACTION_MEMO_CLIPBOARD_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-clipboard-copy") -#define E_SHELL_WINDOW_ACTION_MEMO_CLIPBOARD_CUT(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-clipboard-cut") -#define E_SHELL_WINDOW_ACTION_MEMO_CLIPBOARD_PASTE(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-clipboard-paste") -#define E_SHELL_WINDOW_ACTION_MEMO_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-delete") -#define E_SHELL_WINDOW_ACTION_MEMO_FORWARD(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-forward") -#define E_SHELL_WINDOW_ACTION_MEMO_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-new") -#define E_SHELL_WINDOW_ACTION_MEMO_OPEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-open") -#define E_SHELL_WINDOW_ACTION_MEMO_OPEN_URL(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-open-url") -#define E_SHELL_WINDOW_ACTION_MEMO_PREVIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-preview") -#define E_SHELL_WINDOW_ACTION_MEMO_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-print") -#define E_SHELL_WINDOW_ACTION_MEMO_SAVE_AS(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-save-as") - -/* Memo List Actions */ -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-copy") -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-delete") -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-new") -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-print") -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_PRINT_PREVIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-print-preview") -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_PROPERTIES(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-properties") -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_RENAME(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-rename") -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_SELECT_ONE(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-select-one") - -/* Memo Query Actions */ -#define E_SHELL_WINDOW_ACTION_MEMO_FILTER_ANY_CATEGORY(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-filter-any-category") -#define E_SHELL_WINDOW_ACTION_MEMO_FILTER_UNMATCHED(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-filter-unmatched") -#define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_ANY_FIELD_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-search-any-field-contains") -#define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_DESCRIPTION_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-search-description-contains") -#define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_SUMMARY_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-search-summary-contains") - -/* Action Groups */ -#define E_SHELL_WINDOW_ACTION_GROUP_MEMOS(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "memos") -#define E_SHELL_WINDOW_ACTION_GROUP_MEMOS_FILTER(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "memos-filter") - -#endif /* E_MEMO_SHELL_VIEW_ACTIONS_H */ diff --git a/calendar/module/e-memo-shell-view-private.c b/calendar/module/e-memo-shell-view-private.c deleted file mode 100644 index 69d6c0afe2..0000000000 --- a/calendar/module/e-memo-shell-view-private.c +++ /dev/null @@ -1,524 +0,0 @@ -/* - * e-memo-shell-view-private.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-memo-shell-view-private.h" - -#include "widgets/menus/gal-view-factory-etable.h" - -static void -memo_shell_view_table_popup_event_cb (EShellView *shell_view, - GdkEventButton *event) -{ - const gchar *widget_path; - - widget_path = "/memo-popup"; - e_shell_view_show_popup_menu (shell_view, widget_path, event); -} - -static void -memo_shell_view_table_user_created_cb (EMemoShellView *memo_shell_view, - EMemoTable *memo_table) -{ - EMemoShellSidebar *memo_shell_sidebar; - ECalModel *model; - ECal *client; - ESource *source; - - /* This is the "Click to Add" handler. */ - - model = e_memo_table_get_model (memo_table); - client = e_cal_model_get_default_client (model); - source = e_cal_get_source (client); - - memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; - e_memo_shell_sidebar_add_source (memo_shell_sidebar, source); - - e_cal_model_add_client (model, client); -} - -static void -memo_shell_view_selector_client_added_cb (EMemoShellView *memo_shell_view, - ECal *client) -{ - EMemoShellContent *memo_shell_content; - EMemoTable *memo_table; - ECalModel *model; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - model = e_memo_table_get_model (memo_table); - - e_cal_model_add_client (model, client); -} - -static void -memo_shell_view_selector_client_removed_cb (EMemoShellView *memo_shell_view, - ECal *client) -{ - EMemoShellContent *memo_shell_content; - EMemoTable *memo_table; - ECalModel *model; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - model = e_memo_table_get_model (memo_table); - - e_cal_model_remove_client (model, client); -} - -static gboolean -memo_shell_view_selector_popup_event_cb (EShellView *shell_view, - ESource *primary_source, - GdkEventButton *event) -{ - const gchar *widget_path; - - widget_path = "/memo-list-popup"; - e_shell_view_show_popup_menu (shell_view, widget_path, event); - - return TRUE; -} - -static void -memo_shell_view_load_view_collection (EShellViewClass *shell_view_class) -{ - GalViewCollection *collection; - GalViewFactory *factory; - ETableSpecification *spec; - const gchar *base_dir; - gchar *filename; - - collection = shell_view_class->view_collection; - - base_dir = EVOLUTION_ETSPECDIR; - spec = e_table_specification_new (); - filename = g_build_filename (base_dir, ETSPEC_FILENAME, NULL); - if (!e_table_specification_load_from_file (spec, filename)) - g_critical ("Unable to load ETable specification file " - "for memos"); - g_free (filename); - - factory = gal_view_factory_etable_new (spec); - gal_view_collection_add_factory (collection, factory); - g_object_unref (factory); - g_object_unref (spec); - - gal_view_collection_load (collection); -} - -static void -memo_shell_view_notify_view_id_cb (EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - GalViewInstance *view_instance; - const gchar *view_id; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - view_instance = - e_memo_shell_content_get_view_instance (memo_shell_content); - view_id = e_shell_view_get_view_id (E_SHELL_VIEW (memo_shell_view)); - - /* A NULL view ID implies we're in a custom view. But you can - * only get to a custom view via the "Define Views" dialog, which - * would have already modified the view instance appropriately. - * Furthermore, there's no way to refer to a custom view by ID - * anyway, since custom views have no IDs. */ - if (view_id == NULL) - return; - - gal_view_instance_set_current_view_id (view_instance, view_id); -} - -void -e_memo_shell_view_private_init (EMemoShellView *memo_shell_view, - EShellViewClass *shell_view_class) -{ - if (!gal_view_collection_loaded (shell_view_class->view_collection)) - memo_shell_view_load_view_collection (shell_view_class); - - g_signal_connect ( - memo_shell_view, "notify::view-id", - G_CALLBACK (memo_shell_view_notify_view_id_cb), NULL); -} - -void -e_memo_shell_view_private_constructed (EMemoShellView *memo_shell_view) -{ - EMemoShellViewPrivate *priv = memo_shell_view->priv; - EMemoShellContent *memo_shell_content; - EMemoShellSidebar *memo_shell_sidebar; - EShellView *shell_view; - EShellBackend *shell_backend; - EShellContent *shell_content; - EShellSidebar *shell_sidebar; - EShellWindow *shell_window; - EMemoTable *memo_table; - ECalModel *model; - ETable *table; - ESourceSelector *selector; - - shell_view = E_SHELL_VIEW (memo_shell_view); - shell_backend = e_shell_view_get_shell_backend (shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - e_shell_window_add_action_group (shell_window, "memos"); - e_shell_window_add_action_group (shell_window, "memos-filter"); - - /* Cache these to avoid lots of awkward casting. */ - priv->memo_shell_backend = g_object_ref (shell_backend); - priv->memo_shell_content = g_object_ref (shell_content); - priv->memo_shell_sidebar = g_object_ref (shell_sidebar); - - memo_shell_content = E_MEMO_SHELL_CONTENT (shell_content); - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - model = e_memo_table_get_model (memo_table); - table = e_memo_table_get_table (memo_table); - - memo_shell_sidebar = E_MEMO_SHELL_SIDEBAR (shell_sidebar); - selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); - - g_signal_connect_swapped ( - memo_table, "open-component", - G_CALLBACK (e_memo_shell_view_open_memo), - memo_shell_view); - - g_signal_connect_swapped ( - memo_table, "popup-event", - G_CALLBACK (memo_shell_view_table_popup_event_cb), - memo_shell_view); - - g_signal_connect_swapped ( - memo_table, "status-message", - G_CALLBACK (e_memo_shell_view_set_status_message), - memo_shell_view); - - g_signal_connect_swapped ( - memo_table, "user-created", - G_CALLBACK (memo_shell_view_table_user_created_cb), - memo_shell_view); - - g_signal_connect_swapped ( - model, "model-changed", - G_CALLBACK (e_memo_shell_view_update_sidebar), - memo_shell_view); - - g_signal_connect_swapped ( - model, "model-rows-deleted", - G_CALLBACK (e_memo_shell_view_update_sidebar), - memo_shell_view); - - g_signal_connect_swapped ( - model, "model-rows-inserted", - G_CALLBACK (e_memo_shell_view_update_sidebar), - memo_shell_view); - - g_signal_connect_swapped ( - table, "selection-change", - G_CALLBACK (e_memo_shell_view_update_sidebar), - memo_shell_view); - - g_signal_connect_swapped ( - memo_shell_sidebar, "client-added", - G_CALLBACK (memo_shell_view_selector_client_added_cb), - memo_shell_view); - - g_signal_connect_swapped ( - memo_shell_sidebar, "client-removed", - G_CALLBACK (memo_shell_view_selector_client_removed_cb), - memo_shell_view); - - g_signal_connect_swapped ( - memo_shell_sidebar, "status-message", - G_CALLBACK (e_memo_shell_view_set_status_message), - memo_shell_view); - - g_signal_connect_swapped ( - selector, "popup-event", - G_CALLBACK (memo_shell_view_selector_popup_event_cb), - memo_shell_view); - - g_signal_connect_swapped ( - selector, "primary-selection-changed", - G_CALLBACK (e_shell_view_update_actions), - memo_shell_view); - - e_categories_register_change_listener ( - G_CALLBACK (e_memo_shell_view_update_search_filter), - memo_shell_view); - - e_memo_shell_view_actions_init (memo_shell_view); - e_memo_shell_view_update_sidebar (memo_shell_view); - e_memo_shell_view_update_search_filter (memo_shell_view); - - e_memo_shell_view_execute_search (memo_shell_view); -} - -void -e_memo_shell_view_private_dispose (EMemoShellView *memo_shell_view) -{ - EMemoShellViewPrivate *priv = memo_shell_view->priv; - - DISPOSE (priv->memo_shell_backend); - DISPOSE (priv->memo_shell_content); - DISPOSE (priv->memo_shell_sidebar); - - if (memo_shell_view->priv->activity != NULL) { - /* XXX Activity is not cancellable. */ - e_activity_complete (memo_shell_view->priv->activity); - g_object_unref (memo_shell_view->priv->activity); - memo_shell_view->priv->activity = NULL; - } -} - -void -e_memo_shell_view_private_finalize (EMemoShellView *memo_shell_view) -{ - /* XXX Nothing to do? */ -} - -void -e_memo_shell_view_execute_search (EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - EShellView *shell_view; - EShellWindow *shell_window; - EShellContent *shell_content; - GtkAction *action; - GString *string; - ECalComponentPreview *memo_preview; - EMemoTable *memo_table; - ECalModel *model; - FilterRule *rule; - const gchar *format; - const gchar *text; - gchar *query; - gchar *temp; - gint value; - - shell_view = E_SHELL_VIEW (memo_shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - text = e_shell_content_get_search_text (shell_content); - - shell_window = e_shell_view_get_shell_window (shell_view); - action = ACTION (MEMO_SEARCH_ANY_FIELD_CONTAINS); - value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); - - if (text == NULL || *text == '\0') { - text = ""; - value = MEMO_SEARCH_SUMMARY_CONTAINS; - } - - switch (value) { - default: - text = ""; - /* fall through */ - - case MEMO_SEARCH_SUMMARY_CONTAINS: - format = "(contains? \"summary\" %s)"; - break; - - case MEMO_SEARCH_DESCRIPTION_CONTAINS: - format = "(contains? \"description\" %s)"; - break; - - case MEMO_SEARCH_ANY_FIELD_CONTAINS: - format = "(contains? \"any\" %s)"; - break; - } - - /* Build the query. */ - string = g_string_new (""); - e_sexp_encode_string (string, text); - query = g_strdup_printf (format, string->str); - g_string_free (string, TRUE); - - /* Apply selected filter. */ - value = e_shell_content_get_filter_value (shell_content); - switch (value) { - case MEMO_FILTER_ANY_CATEGORY: - break; - - case MEMO_FILTER_UNMATCHED: - temp = g_strdup_printf ( - "(and (has-categories? #f) %s", query); - g_free (query); - query = temp; - break; - - default: - { - GList *categories; - const gchar *category_name; - - categories = e_categories_get_list (); - category_name = g_list_nth_data (categories, value); - g_list_free (categories); - - temp = g_strdup_printf ( - "(and (has-categories? \"%s\") %s)", - category_name, query); - g_free (query); - query = temp; - } - } - - /* XXX This is wrong. We need to programmatically construct a - * FilterRule, tell it to build code, and pass the resulting - * expression string to ECalModel. */ - rule = filter_rule_new (); - e_shell_content_set_search_rule (shell_content, rule); - g_object_unref (rule); - - /* Submit the query. */ - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - model = e_memo_table_get_model (memo_table); - e_cal_model_set_search_query (model, query); - g_free (query); - - memo_preview = - e_memo_shell_content_get_memo_preview (memo_shell_content); - e_cal_component_preview_clear (memo_preview); -} - -void -e_memo_shell_view_open_memo (EMemoShellView *memo_shell_view, - ECalModelComponent *comp_data) -{ - EShell *shell; - EShellView *shell_view; - EShellWindow *shell_window; - CompEditor *editor; - CompEditorFlags flags = 0; - ECalComponent *comp; - icalcomponent *clone; - const gchar *uid; - - g_return_if_fail (E_IS_MEMO_SHELL_VIEW (memo_shell_view)); - g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data)); - - shell_view = E_SHELL_VIEW (memo_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell = e_shell_window_get_shell (shell_window); - - uid = icalcomponent_get_uid (comp_data->icalcomp); - editor = comp_editor_find_instance (uid); - - if (editor != NULL) - goto exit; - - comp = e_cal_component_new (); - clone = icalcomponent_new_clone (comp_data->icalcomp); - e_cal_component_set_icalcomponent (comp, clone); - - if (e_cal_component_has_organizer (comp)) - flags |= COMP_EDITOR_IS_SHARED; - - if (itip_organizer_is_user (comp, comp_data->client)) - flags |= COMP_EDITOR_USER_ORG; - - editor = memo_editor_new (comp_data->client, shell, flags); - comp_editor_edit_comp (editor, comp); - - g_object_unref (comp); - -exit: - gtk_window_present (GTK_WINDOW (editor)); -} - -void -e_memo_shell_view_set_status_message (EMemoShellView *memo_shell_view, - const gchar *status_message, - gdouble percent) -{ - EActivity *activity; - EShellView *shell_view; - EShellBackend *shell_backend; - - g_return_if_fail (E_IS_MEMO_SHELL_VIEW (memo_shell_view)); - - activity = memo_shell_view->priv->activity; - shell_view = E_SHELL_VIEW (memo_shell_view); - shell_backend = e_shell_view_get_shell_backend (shell_view); - - if (status_message == NULL || *status_message == '\0') { - if (activity != NULL) { - e_activity_complete (activity); - g_object_unref (activity); - activity = NULL; - } - - } else if (activity == NULL) { - activity = e_activity_new (status_message); - e_activity_set_percent (activity, percent); - e_shell_backend_add_activity (shell_backend, activity); - - } else { - e_activity_set_percent (activity, percent); - e_activity_set_primary_text (activity, status_message); - } - - memo_shell_view->priv->activity = activity; -} - -void -e_memo_shell_view_update_sidebar (EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - EShellView *shell_view; - EShellSidebar *shell_sidebar; - EMemoTable *memo_table; - ECalModel *model; - ETable *table; - GString *string; - const gchar *format; - gint n_rows; - gint n_selected; - - shell_view = E_SHELL_VIEW (memo_shell_view); - shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - - model = e_memo_table_get_model (memo_table); - table = e_memo_table_get_table (memo_table); - - n_rows = e_table_model_row_count (E_TABLE_MODEL (model)); - n_selected = e_table_selected_count (table); - - string = g_string_sized_new (64); - - format = ngettext ("%d memo", "%d memos", n_rows); - g_string_append_printf (string, format, n_rows); - - if (n_selected > 0) { - format = _("%d selected"); - g_string_append_len (string, ", ", 2); - g_string_append_printf (string, format, n_selected); - } - - e_shell_sidebar_set_secondary_text (shell_sidebar, string->str); - - g_string_free (string, TRUE); -} diff --git a/calendar/module/e-memo-shell-view-private.h b/calendar/module/e-memo-shell-view-private.h deleted file mode 100644 index c41eaed7c0..0000000000 --- a/calendar/module/e-memo-shell-view-private.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * e-memo-shell-view-private.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_MEMO_SHELL_VIEW_PRIVATE_H -#define E_MEMO_SHELL_VIEW_PRIVATE_H - -#include "e-memo-shell-view.h" - -#include -#include -#include -#include - -#include "e-util/e-dialog-utils.h" -#include "e-util/e-error.h" -#include "e-util/e-util.h" -#include "e-util/gconf-bridge.h" -#include "widgets/misc/e-popup-action.h" - -#include "calendar/gui/comp-util.h" -#include "calendar/gui/e-cal-component-preview.h" -#include "calendar/gui/e-calendar-selector.h" -#include "calendar/gui/print.h" -#include "calendar/gui/dialogs/calendar-setup.h" -#include "calendar/gui/dialogs/copy-source-dialog.h" -#include "calendar/gui/dialogs/memo-editor.h" - -#include "e-memo-shell-backend.h" -#include "e-memo-shell-content.h" -#include "e-memo-shell-sidebar.h" -#include "e-memo-shell-view-actions.h" - -#define E_MEMO_SHELL_VIEW_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_MEMO_SHELL_VIEW, EMemoShellViewPrivate)) - -/* Shorthand, requires a variable named "shell_window". */ -#define ACTION(name) \ - (E_SHELL_WINDOW_ACTION_##name (shell_window)) -#define ACTION_GROUP(name) \ - (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) - -/* For use in dispose() methods. */ -#define DISPOSE(obj) \ - G_STMT_START { \ - if ((obj) != NULL) { g_object_unref (obj); (obj) = NULL; } \ - } G_STMT_END - -/* ETable Specifications */ -#define ETSPEC_FILENAME "e-memo-table.etspec" - -G_BEGIN_DECLS - -/* Filter items are displayed in ascending order. - * Non-negative values are reserved for categories. */ -enum { - MEMO_FILTER_ANY_CATEGORY = -2, - MEMO_FILTER_UNMATCHED = -1 -}; - -/* Search items are displayed in ascending order. */ -enum { - MEMO_SEARCH_SUMMARY_CONTAINS, - MEMO_SEARCH_DESCRIPTION_CONTAINS, - MEMO_SEARCH_ANY_FIELD_CONTAINS -}; - -struct _EMemoShellViewPrivate { - - /* These are just for convenience. */ - EMemoShellBackend *memo_shell_backend; - EMemoShellContent *memo_shell_content; - EMemoShellSidebar *memo_shell_sidebar; - - EActivity *activity; -}; - -void e_memo_shell_view_private_init - (EMemoShellView *memo_shell_view, - EShellViewClass *shell_view_class); -void e_memo_shell_view_private_constructed - (EMemoShellView *memo_shell_view); -void e_memo_shell_view_private_dispose - (EMemoShellView *memo_shell_view); -void e_memo_shell_view_private_finalize - (EMemoShellView *memo_shell_view); - -/* Private Utilities */ - -void e_memo_shell_view_actions_init - (EMemoShellView *memo_shell_view); -void e_memo_shell_view_execute_search - (EMemoShellView *memo_shell_view); -void e_memo_shell_view_open_memo - (EMemoShellView *memo_shell_view, - ECalModelComponent *comp_data); -void e_memo_shell_view_set_status_message - (EMemoShellView *memo_shell_view, - const gchar *status_message, - gdouble percent); -void e_memo_shell_view_update_sidebar - (EMemoShellView *memo_shell_view); -void e_memo_shell_view_update_search_filter - (EMemoShellView *memo_shell_view); - -G_END_DECLS - -#endif /* E_MEMO_SHELL_VIEW_PRIVATE_H */ diff --git a/calendar/module/e-memo-shell-view.c b/calendar/module/e-memo-shell-view.c deleted file mode 100644 index e2964b061c..0000000000 --- a/calendar/module/e-memo-shell-view.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * e-memo-shell-view.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-memo-shell-view-private.h" - -static gpointer parent_class; -static GType memo_shell_view_type; - -static void -memo_shell_view_dispose (GObject *object) -{ - e_memo_shell_view_private_dispose (E_MEMO_SHELL_VIEW (object)); - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -memo_shell_view_finalize (GObject *object) -{ - e_memo_shell_view_private_finalize (E_MEMO_SHELL_VIEW (object)); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -memo_shell_view_constructed (GObject *object) -{ - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (parent_class)->constructed (object); - - e_memo_shell_view_private_constructed (E_MEMO_SHELL_VIEW (object)); -} - -static void -memo_shell_view_update_actions (EShellView *shell_view) -{ - EMemoShellViewPrivate *priv; - EShellContent *shell_content; - EShellSidebar *shell_sidebar; - EShellWindow *shell_window; - GtkAction *action; - const gchar *label; - gboolean sensitive; - guint32 state; - - /* Be descriptive. */ - gboolean any_memos_selected; - gboolean has_primary_source; - gboolean multiple_memos_selected; - gboolean primary_source_is_system; - gboolean selection_has_url; - gboolean single_memo_selected; - gboolean sources_are_editable; - - priv = E_MEMO_SHELL_VIEW_GET_PRIVATE (shell_view); - - shell_window = e_shell_view_get_shell_window (shell_view); - - shell_content = e_shell_view_get_shell_content (shell_view); - state = e_shell_content_check_state (shell_content); - - single_memo_selected = - (state & E_MEMO_SHELL_CONTENT_SELECTION_SINGLE); - multiple_memos_selected = - (state & E_MEMO_SHELL_CONTENT_SELECTION_MULTIPLE); - sources_are_editable = - (state & E_MEMO_SHELL_CONTENT_SELECTION_CAN_EDIT); - selection_has_url = - (state & E_MEMO_SHELL_CONTENT_SELECTION_HAS_URL); - - shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - state = e_shell_sidebar_check_state (shell_sidebar); - - has_primary_source = - (state & E_MEMO_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE); - primary_source_is_system = - (state & E_MEMO_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM); - - any_memos_selected = - (single_memo_selected || multiple_memos_selected); - - action = ACTION (MEMO_CLIPBOARD_COPY); - sensitive = any_memos_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MEMO_CLIPBOARD_CUT); - sensitive = any_memos_selected && sources_are_editable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MEMO_CLIPBOARD_PASTE); - sensitive = sources_are_editable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MEMO_DELETE); - sensitive = any_memos_selected && sources_are_editable; - gtk_action_set_sensitive (action, sensitive); - if (multiple_memos_selected) - label = _("Delete Memos"); - else - label = _("Delete Memo"); - g_object_set (action, "label", label, NULL); - - action = ACTION (MEMO_FORWARD); - sensitive = single_memo_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MEMO_LIST_COPY); - sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MEMO_LIST_DELETE); - sensitive = has_primary_source && !primary_source_is_system; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MEMO_LIST_PROPERTIES); - sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MEMO_LIST_RENAME); - sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MEMO_OPEN); - sensitive = single_memo_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MEMO_OPEN_URL); - sensitive = single_memo_selected && selection_has_url; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MEMO_PRINT); - sensitive = single_memo_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MEMO_SAVE_AS); - sensitive = single_memo_selected; - gtk_action_set_sensitive (action, sensitive); -} - -static void -memo_shell_view_class_init (EMemoShellViewClass *class, - GTypeModule *type_module) -{ - GObjectClass *object_class; - EShellViewClass *shell_view_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (EMemoShellViewPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->dispose = memo_shell_view_dispose; - object_class->finalize = memo_shell_view_finalize; - object_class->constructed = memo_shell_view_constructed; - - shell_view_class = E_SHELL_VIEW_CLASS (class); - shell_view_class->label = _("Memos"); - shell_view_class->icon_name = "evolution-memos"; - shell_view_class->ui_definition = "evolution-memos.ui"; - shell_view_class->ui_manager_id = "org.gnome.evolution.memos"; - shell_view_class->search_options = "/memo-search-options"; - shell_view_class->search_rules = "memotypes.xml"; - shell_view_class->new_shell_content = e_memo_shell_content_new; - shell_view_class->new_shell_sidebar = e_memo_shell_sidebar_new; - shell_view_class->update_actions = memo_shell_view_update_actions; -} - -static void -memo_shell_view_init (EMemoShellView *memo_shell_view, - EShellViewClass *shell_view_class) -{ - memo_shell_view->priv = - E_MEMO_SHELL_VIEW_GET_PRIVATE (memo_shell_view); - - e_memo_shell_view_private_init (memo_shell_view, shell_view_class); -} - -GType -e_memo_shell_view_get_type (void) -{ - return memo_shell_view_type; -} - -void -e_memo_shell_view_register_type (GTypeModule *type_module) -{ - const GTypeInfo type_info = { - sizeof (EMemoShellViewClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) memo_shell_view_class_init, - (GClassFinalizeFunc) NULL, - type_module, - sizeof (EMemoShellView), - 0, /* n_preallocs */ - (GInstanceInitFunc) memo_shell_view_init, - NULL /* value_table */ - }; - - memo_shell_view_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_VIEW, - "EMemoShellView", &type_info, 0); -} diff --git a/calendar/module/e-memo-shell-view.h b/calendar/module/e-memo-shell-view.h deleted file mode 100644 index 686ae734c9..0000000000 --- a/calendar/module/e-memo-shell-view.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * e-memo-shell-view.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_MEMO_SHELL_VIEW_H -#define E_MEMO_SHELL_VIEW_H - -#include -#include - -/* Standard GObject macros */ -#define E_TYPE_MEMO_SHELL_VIEW \ - (e_memo_shell_view_get_type ()) -#define E_MEMO_SHELL_VIEW(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_MEMO_SHELL_VIEW, EMemoShellView)) -#define E_MEMO_SHELL_VIEW_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_MEMO_SHELL_VIEW, EMemoShellViewClass)) -#define E_IS_MEMO_SHELL_VIEW(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_MEMO_SHELL_VIEW)) -#define E_IS_MEMO_SHELL_VIEW_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_MEMO_SHELL_VIEW)) -#define E_MEMO_SHELL_VIEW_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_MEMO_SHELL_VIEW, EMemoShellViewClass)) - -G_BEGIN_DECLS - -typedef struct _EMemoShellView EMemoShellView; -typedef struct _EMemoShellViewClass EMemoShellViewClass; -typedef struct _EMemoShellViewPrivate EMemoShellViewPrivate; - -struct _EMemoShellView { - EShellView parent; - EMemoShellViewPrivate *priv; -}; - -struct _EMemoShellViewClass { - EShellViewClass parent_class; -}; - -GType e_memo_shell_view_get_type (void); -void e_memo_shell_view_register_type (GTypeModule *type_module); - -G_END_DECLS - -#endif /* E_MEMO_SHELL_VIEW_H */ diff --git a/calendar/module/e-task-shell-backend.c b/calendar/module/e-task-shell-backend.c deleted file mode 100644 index 6bded3e412..0000000000 --- a/calendar/module/e-task-shell-backend.c +++ /dev/null @@ -1,621 +0,0 @@ -/* - * e-task-shell-backend.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-task-shell-backend.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "shell/e-shell.h" -#include "shell/e-shell-backend.h" -#include "shell/e-shell-window.h" - -#include "calendar/common/authentication.h" -#include "calendar/gui/calendar-config.h" -#include "calendar/gui/comp-util.h" -#include "calendar/gui/dialogs/calendar-setup.h" -#include "calendar/gui/dialogs/task-editor.h" - -#include "e-task-shell-content.h" -#include "e-task-shell-migrate.h" -#include "e-task-shell-sidebar.h" -#include "e-task-shell-view.h" - -#define E_TASK_SHELL_BACKEND_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_TASK_SHELL_BACKEND, ETaskShellBackendPrivate)) - -#define WEB_BASE_URI "webcal://" -#define PERSONAL_RELATIVE_URI "system" - -struct _ETaskShellBackendPrivate { - ESourceList *source_list; -}; - -enum { - PROP_0, - PROP_SOURCE_LIST -}; - -static gpointer parent_class; -static GType task_shell_backend_type; - -static void -task_module_ensure_sources (EShellBackend *shell_backend) -{ - /* XXX This is basically the same algorithm across all modules. - * Maybe we could somehow integrate this into EShellBackend? */ - - ETaskShellBackendPrivate *priv; - ESourceGroup *on_this_computer; - ESourceGroup *on_the_web; - ESource *personal; - GSList *groups, *iter; - const gchar *data_dir; - const gchar *name; - gchar *base_uri; - gchar *filename; - - on_this_computer = NULL; - on_the_web = NULL; - personal = NULL; - - priv = E_TASK_SHELL_BACKEND_GET_PRIVATE (shell_backend); - - if (!e_cal_get_sources (&priv->source_list, E_CAL_SOURCE_TYPE_TODO, NULL)) { - g_warning ("Could not get task sources from GConf!"); - return; - } - - data_dir = e_shell_backend_get_data_dir (shell_backend); - filename = g_build_filename (data_dir, "local", NULL); - base_uri = g_filename_to_uri (filename, NULL, NULL); - g_free (filename); - - groups = e_source_list_peek_groups (priv->source_list); - for (iter = groups; iter != NULL; iter = iter->next) { - ESourceGroup *source_group = iter->data; - const gchar *group_base_uri; - - group_base_uri = e_source_group_peek_base_uri (source_group); - - /* Compare only "file://" part. If the user's home - * changes, we do not want to create another group. */ - if (on_this_computer == NULL && - strncmp (base_uri, group_base_uri, 7) == 0) - on_this_computer = source_group; - - else if (on_the_web == NULL && - strcmp (WEB_BASE_URI, group_base_uri) == 0) - on_the_web = source_group; - } - - name = _("On This Computer"); - - if (on_this_computer != NULL) { - GSList *sources; - const gchar *group_base_uri; - - /* Force the group name to the current locale. */ - e_source_group_set_name (on_this_computer, name); - - sources = e_source_group_peek_sources (on_this_computer); - group_base_uri = e_source_group_peek_base_uri (on_this_computer); - - /* Make sure this group includes a "Personal" source. */ - for (iter = sources; iter != NULL; iter = iter->next) { - ESource *source = iter->data; - const gchar *relative_uri; - - relative_uri = e_source_peek_relative_uri (source); - if (relative_uri == NULL) - continue; - - if (strcmp (PERSONAL_RELATIVE_URI, relative_uri) != 0) - continue; - - personal = source; - break; - } - - /* Make sure we have the correct base URI. This can - * change when the user's home directory changes. */ - if (strcmp (base_uri, group_base_uri) != 0) { - e_source_group_set_base_uri ( - on_this_computer, base_uri); - - /* XXX We shouldn't need this sync call here as - * set_base_uri() results in synching to GConf, - * but that happens in an idle loop and too late - * to prevent the user from seeing a "Cannot - * Open ... because of invalid URI" error. */ - e_source_list_sync (priv->source_list, NULL); - } - - } else { - ESourceGroup *source_group; - - source_group = e_source_group_new (name, base_uri); - e_source_list_add_group (priv->source_list, source_group, -1); - g_object_unref (source_group); - } - - name = _("Personal"); - - if (personal == NULL) { - ESource *source; - GSList *selected; - gchar *primary; - - source = e_source_new (name, PERSONAL_RELATIVE_URI); - e_source_group_add_source (on_this_computer, source, -1); - g_object_unref (source); - - primary = calendar_config_get_primary_tasks (); - selected = calendar_config_get_tasks_selected (); - - if (primary == NULL && selected == NULL) { - const gchar *uid; - - uid = e_source_peek_uid (source); - selected = g_slist_prepend (NULL, g_strdup (uid)); - - calendar_config_set_primary_tasks (uid); - calendar_config_set_tasks_selected (selected); - } - - g_slist_foreach (selected, (GFunc) g_free, NULL); - g_slist_free (selected); - g_free (primary); - } else { - /* Force the source name to the current locale. */ - e_source_set_name (personal, name); - } - - name = _("On The Web"); - - if (on_the_web == NULL) { - ESourceGroup *source_group; - - source_group = e_source_group_new (name, WEB_BASE_URI); - e_source_list_add_group (priv->source_list, source_group, -1); - g_object_unref (source_group); - } else { - /* Force the group name to the current locale. */ - e_source_group_set_name (on_the_web, name); - } - - g_free (base_uri); -} - -static void -task_module_cal_opened_cb (ECal *cal, - ECalendarStatus status, - GtkAction *action) -{ - EShell *shell; - ECalComponent *comp; - CompEditor *editor; - CompEditorFlags flags = 0; - const gchar *action_name; - - /* FIXME Pass this in. */ - shell = e_shell_get_default (); - - /* XXX Handle errors better. */ - if (status != E_CALENDAR_STATUS_OK) - return; - - action_name = gtk_action_get_name (action); - - flags |= COMP_EDITOR_NEW_ITEM; - if (strcmp (action_name, "task-assigned-new") == 0) { - flags |= COMP_EDITOR_IS_ASSIGNED; - flags |= COMP_EDITOR_USER_ORG; - } - - editor = task_editor_new (cal, shell, flags); - comp = cal_comp_task_new_with_defaults (cal); - comp_editor_edit_comp (editor, comp); - - gtk_window_present (GTK_WINDOW (editor)); - - g_object_unref (comp); - g_object_unref (cal); -} - -static void -action_task_new_cb (GtkAction *action, - EShellWindow *shell_window) -{ - ECal *cal = NULL; - ECalSourceType source_type; - ESourceList *source_list; - gchar *uid; - - /* This callback is used for both tasks and assigned tasks. */ - - source_type = E_CAL_SOURCE_TYPE_TODO; - - if (!e_cal_get_sources (&source_list, source_type, NULL)) { - g_warning ("Could not get task sources from GConf!"); - return; - } - - uid = calendar_config_get_primary_tasks (); - - if (uid != NULL) { - ESource *source; - - source = e_source_list_peek_source_by_uid (source_list, uid); - if (source != NULL) - cal = auth_new_cal_from_source (source, source_type); - g_free (uid); - } - - if (cal == NULL) - cal = auth_new_cal_from_default (source_type); - - g_return_if_fail (cal != NULL); - - g_signal_connect ( - cal, "cal-opened", - G_CALLBACK (task_module_cal_opened_cb), action); - - e_cal_open_async (cal, FALSE); -} - -static void -action_task_list_new_cb (GtkAction *action, - EShellWindow *shell_window) -{ - calendar_setup_new_task_list (GTK_WINDOW (shell_window)); -} - -static GtkActionEntry item_entries[] = { - - { "task-new", - "stock_task", - NC_("New", "_Task"), - "t", - N_("Create a new task"), - G_CALLBACK (action_task_new_cb) }, - - { "task-assigned-new", - "stock_task", - N_("Assigne_d Task"), - NULL, - N_("Create a new assigned task"), - G_CALLBACK (action_task_new_cb) } -}; - -static GtkActionEntry source_entries[] = { - - { "task-list-new", - "stock_todo", - NC_("New", "Tas_k List"), - NULL, - N_("Create a new task list"), - G_CALLBACK (action_task_list_new_cb) } -}; - -static gboolean -task_module_handle_uri_cb (EShellBackend *shell_backend, - const gchar *uri) -{ - EShell *shell; - CompEditor *editor; - CompEditorFlags flags = 0; - ECal *client; - ECalComponent *comp; - ESource *source; - ESourceList *source_list; - ECalSourceType source_type; - EUri *euri; - icalcomponent *icalcomp; - icalproperty *icalprop; - const gchar *cp; - gchar *source_uid = NULL; - gchar *comp_uid = NULL; - gchar *comp_rid = NULL; - gboolean handled = FALSE; - GError *error = NULL; - - source_type = E_CAL_SOURCE_TYPE_TODO; - shell = e_shell_backend_get_shell (shell_backend); - - if (strncmp (uri, "task:", 5) != 0) - return FALSE; - - euri = e_uri_new (uri); - cp = euri->query; - if (cp == NULL) - goto exit; - - while (*cp != '\0') { - gchar *header; - gchar *content; - gsize header_len; - gsize content_len; - - header_len = strcspn (cp, "=&"); - - /* If it's malformed, give up. */ - if (cp[header_len] != '=') - break; - - header = (gchar *) cp; - header[header_len] = '\0'; - cp += header_len + 1; - - content_len = strcspn (cp, "&"); - - content = g_strndup (cp, content_len); - if (g_ascii_strcasecmp (header, "source-uid") == 0) - source_uid = g_strdup (content); - else if (g_ascii_strcasecmp (header, "comp-uid") == 0) - comp_uid = g_strdup (content); - else if (g_ascii_strcasecmp (header, "comp-rid") == 0) - comp_rid = g_strdup (content); - g_free (content); - - cp += content_len; - if (*cp == '&') { - cp++; - if (strcmp (cp, "amp;") == 0) - cp += 4; - } - } - - if (source_uid != NULL || comp_uid != NULL) - goto exit; - - /* URI is valid, so consider it handled. Whether - * we successfully open it is another matter... */ - handled = TRUE; - - if (!e_cal_get_sources (&source_list, source_type, NULL)) { - g_printerr ("Could not get task sources from GConf!\n"); - goto exit; - } - - source = e_source_list_peek_source_by_uid (source_list, source_uid); - if (source == NULL) { - g_printerr ("No source for UID `%s'\n", source_uid); - g_object_unref (source_list); - goto exit; - } - - client = auth_new_cal_from_source (source, source_type); - if (client == NULL || !e_cal_open (client, TRUE, &error)) { - g_printerr ("%s\n", error->message); - g_object_unref (source_list); - g_error_free (error); - goto exit; - } - - /* XXX Copied from e_task_shell_view_open_task(). - * Clearly a new utility function is needed. */ - - editor = comp_editor_find_instance (comp_uid); - - if (editor != NULL) - goto present; - - if (!e_cal_get_object (client, comp_uid, comp_rid, &icalcomp, &error)) { - g_printerr ("%s\n", error->message); - g_object_unref (source_list); - g_error_free (error); - goto exit; - } - - comp = e_cal_component_new (); - e_cal_component_set_icalcomponent (comp, icalcomp); - - icalprop = icalcomponent_get_first_property ( - icalcomp, ICAL_ATTENDEE_PROPERTY); - if (icalprop != NULL) - flags |= COMP_EDITOR_IS_ASSIGNED; - - if (itip_organizer_is_user (comp, client)) - flags |= COMP_EDITOR_USER_ORG; - - if (!e_cal_component_has_attendees (comp)) - flags |= COMP_EDITOR_USER_ORG; - - editor = task_editor_new (client, shell, flags); - comp_editor_edit_comp (editor, comp); - - g_object_unref (comp); - -present: - gtk_window_present (GTK_WINDOW (editor)); - - g_object_unref (source_list); - g_object_unref (client); - -exit: - g_free (source_uid); - g_free (comp_uid); - g_free (comp_rid); - - e_uri_free (euri); - - return handled; -} - -static void -task_module_window_created_cb (EShellBackend *shell_backend, - GtkWindow *window) -{ - const gchar *module_name; - - if (!E_IS_SHELL_WINDOW (window)) - return; - - module_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name; - - e_shell_window_register_new_item_actions ( - E_SHELL_WINDOW (window), module_name, - item_entries, G_N_ELEMENTS (item_entries)); - - e_shell_window_register_new_source_actions ( - E_SHELL_WINDOW (window), module_name, - source_entries, G_N_ELEMENTS (source_entries)); -} - -static void -task_shell_backend_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_SOURCE_LIST: - g_value_set_object ( - value, - e_task_shell_backend_get_source_list ( - E_TASK_SHELL_BACKEND (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -task_shell_backend_dispose (GObject *object) -{ - ETaskShellBackendPrivate *priv; - - priv = E_TASK_SHELL_BACKEND_GET_PRIVATE (object); - - if (priv->source_list != NULL) { - g_object_unref (priv->source_list); - priv->source_list = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -task_shell_backend_constructed (GObject *object) -{ - EShell *shell; - EShellBackend *shell_backend; - - shell_backend = E_SHELL_BACKEND (object); - shell = e_shell_backend_get_shell (shell_backend); - - task_module_ensure_sources (shell_backend); - - g_signal_connect_swapped ( - shell, "handle-uri", - G_CALLBACK (task_module_handle_uri_cb), shell_backend); - - g_signal_connect_swapped ( - shell, "window-created", - G_CALLBACK (task_module_window_created_cb), shell_backend); -} - -static void -task_shell_backend_class_init (ETaskShellBackendClass *class) -{ - GObjectClass *object_class; - EShellBackendClass *shell_backend_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (ETaskShellBackendPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->get_property = task_shell_backend_get_property; - object_class->dispose = task_shell_backend_dispose; - object_class->constructed = task_shell_backend_constructed; - - shell_backend_class = E_SHELL_BACKEND_CLASS (class); - shell_backend_class->shell_view_type = E_TYPE_TASK_SHELL_VIEW; - shell_backend_class->name = "tasks"; - shell_backend_class->aliases = ""; - shell_backend_class->schemes = "task"; - shell_backend_class->sort_order = 600; - shell_backend_class->start = NULL; - shell_backend_class->is_busy = NULL; - shell_backend_class->shutdown = NULL; - shell_backend_class->migrate = e_task_shell_backend_migrate; - - g_object_class_install_property ( - object_class, - PROP_SOURCE_LIST, - g_param_spec_object ( - "source-list", - _("Source List"), - _("The registry of task lists"), - E_TYPE_SOURCE_LIST, - G_PARAM_READABLE)); -} - -static void -task_shell_backend_init (ETaskShellBackend *task_shell_backend) -{ - task_shell_backend->priv = - E_TASK_SHELL_BACKEND_GET_PRIVATE (task_shell_backend); -} - -GType -e_task_shell_backend_get_type (void) -{ - return task_shell_backend_type; -} - -void -e_task_shell_backend_register_type (GTypeModule *type_module) -{ - const GTypeInfo type_info = { - sizeof (ETaskShellBackendClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) task_shell_backend_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (ETaskShellBackend), - 0, /* n_preallocs */ - (GInstanceInitFunc) task_shell_backend_init, - NULL /* value_table */ - }; - - task_shell_backend_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_BACKEND, - "ETaskShellBackend", &type_info, 0); -} - -ESourceList * -e_task_shell_backend_get_source_list (ETaskShellBackend *task_shell_backend) -{ - g_return_val_if_fail ( - E_IS_TASK_SHELL_BACKEND (task_shell_backend), NULL); - - return task_shell_backend->priv->source_list; -} diff --git a/calendar/module/e-task-shell-backend.h b/calendar/module/e-task-shell-backend.h deleted file mode 100644 index 63b157ad85..0000000000 --- a/calendar/module/e-task-shell-backend.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * e-task-shell-backend.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_TASK_SHELL_BACKEND_H -#define E_TASK_SHELL_BACKEND_H - -#include -#include - -/* Standard GObject macros */ -#define E_TYPE_TASK_SHELL_BACKEND \ - (e_task_shell_backend_get_type ()) -#define E_TASK_SHELL_BACKEND(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_TASK_SHELL_BACKEND, ETaskShellBackend)) -#define E_TASK_SHELL_BACKEND_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_TASK_SHELL_BACKEND, ETaskShellBackendClass)) -#define E_IS_TASK_SHELL_BACKEND(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_TASK_SHELL_BACKEND)) -#define E_IS_TASK_SHELL_BACKEND_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_TASK_SHELL_BACKEND)) -#define E_TASK_SHELL_BACKEND_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_TASK_SHELL_BACKEND, ETaskShellBackendClass)) - -G_BEGIN_DECLS - -typedef struct _ETaskShellBackend ETaskShellBackend; -typedef struct _ETaskShellBackendClass ETaskShellBackendClass; -typedef struct _ETaskShellBackendPrivate ETaskShellBackendPrivate; - -struct _ETaskShellBackend { - EShellBackend parent; - ETaskShellBackendPrivate *priv; -}; - -struct _ETaskShellBackendClass { - EShellBackendClass parent_class; -}; - -GType e_task_shell_backend_get_type (void); -void e_task_shell_backend_register_type - (GTypeModule *type_module); -ESourceList * e_task_shell_backend_get_source_list - (ETaskShellBackend *task_shell_backend); - -G_END_DECLS - -#endif /* E_TASK_SHELL_BACKEND_H */ diff --git a/calendar/module/e-task-shell-content.c b/calendar/module/e-task-shell-content.c deleted file mode 100644 index 0177c6c3c3..0000000000 --- a/calendar/module/e-task-shell-content.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * e-task-shell-content.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-task-shell-content.h" - -#include - -#include "e-util/gconf-bridge.h" - -#include "calendar/gui/calendar-config.h" -#include "calendar/gui/comp-util.h" -#include "calendar/gui/e-cal-model-tasks.h" -#include "calendar/gui/e-calendar-table.h" -#include "calendar/gui/e-calendar-table-config.h" - -#include "widgets/menus/gal-view-etable.h" - -#define E_TASK_SHELL_CONTENT_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_TASK_SHELL_CONTENT, ETaskShellContentPrivate)) - -#define E_CALENDAR_TABLE_DEFAULT_STATE \ - "" \ - "" \ - " " \ - " " \ - " " \ - " " \ - " " \ - "" - -struct _ETaskShellContentPrivate { - GtkWidget *paned; - GtkWidget *task_table; - GtkWidget *task_preview; - - ECalModel *task_model; - ECalendarTableConfig *table_config; - GalViewInstance *view_instance; - - gchar *current_uid; -}; - -enum { - PROP_0, - PROP_MODEL, - PROP_PREVIEW_VISIBLE -}; - -enum { - TARGET_VCALENDAR -}; - -static GtkTargetEntry drag_types[] = { - { (gchar *) "text/calendar", 0, TARGET_VCALENDAR }, - { (gchar *) "text/x-calendar", 0, TARGET_VCALENDAR } -}; - -static gpointer parent_class; -static GType task_shell_content_type; - -static void -task_shell_content_display_view_cb (ETaskShellContent *task_shell_content, - GalView *gal_view) -{ - ECalendarTable *task_table; - ETable *table; - - if (!GAL_IS_VIEW_ETABLE (gal_view)) - return; - - task_table = e_task_shell_content_get_task_table (task_shell_content); - table = e_calendar_table_get_table (task_table); - - gal_view_etable_attach_table (GAL_VIEW_ETABLE (gal_view), table); -} - -static void -task_shell_content_table_foreach_cb (gint model_row, - gpointer user_data) -{ - ECalModelComponent *comp_data; - icalcomponent *clone; - icalcomponent *vcal; - gchar *string; - - struct { - ECalModel *model; - GSList *list; - } *foreach_data = user_data; - - comp_data = e_cal_model_get_component_at ( - foreach_data->model, model_row); - - vcal = e_cal_util_new_top_level (); - clone = icalcomponent_new_clone (comp_data->icalcomp); - e_cal_util_add_timezones_from_component (vcal, comp_data->icalcomp); - icalcomponent_add_component (vcal, clone); - - /* String is owned by libical; do not free. */ - string = icalcomponent_as_ical_string (vcal); - if (string != NULL) { - ESource *source; - const gchar *source_uid; - - source = e_cal_get_source (comp_data->client); - source_uid = e_source_peek_uid (source); - - foreach_data->list = g_slist_prepend ( - foreach_data->list, - g_strdup_printf ("%s\n%s", source_uid, string)); - } - - icalcomponent_free (vcal); -} - -static void -task_shell_content_table_drag_data_get_cb (ETaskShellContent *task_shell_content, - gint row, - gint col, - GdkDragContext *context, - GtkSelectionData *selection_data, - guint info, - guint time) -{ - ECalendarTable *task_table; - ETable *table; - - struct { - ECalModel *model; - GSList *list; - } foreach_data; - - if (info != TARGET_VCALENDAR) - return; - - task_table = e_task_shell_content_get_task_table (task_shell_content); - table = e_calendar_table_get_table (task_table); - - foreach_data.model = e_calendar_table_get_model (task_table); - foreach_data.list = NULL; - - e_table_selected_row_foreach ( - table, task_shell_content_table_foreach_cb, - &foreach_data); - - if (foreach_data.list != NULL) { - cal_comp_selection_set_string_list ( - selection_data, foreach_data.list); - g_slist_foreach (foreach_data.list, (GFunc) g_free, NULL); - g_slist_free (foreach_data.list); - } -} - -static void -task_shell_content_table_drag_data_delete_cb (ETaskShellContent *task_shell_content, - gint row, - gint col, - GdkDragContext *context) -{ - /* Moved components are deleted from source immediately when moved, - * because some of them can be part of destination source, and we - * don't want to delete not-moved tasks. There is no such information - * which event has been moved and which not, so skip this method. */ -} - -static void -task_shell_content_cursor_change_cb (ETaskShellContent *task_shell_content, - gint row, - ETable *table) -{ - ECalComponentPreview *task_preview; - ECalendarTable *task_table; - ECalModel *task_model; - ECalModelComponent *comp_data; - ECalComponent *comp; - const gchar *uid; - - task_model = e_task_shell_content_get_task_model (task_shell_content); - task_table = e_task_shell_content_get_task_table (task_shell_content); - task_preview = e_task_shell_content_get_task_preview (task_shell_content); - - if (e_table_selected_count (table) != 1) { - e_cal_component_preview_clear (task_preview); - return; - } - - row = e_table_get_cursor_row (table); - comp_data = e_cal_model_get_component_at (task_model, row); - - comp = e_cal_component_new (); - e_cal_component_set_icalcomponent ( - comp, icalcomponent_new_clone (comp_data->icalcomp)); - e_cal_component_preview_display ( - task_preview, comp_data->client, comp); - - e_cal_component_get_uid (comp, &uid); - g_free (task_shell_content->priv->current_uid); - task_shell_content->priv->current_uid = g_strdup (uid); - - g_object_unref (comp); -} - -static void -task_shell_content_selection_change_cb (ETaskShellContent *task_shell_content, - ETable *table) -{ - ECalComponentPreview *task_preview; - - task_preview = e_task_shell_content_get_task_preview (task_shell_content); - - if (e_table_selected_count (table) != 1) - e_cal_component_preview_clear (task_preview); -} - -static void -task_shell_content_model_row_changed_cb (ETaskShellContent *task_shell_content, - gint row, - ETableModel *model) -{ - ECalModelComponent *comp_data; - ECalendarTable *task_table; - ETable *table; - const gchar *current_uid; - const gchar *uid; - - current_uid = task_shell_content->priv->current_uid; - if (current_uid == NULL) - return; - - comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row); - if (comp_data == NULL) - return; - - uid = icalcomponent_get_uid (comp_data->icalcomp); - if (g_strcmp0 (uid, current_uid) != 0) - return; - - task_table = e_task_shell_content_get_task_table (task_shell_content); - table = e_calendar_table_get_table (task_table); - - task_shell_content_cursor_change_cb (task_shell_content, 0, table); -} - -static void -task_shell_content_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_PREVIEW_VISIBLE: - e_task_shell_content_set_preview_visible ( - E_TASK_SHELL_CONTENT (object), - g_value_get_boolean (value)); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -task_shell_content_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_MODEL: - g_value_set_object ( - value, e_task_shell_content_get_task_model ( - E_TASK_SHELL_CONTENT (object))); - return; - - case PROP_PREVIEW_VISIBLE: - g_value_set_boolean ( - value, e_task_shell_content_get_preview_visible ( - E_TASK_SHELL_CONTENT (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -task_shell_content_dispose (GObject *object) -{ - ETaskShellContentPrivate *priv; - - priv = E_TASK_SHELL_CONTENT_GET_PRIVATE (object); - - if (priv->paned != NULL) { - g_object_unref (priv->paned); - priv->paned = NULL; - } - - if (priv->task_table != NULL) { - g_object_unref (priv->task_table); - priv->task_table = NULL; - } - - if (priv->task_preview != NULL) { - g_object_unref (priv->task_preview); - priv->task_preview = NULL; - } - - if (priv->task_model != NULL) { - g_object_unref (priv->task_model); - priv->task_model = NULL; - } - - if (priv->table_config != NULL) { - g_object_unref (priv->table_config); - priv->table_config = NULL; - } - - if (priv->view_instance != NULL) { - g_object_unref (priv->view_instance); - priv->view_instance = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -task_shell_content_finalize (GObject *object) -{ - ETaskShellContentPrivate *priv; - - priv = E_TASK_SHELL_CONTENT_GET_PRIVATE (object); - - g_free (priv->current_uid); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -task_shell_content_constructed (GObject *object) -{ - ETaskShellContentPrivate *priv; - EShellContent *shell_content; - EShellView *shell_view; - GalViewInstance *view_instance; - ETable *table; - GConfBridge *bridge; - GtkWidget *container; - GtkWidget *widget; - const gchar *key; - - priv = E_TASK_SHELL_CONTENT_GET_PRIVATE (object); - - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (parent_class)->constructed (object); - - shell_content = E_SHELL_CONTENT (object); - shell_view = e_shell_content_get_shell_view (shell_content); - - /* Build content widgets. */ - - container = GTK_WIDGET (object); - - widget = gtk_vpaned_new (); - gtk_container_add (GTK_CONTAINER (container), widget); - priv->paned = g_object_ref (widget); - gtk_widget_show (widget); - - container = widget; - - widget = e_calendar_table_new (shell_view, priv->task_model); - gtk_paned_add1 (GTK_PANED (container), widget); - priv->task_table = g_object_ref (widget); - gtk_widget_show (widget); - - widget = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy ( - GTK_SCROLLED_WINDOW (widget), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type ( - GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); - gtk_paned_add2 (GTK_PANED (container), widget); - gtk_widget_show (widget); - - container = widget; - - widget = e_cal_component_preview_new (); - e_cal_component_preview_set_default_timezone ( - E_CAL_COMPONENT_PREVIEW (widget), - calendar_config_get_icaltimezone ()); - gtk_container_add (GTK_CONTAINER (container), widget); - priv->task_preview = g_object_ref (widget); - gtk_widget_show (widget); - - /* Configure the task table. */ - - widget = E_CALENDAR_TABLE (priv->task_table)->etable; - table = e_table_scrolled_get_table (E_TABLE_SCROLLED (widget)); - - priv->table_config = e_calendar_table_config_new ( - E_CALENDAR_TABLE (priv->task_table)); - - e_table_set_state (table, E_CALENDAR_TABLE_DEFAULT_STATE); - - e_table_drag_source_set ( - table, GDK_BUTTON1_MASK, - drag_types, G_N_ELEMENTS (drag_types), - GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_ASK); - - g_signal_connect_swapped ( - table, "table-drag-data-get", - G_CALLBACK (task_shell_content_table_drag_data_get_cb), - object); - - g_signal_connect_swapped ( - table, "table-drag-data-delete", - G_CALLBACK (task_shell_content_table_drag_data_delete_cb), - object); - - g_signal_connect_swapped ( - table, "cursor-change", - G_CALLBACK (task_shell_content_cursor_change_cb), - object); - - g_signal_connect_swapped ( - table, "selection-change", - G_CALLBACK (task_shell_content_selection_change_cb), - object); - - g_signal_connect_swapped ( - priv->task_model, "model-row-changed", - G_CALLBACK (task_shell_content_model_row_changed_cb), - object); - - /* Load the view instance. */ - - view_instance = e_shell_view_new_view_instance (shell_view, NULL); - g_signal_connect_swapped ( - view_instance, "display-view", - G_CALLBACK (task_shell_content_display_view_cb), - object); - gal_view_instance_load (view_instance); - priv->view_instance = view_instance; - - /* Bind GObject properties to GConf keys. */ - - bridge = gconf_bridge_get (); - - object = G_OBJECT (priv->paned); - key = "/apps/evolution/calendar/display/task_vpane_position"; - gconf_bridge_bind_property_delayed (bridge, key, object, "position"); -} - -static guint32 -task_shell_content_check_state (EShellContent *shell_content) -{ - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - ETable *table; - GSList *list, *iter; - gboolean assignable = TRUE; - gboolean editable = TRUE; - gboolean has_url = FALSE; - gint n_selected; - gint n_complete = 0; - gint n_incomplete = 0; - guint32 state = 0; - - task_shell_content = E_TASK_SHELL_CONTENT (shell_content); - task_table = e_task_shell_content_get_task_table (task_shell_content); - - table = e_calendar_table_get_table (task_table); - n_selected = e_table_selected_count (table); - - list = e_calendar_table_get_selected (task_table); - for (iter = list; iter != NULL; iter = iter->next) { - ECalModelComponent *comp_data = iter->data; - icalproperty *prop; - const gchar *cap; - gboolean read_only; - - e_cal_is_read_only (comp_data->client, &read_only, NULL); - editable &= !read_only; - - cap = CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT; - if (e_cal_get_static_capability (comp_data->client, cap)) - assignable = FALSE; - - cap = CAL_STATIC_CAPABILITY_NO_CONV_TO_ASSIGN_TASK; - if (e_cal_get_static_capability (comp_data->client, cap)) - assignable = FALSE; - - prop = icalcomponent_get_first_property ( - comp_data->icalcomp, ICAL_URL_PROPERTY); - has_url |= (prop != NULL); - - prop = icalcomponent_get_first_property ( - comp_data->icalcomp, ICAL_COMPLETED_PROPERTY); - if (prop != NULL) - n_complete++; - else - n_incomplete++; - } - g_slist_free (list); - - if (n_selected == 1) - state |= E_TASK_SHELL_CONTENT_SELECTION_SINGLE; - if (n_selected > 1) - state |= E_TASK_SHELL_CONTENT_SELECTION_MULTIPLE; - if (assignable) - state |= E_TASK_SHELL_CONTENT_SELECTION_CAN_ASSIGN; - if (editable) - state |= E_TASK_SHELL_CONTENT_SELECTION_CAN_EDIT; - if (n_complete > 0) - state |= E_TASK_SHELL_CONTENT_SELECTION_HAS_COMPLETE; - if (n_incomplete > 0) - state |= E_TASK_SHELL_CONTENT_SELECTION_HAS_INCOMPLETE; - if (has_url) - state |= E_TASK_SHELL_CONTENT_SELECTION_HAS_URL; - - return state; -} - -static void -task_shell_content_class_init (ETaskShellContentClass *class) -{ - GObjectClass *object_class; - EShellContentClass *shell_content_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (ETaskShellContentPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->set_property = task_shell_content_set_property; - object_class->get_property = task_shell_content_get_property; - object_class->dispose = task_shell_content_dispose; - object_class->finalize = task_shell_content_finalize; - object_class->constructed = task_shell_content_constructed; - - shell_content_class = E_SHELL_CONTENT_CLASS (class); - shell_content_class->check_state = task_shell_content_check_state; - - g_object_class_install_property ( - object_class, - PROP_MODEL, - g_param_spec_object ( - "model", - _("Model"), - _("The task table model"), - E_TYPE_CAL_MODEL, - G_PARAM_READABLE)); - - g_object_class_install_property ( - object_class, - PROP_PREVIEW_VISIBLE, - g_param_spec_boolean ( - "preview-visible", - _("Preview is Visible"), - _("Whether the preview pane is visible"), - TRUE, - G_PARAM_READWRITE)); -} - -static void -task_shell_content_init (ETaskShellContent *task_shell_content) -{ - task_shell_content->priv = - E_TASK_SHELL_CONTENT_GET_PRIVATE (task_shell_content); - - task_shell_content->priv->task_model = e_cal_model_tasks_new (); - - /* Postpone widget construction until we have a shell view. */ -} - -GType -e_task_shell_content_get_type (void) -{ - return task_shell_content_type; -} - -void -e_task_shell_content_register_type (GTypeModule *type_module) -{ - static const GTypeInfo type_info = { - sizeof (ETaskShellContentClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) task_shell_content_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (ETaskShellContent), - 0, /* n_preallocs */ - (GInstanceInitFunc) task_shell_content_init, - NULL /* value_table */ - }; - - task_shell_content_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_CONTENT, - "ETaskShellContent", &type_info, 0); -} - -GtkWidget * -e_task_shell_content_new (EShellView *shell_view) -{ - g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - - return g_object_new ( - E_TYPE_TASK_SHELL_CONTENT, - "shell-view", shell_view, NULL); -} - -ECalModel * -e_task_shell_content_get_task_model (ETaskShellContent *task_shell_content) -{ - g_return_val_if_fail ( - E_IS_TASK_SHELL_CONTENT (task_shell_content), NULL); - - return task_shell_content->priv->task_model; -} - -ECalComponentPreview * -e_task_shell_content_get_task_preview (ETaskShellContent *task_shell_content) -{ - g_return_val_if_fail ( - E_IS_TASK_SHELL_CONTENT (task_shell_content), NULL); - - return E_CAL_COMPONENT_PREVIEW ( - task_shell_content->priv->task_preview); -} - -ECalendarTable * -e_task_shell_content_get_task_table (ETaskShellContent *task_shell_content) -{ - g_return_val_if_fail ( - E_IS_TASK_SHELL_CONTENT (task_shell_content), NULL); - - return E_CALENDAR_TABLE (task_shell_content->priv->task_table); -} - -GalViewInstance * -e_task_shell_content_get_view_instance (ETaskShellContent *task_shell_content) -{ - g_return_val_if_fail ( - E_IS_TASK_SHELL_CONTENT (task_shell_content), NULL); - - return task_shell_content->priv->view_instance; -} - -gboolean -e_task_shell_content_get_preview_visible (ETaskShellContent *task_shell_content) -{ - GtkPaned *paned; - GtkWidget *child; - - g_return_val_if_fail ( - E_IS_TASK_SHELL_CONTENT (task_shell_content), FALSE); - - paned = GTK_PANED (task_shell_content->priv->paned); - child = gtk_paned_get_child2 (paned); - - return GTK_WIDGET_VISIBLE (child); -} - -void -e_task_shell_content_set_preview_visible (ETaskShellContent *task_shell_content, - gboolean preview_visible) -{ - GtkPaned *paned; - GtkWidget *child; - - g_return_if_fail (E_IS_TASK_SHELL_CONTENT (task_shell_content)); - - paned = GTK_PANED (task_shell_content->priv->paned); - child = gtk_paned_get_child2 (paned); - - if (preview_visible) - gtk_widget_show (child); - else - gtk_widget_hide (child); - - g_object_notify (G_OBJECT (task_shell_content), "preview-visible"); -} diff --git a/calendar/module/e-task-shell-content.h b/calendar/module/e-task-shell-content.h deleted file mode 100644 index 7e0b2128a7..0000000000 --- a/calendar/module/e-task-shell-content.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * e-task-shell-content.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_TASK_SHELL_CONTENT_H -#define E_TASK_SHELL_CONTENT_H - -#include -#include - -#include -#include -#include - -#include - -/* Standard GObject macros */ -#define E_TYPE_TASK_SHELL_CONTENT \ - (e_task_shell_content_get_type ()) -#define E_TASK_SHELL_CONTENT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_TASK_SHELL_CONTENT, ETaskShellContent)) -#define E_TASK_SHELL_CONTENT_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_TASK_SHELL_CONTENT, ETaskShellContentClass)) -#define E_IS_TASK_SHELL_CONTENT(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_TASK_SHELL_CONTENT)) -#define E_IS_TASK_SHELL_CONTENT_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_TASK_SHELL_CONTENT)) -#define E_TASK_SHELL_CONTENT_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_TASK_SHELL_CONTENT, ETaskShellContentClass)) - -G_BEGIN_DECLS - -typedef struct _ETaskShellContent ETaskShellContent; -typedef struct _ETaskShellContentClass ETaskShellContentClass; -typedef struct _ETaskShellContentPrivate ETaskShellContentPrivate; - -enum { - E_TASK_SHELL_CONTENT_SELECTION_SINGLE = 1 << 0, - E_TASK_SHELL_CONTENT_SELECTION_MULTIPLE = 1 << 1, - E_TASK_SHELL_CONTENT_SELECTION_CAN_ASSIGN = 1 << 2, - E_TASK_SHELL_CONTENT_SELECTION_CAN_EDIT = 1 << 3, - E_TASK_SHELL_CONTENT_SELECTION_HAS_COMPLETE = 1 << 4, - E_TASK_SHELL_CONTENT_SELECTION_HAS_INCOMPLETE = 1 << 5, - E_TASK_SHELL_CONTENT_SELECTION_HAS_URL = 1 << 6 -}; - -struct _ETaskShellContent { - EShellContent parent; - ETaskShellContentPrivate *priv; -}; - -struct _ETaskShellContentClass { - EShellContentClass parent_class; -}; - -GType e_task_shell_content_get_type (void); -void e_task_shell_content_register_type - (GTypeModule *type_module); -GtkWidget * e_task_shell_content_new(EShellView *shell_view); -ECalModel * e_task_shell_content_get_task_model - (ETaskShellContent *task_shell_content); -ECalComponentPreview * - e_task_shell_content_get_task_preview - (ETaskShellContent *task_shell_content); -ECalendarTable *e_task_shell_content_get_task_table - (ETaskShellContent *task_shell_content); -GalViewInstance * - e_task_shell_content_get_view_instance - (ETaskShellContent *task_shell_content); -gboolean e_task_shell_content_get_preview_visible - (ETaskShellContent *task_shell_content); -void e_task_shell_content_set_preview_visible - (ETaskShellContent *task_shell_content, - gboolean preview_visible); - -G_END_DECLS - -#endif /* E_TASK_SHELL_CONTENT_H */ diff --git a/calendar/module/e-task-shell-migrate.c b/calendar/module/e-task-shell-migrate.c deleted file mode 100644 index ced54bafdf..0000000000 --- a/calendar/module/e-task-shell-migrate.c +++ /dev/null @@ -1,664 +0,0 @@ -/* - * e-task-shell-backend-migrate.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-task-shell-migrate.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "e-util/e-bconf-map.h" -#include "e-util/e-folder-map.h" -#include "e-util/e-util-private.h" -#include "calendar/gui/calendar-config.h" -#include "calendar/gui/calendar-config-keys.h" - -#define WEBCAL_BASE_URI "webcal://" -#define PERSONAL_RELATIVE_URI "system" - -static e_gconf_map_t calendar_tasks_map[] = { - /* /Calendar/Tasks */ - { "HideCompletedTasks", "calendar/tasks/hide_completed", E_GCONF_MAP_BOOL }, - { "HideCompletedTasksUnits", "calendar/tasks/hide_completed_units", E_GCONF_MAP_STRING }, - { "HideCompletedTasksValue", "calendar/tasks/hide_completed_value", E_GCONF_MAP_INT }, - { NULL }, -}; - -static e_gconf_map_t calendar_tasks_colours_map[] = { - /* /Calendar/Tasks/Colors */ - { "TasksDueToday", "calendar/tasks/colors/due_today", E_GCONF_MAP_STRING }, - { "TasksOverDue", "calendar/tasks/colors/overdue", E_GCONF_MAP_STRING }, - { "TasksDueToday", "calendar/tasks/colors/due_today", E_GCONF_MAP_STRING }, - { NULL }, -}; - -static e_gconf_map_list_t task_remap_list[] = { - - { "/Calendar/Tasks", calendar_tasks_map }, - { "/Calendar/Tasks/Colors", calendar_tasks_colours_map }, - - { NULL }, -}; - -static GtkWidget *window; -static GtkLabel *label; -static GtkProgressBar *progress; - -#ifndef G_OS_WIN32 - -/* No previous versions have been available on Win32, so don't - * bother with upgrade support from 1.x on Win32. - */ - -static void -setup_progress_dialog (void) -{ - GtkWidget *vbox, *hbox, *w; - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title ((GtkWindow *) window, _("Migrating...")); - gtk_window_set_modal ((GtkWindow *) window, TRUE); - gtk_container_set_border_width ((GtkContainer *) window, 6); - - vbox = gtk_vbox_new (FALSE, 6); - gtk_widget_show (vbox); - gtk_container_add ((GtkContainer *) window, vbox); - - w = gtk_label_new (_("The location and hierarchy of the Evolution task " - "folders has changed since Evolution 1.x.\n\nPlease be " - "patient while Evolution migrates your folders...")); - - gtk_label_set_line_wrap ((GtkLabel *) w, TRUE); - gtk_widget_show (w); - gtk_box_pack_start_defaults ((GtkBox *) vbox, w); - - hbox = gtk_hbox_new (FALSE, 6); - gtk_widget_show (hbox); - gtk_box_pack_start_defaults ((GtkBox *) vbox, hbox); - - label = (GtkLabel *) gtk_label_new (""); - gtk_widget_show ((GtkWidget *) label); - gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) label); - - progress = (GtkProgressBar *) gtk_progress_bar_new (); - gtk_widget_show ((GtkWidget *) progress); - gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) progress); - - gtk_widget_show (window); -} - -static void -dialog_close (void) -{ - gtk_widget_destroy ((GtkWidget *) window); -} - -static void -dialog_set_folder_name (const gchar *folder_name) -{ - gchar *text; - - text = g_strdup_printf (_("Migrating '%s':"), folder_name); - gtk_label_set_text (label, text); - g_free (text); - - gtk_progress_bar_set_fraction (progress, 0.0); - - while (gtk_events_pending ()) - gtk_main_iteration (); -} - -static void -dialog_set_progress (double percent) -{ - gchar text[5]; - - snprintf (text, sizeof (text), "%d%%", (gint) (percent * 100.0f)); - - gtk_progress_bar_set_fraction (progress, percent); - gtk_progress_bar_set_text (progress, text); - - while (gtk_events_pending ()) - gtk_main_iteration (); -} - -static gboolean -check_for_conflict (ESourceGroup *group, gchar *name) -{ - GSList *sources; - GSList *s; - - sources = e_source_group_peek_sources (group); - - for (s = sources; s; s = s->next) { - ESource *source = E_SOURCE (s->data); - - if (!strcmp (e_source_peek_name (source), name)) - return TRUE; - } - - return FALSE; -} - -static gchar * -get_source_name (ESourceGroup *group, const gchar *path) -{ - gchar **p = g_strsplit (path, "/", 0); - gint i, j, starting_index; - gint num_elements; - gboolean conflict; - GString *s = g_string_new (NULL); - - for (i = 0; p[i]; i ++); - - num_elements = i; - i--; - - /* p[i] is now the last path element */ - - /* check if it conflicts */ - starting_index = i; - do { - for (j = starting_index; j < num_elements; j += 2) { - if (j != starting_index) - g_string_append_c (s, '_'); - g_string_append (s, p[j]); - } - - conflict = check_for_conflict (group, s->str); - - - /* if there was a conflict back up 2 levels (skipping the /subfolder/ element) */ - if (conflict) - starting_index -= 2; - - /* we always break out if we can't go any further, - regardless of whether or not we conflict. */ - if (starting_index < 0) - break; - - } while (conflict); - g_strfreev (p); - - return g_string_free (s, FALSE); -} - -static gboolean -migrate_ical (ECal *old_ecal, ECal *new_ecal) -{ - GList *l, *objects; - gint num_added = 0; - gint num_objects; - gboolean retval = TRUE; - - /* both ecals are loaded, start the actual migration */ - if (!e_cal_get_object_list (old_ecal, "#t", &objects, NULL)) - return FALSE; - - num_objects = g_list_length (objects); - for (l = objects; l; l = l->next) { - icalcomponent *ical_comp = l->data; - GError *error = NULL; - - if (!e_cal_create_object (new_ecal, ical_comp, NULL, &error)) { - g_warning ("Migration of object failed: %s", error->message); - retval = FALSE; - } - - g_clear_error (&error); - - num_added ++; - dialog_set_progress ((double)num_added / num_objects); - } - - g_list_foreach (objects, (GFunc) icalcomponent_free, NULL); - g_list_free (objects); - - return retval; -} - -static gboolean -migrate_ical_folder_to_source (gchar *old_path, ESource *new_source, ECalSourceType type) -{ - ECal *old_ecal = NULL, *new_ecal = NULL; - ESource *old_source; - ESourceGroup *group; - gchar *old_uri = g_strdup_printf ("file://%s", old_path); - GError *error = NULL; - gboolean retval = FALSE; - - group = e_source_group_new ("", old_uri); - old_source = e_source_new ("", ""); - e_source_group_add_source (group, old_source, -1); - - dialog_set_folder_name (e_source_peek_name (new_source)); - - if (!(old_ecal = e_cal_new (old_source, type))) { - g_warning ("could not find a backend for '%s'", e_source_get_uri (old_source)); - goto finish; - } - if (!e_cal_open (old_ecal, FALSE, &error)) { - g_warning ("failed to load source ecal for migration: '%s' (%s)", error->message, - e_source_get_uri (old_source)); - goto finish; - } - - if (!(new_ecal = e_cal_new (new_source, type))) { - g_warning ("could not find a backend for '%s'", e_source_get_uri (new_source)); - goto finish; - } - if (!e_cal_open (new_ecal, FALSE, &error)) { - g_warning ("failed to load destination ecal for migration: '%s' (%s)", error->message, - e_source_get_uri (new_source)); - goto finish; - } - - retval = migrate_ical (old_ecal, new_ecal); - -finish: - g_clear_error (&error); - if (old_ecal) - g_object_unref (old_ecal); - g_object_unref (group); - if (new_ecal) - g_object_unref (new_ecal); - g_free (old_uri); - - return retval; -} - -static gboolean -migrate_ical_folder (gchar *old_path, ESourceGroup *dest_group, gchar *source_name, ECalSourceType type) -{ - ESource *new_source; - gboolean retval; - - new_source = e_source_new (source_name, source_name); - e_source_set_relative_uri (new_source, e_source_peek_uid (new_source)); - e_source_group_add_source (dest_group, new_source, -1); - - retval = migrate_ical_folder_to_source (old_path, new_source, type); - - g_object_unref (new_source); - - return retval; -} - -#endif /* !G_OS_WIN32 */ - -#ifndef G_OS_WIN32 - -static void -migrate_pilot_db_key (const gchar *key, gpointer user_data) -{ - EXmlHash *xmlhash = user_data; - - e_xmlhash_add (xmlhash, key, ""); -} - -static void -migrate_pilot_data (const gchar *component, const gchar *conduit, const gchar *old_path, const gchar *new_path) -{ - gchar *changelog, *map; - const gchar *dent; - const gchar *ext; - gchar *filename; - GDir *dir; - - if (!(dir = g_dir_open (old_path, 0, NULL))) - return; - - map = g_alloca (12 + strlen (conduit)); - sprintf (map, "pilot-map-%s-", conduit); - - changelog = g_alloca (24 + strlen (conduit)); - sprintf (changelog, "pilot-sync-evolution-%s-", conduit); - - while ((dent = g_dir_read_name (dir))) { - if (!strncmp (dent, map, strlen (map)) && - ((ext = strrchr (dent, '.')) && !strcmp (ext, ".xml"))) { - /* pilot map file - src and dest file formats are identical */ - guchar inbuf[4096]; - gsize nread, nwritten; - gint fd0, fd1; - gssize n; - - filename = g_build_filename (old_path, dent, NULL); - if ((fd0 = g_open (filename, O_RDONLY|O_BINARY, 0)) == -1) { - g_free (filename); - continue; - } - - g_free (filename); - filename = g_build_filename (new_path, dent, NULL); - if ((fd1 = g_open (filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666)) == -1) { - g_free (filename); - close (fd0); - continue; - } - - do { - do { - n = read (fd0, inbuf, sizeof (inbuf)); - } while (n == -1 && errno == EINTR); - - if (n < 1) - break; - - nread = n; - nwritten = 0; - do { - do { - n = write (fd1, inbuf + nwritten, nread - nwritten); - } while (n == -1 && errno == EINTR); - - if (n > 0) - nwritten += n; - } while (nwritten < nread && n != -1); - - if (n == -1) - break; - } while (1); - - if (n != -1) - n = fsync (fd1); - - if (n == -1) { - g_warning ("Failed to migrate %s: %s", dent, strerror (errno)); - g_unlink (filename); - } - - close (fd0); - close (fd1); - g_free (filename); - } else if (!strncmp (dent, changelog, strlen (changelog)) && - ((ext = strrchr (dent, '.')) && !strcmp (ext, ".db"))) { - /* src and dest formats differ, src format is db3 while dest format is xml */ - EXmlHash *xmlhash; - EDbHash *dbhash; - struct stat st; - - filename = g_build_filename (old_path, dent, NULL); - if (g_stat (filename, &st) == -1) { - g_free (filename); - continue; - } - - dbhash = e_dbhash_new (filename); - g_free (filename); - - filename = g_strdup_printf ("%s/%s.ics-%s", new_path, component, dent); - if (g_stat (filename, &st) != -1) - g_unlink (filename); - xmlhash = e_xmlhash_new (filename); - g_free (filename); - - e_dbhash_foreach_key (dbhash, migrate_pilot_db_key, xmlhash); - - e_dbhash_destroy (dbhash); - - e_xmlhash_write (xmlhash); - e_xmlhash_destroy (xmlhash); - } - } - - g_dir_close (dir); -} - -#endif - -static void -create_task_sources (EShellBackend *shell_backend, - ESourceList *source_list, - ESourceGroup **on_this_computer, - ESourceGroup **on_the_web, - ESource **personal_source) -{ - GSList *groups; - ESourceGroup *group; - gchar *base_uri, *base_uri_proto; - const gchar *base_dir; - - *on_this_computer = NULL; - *on_the_web = NULL; - *personal_source = NULL; - - base_dir = e_shell_backend_get_config_dir (shell_backend); - base_uri = g_build_filename (base_dir, "local", NULL); - - base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL); - - groups = e_source_list_peek_groups (source_list); - if (groups) { - /* groups are already there, we need to search for things... */ - GSList *g; - - for (g = groups; g; g = g->next) { - - group = E_SOURCE_GROUP (g->data); - - if (!*on_this_computer && !strcmp (base_uri_proto, e_source_group_peek_base_uri (group))) - *on_this_computer = g_object_ref (group); - else if (!*on_the_web && !strcmp (WEBCAL_BASE_URI, e_source_group_peek_base_uri (group))) - *on_the_web = g_object_ref (group); - } - } - - if (*on_this_computer) { - /* make sure "Personal" shows up as a source under - this group */ - GSList *sources = e_source_group_peek_sources (*on_this_computer); - GSList *s; - for (s = sources; s; s = s->next) { - ESource *source = E_SOURCE (s->data); - const gchar *relative_uri; - - relative_uri = e_source_peek_relative_uri (source); - if (relative_uri == NULL) - continue; - if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) { - *personal_source = g_object_ref (source); - break; - } - } - } else { - /* create the local source group */ - group = e_source_group_new (_("On This Computer"), base_uri_proto); - e_source_list_add_group (source_list, group, -1); - - *on_this_computer = group; - } - - if (!*personal_source) { - /* Create the default Person task list */ - ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); - e_source_group_add_source (*on_this_computer, source, -1); - - if (!calendar_config_get_primary_tasks () && !calendar_config_get_tasks_selected ()) { - GSList selected; - - calendar_config_set_primary_tasks (e_source_peek_uid (source)); - - selected.data = (gpointer)e_source_peek_uid (source); - selected.next = NULL; - calendar_config_set_tasks_selected (&selected); - } - - e_source_set_color_spec (source, "#BECEDD"); - *personal_source = source; - } - - if (!*on_the_web) { - /* Create the Webcal source group */ - group = e_source_group_new (_("On The Web"), WEBCAL_BASE_URI); - e_source_list_add_group (source_list, group, -1); - - *on_the_web = group; - } - - g_free (base_uri_proto); - g_free (base_uri); -} - -gboolean -e_task_shell_backend_migrate (EShellBackend *shell_backend, - gint major, - gint minor, - gint micro, - GError **error) -{ - ESourceGroup *on_this_computer = NULL; - ESourceGroup *on_the_web = NULL; - ESource *personal_source = NULL; - ESourceList *source_list; - gboolean retval = FALSE; - - source_list = g_object_get_data ( - G_OBJECT (source_list), "source-list"); - - /* we call this unconditionally now - create_groups either - creates the groups/sources or it finds the necessary - groups/sources. */ - create_task_sources ( - shell_backend, source_list, &on_this_computer, - &on_the_web, &personal_source); - -#ifndef G_OS_WIN32 - if (major == 1) { - xmlDocPtr config_doc = NULL; - gchar *conf_file; - - conf_file = g_build_filename (g_get_home_dir (), "evolution", "config.xmldb", NULL); - if (g_file_test (conf_file, G_FILE_TEST_IS_REGULAR)) - config_doc = e_xml_parse_file (conf_file); - g_free (conf_file); - - if (config_doc && minor <= 2) { - GConfClient *gconf; - gint res = 0; - - /* move bonobo config to gconf */ - gconf = gconf_client_get_default (); - - res = e_bconf_import (gconf, config_doc, task_remap_list); - - g_object_unref (gconf); - - xmlFreeDoc(config_doc); - - if (res != 0) { - g_set_error(error, 0, 0, _("Unable to migrate old settings from evolution/config.xmldb")); - goto fail; - } - } - - if (minor <= 4) { - GSList *migration_dirs, *l; - gchar *path, *local_task_folder; - - setup_progress_dialog (); - - path = g_build_filename (g_get_home_dir (), "evolution", "local", NULL); - migration_dirs = e_folder_map_local_folders (path, "tasks"); - local_task_folder = g_build_filename (path, "Tasks", NULL); - g_free (path); - - if (personal_source) - migrate_ical_folder_to_source (local_task_folder, personal_source, E_CAL_SOURCE_TYPE_TODO); - - for (l = migration_dirs; l; l = l->next) { - gchar *source_name; - - if (personal_source && !strcmp ((gchar *)l->data, local_task_folder)) - continue; - - source_name = get_source_name (on_this_computer, (gchar *)l->data); - - if (!migrate_ical_folder (l->data, on_this_computer, source_name, E_CAL_SOURCE_TYPE_TODO)) { - /* FIXME: domain/code */ - g_set_error(error, 0, 0, _("Unable to migrate tasks `%s'"), source_name); - g_free(source_name); - goto fail; - } - - g_free (source_name); - } - - g_free (local_task_folder); - - dialog_close (); - } - - if (minor < 5 || (minor == 5 && micro <= 10)) { - gchar *old_path, *new_path; - - old_path = g_build_filename (g_get_home_dir (), "evolution", "local", "Tasks", NULL); - new_path = g_build_filename (e_shell_backend_get_config_dir (shell_backend), - "local", "system", NULL); - migrate_pilot_data ("tasks", "todo", old_path, new_path); - g_free (new_path); - g_free (old_path); - } - - /* we only need to do this next step if people ran - older versions of 1.5. We need to clear out the - absolute URI's that were assigned to ESources - during one phase of development, as they take - precedent over relative uris (but aren't updated - when editing an ESource). */ - if (minor == 5 && micro <= 11) { - GSList *g; - for (g = e_source_list_peek_groups (source_list); g; g = g->next) { - ESourceGroup *group = g->data; - GSList *s; - - for (s = e_source_group_peek_sources (group); s; s = s->next) { - ESource *source = s->data; - e_source_set_absolute_uri (source, NULL); - } - } - } - } -#endif /* !G_OS_WIN32 */ - e_source_list_sync (source_list, NULL); - retval = TRUE; -fail: - if (on_this_computer) - g_object_unref (on_this_computer); - if (on_the_web) - g_object_unref (on_the_web); - if (personal_source) - g_object_unref (personal_source); - - return retval; -} diff --git a/calendar/module/e-task-shell-migrate.h b/calendar/module/e-task-shell-migrate.h deleted file mode 100644 index 4cb91c9f4a..0000000000 --- a/calendar/module/e-task-shell-migrate.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * e-task-shell-backend-migrate.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_TASK_SHELL_BACKEND_MIGRATE_H -#define E_TASK_SHELL_BACKEND_MIGRATE_H - -#include -#include - -G_BEGIN_DECLS - -gboolean e_task_shell_backend_migrate (EShellBackend *shell_backend, - gint major, - gint minor, - gint micro, - GError **error); - -G_END_DECLS - -#endif /* E_TASK_SHELL_BACKEND_MIGRATE_H */ diff --git a/calendar/module/e-task-shell-sidebar.c b/calendar/module/e-task-shell-sidebar.c deleted file mode 100644 index 827a0a037e..0000000000 --- a/calendar/module/e-task-shell-sidebar.c +++ /dev/null @@ -1,696 +0,0 @@ -/* - * e-task-shell-sidebar.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-task-shell-sidebar.h" - -#include -#include -#include - -#include "e-util/e-error.h" -#include "e-util/e-util.h" -#include "calendar/common/authentication.h" -#include "calendar/gui/calendar-config.h" -#include "calendar/gui/e-task-list-selector.h" -#include "calendar/gui/misc.h" - -#include "e-task-shell-backend.h" -#include "e-task-shell-view.h" - -#define E_TASK_SHELL_SIDEBAR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_TASK_SHELL_SIDEBAR, ETaskShellSidebarPrivate)) - -struct _ETaskShellSidebarPrivate { - GtkWidget *selector; - - /* UID -> Client */ - GHashTable *client_table; -}; - -enum { - PROP_0, - PROP_SELECTOR -}; - -enum { - CLIENT_ADDED, - CLIENT_REMOVED, - STATUS_MESSAGE, - LAST_SIGNAL -}; - -static gpointer parent_class; -static guint signals[LAST_SIGNAL]; -static GType task_shell_sidebar_type; - -static void -task_shell_sidebar_emit_client_added (ETaskShellSidebar *task_shell_sidebar, - ECal *client) -{ - guint signal_id = signals[CLIENT_ADDED]; - - g_signal_emit (task_shell_sidebar, signal_id, 0, client); -} - -static void -task_shell_sidebar_emit_client_removed (ETaskShellSidebar *task_shell_sidebar, - ECal *client) -{ - guint signal_id = signals[CLIENT_REMOVED]; - - g_signal_emit (task_shell_sidebar, signal_id, 0, client); -} - -static void -task_shell_sidebar_emit_status_message (ETaskShellSidebar *task_shell_sidebar, - const gchar *status_message) -{ - guint signal_id = signals[STATUS_MESSAGE]; - - g_signal_emit (task_shell_sidebar, signal_id, 0, status_message, -1.0); -} - -static void -task_shell_sidebar_backend_died_cb (ETaskShellSidebar *task_shell_sidebar, - ECal *client) -{ - EShellView *shell_view; - EShellWindow *shell_window; - EShellSidebar *shell_sidebar; - GHashTable *client_table; - ESource *source; - const gchar *uid; - - client_table = task_shell_sidebar->priv->client_table; - - shell_sidebar = E_SHELL_SIDEBAR (task_shell_sidebar); - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - shell_window = e_shell_view_get_shell_window (shell_view); - - source = e_cal_get_source (client); - uid = e_source_peek_uid (source); - - g_object_ref (source); - - g_hash_table_remove (client_table, uid); - task_shell_sidebar_emit_status_message (task_shell_sidebar, NULL); - - e_error_run ( - GTK_WINDOW (shell_window), - "calendar:tasks-crashed", NULL); - - g_object_unref (source); -} - -static void -task_shell_sidebar_backend_error_cb (ETaskShellSidebar *task_shell_sidebar, - const gchar *message, - ECal *client) -{ - EShellView *shell_view; - EShellWindow *shell_window; - EShellSidebar *shell_sidebar; - GtkWidget *dialog; - const gchar *uri; - gchar *uri_no_passwd; - - shell_sidebar = E_SHELL_SIDEBAR (task_shell_sidebar); - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - shell_window = e_shell_view_get_shell_window (shell_view); - - uri = e_cal_get_uri (client); - uri_no_passwd = get_uri_without_password (uri); - - dialog = gtk_message_dialog_new ( - GTK_WINDOW (shell_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, - _("Error on %s\n%s"), - uri_no_passwd, message); - - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - - g_free (uri_no_passwd); -} - -static void -task_shell_sidebar_client_opened_cb (ETaskShellSidebar *task_shell_sidebar, - ECalendarStatus status, - ECal *client) -{ - EShellView *shell_view; - EShellWindow *shell_window; - EShellSidebar *shell_sidebar; - ESource *source; - - source = e_cal_get_source (client); - - shell_sidebar = E_SHELL_SIDEBAR (task_shell_sidebar); - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - shell_window = e_shell_view_get_shell_window (shell_view); - - if (status == E_CALENDAR_STATUS_AUTHENTICATION_FAILED || - status == E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED) - auth_cal_forget_password (client); - - switch (status) { - case E_CALENDAR_STATUS_OK: - g_signal_handlers_disconnect_matched ( - client, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, - task_shell_sidebar_client_opened_cb, NULL); - - task_shell_sidebar_emit_status_message ( - task_shell_sidebar, _("Loading tasks")); - task_shell_sidebar_emit_client_added ( - task_shell_sidebar, client); - task_shell_sidebar_emit_status_message ( - task_shell_sidebar, NULL); - break; - - case E_CALENDAR_STATUS_AUTHENTICATION_FAILED: - e_cal_open_async (client, FALSE); - break; - - case E_CALENDAR_STATUS_BUSY: - break; - - case E_CALENDAR_STATUS_REPOSITORY_OFFLINE: - e_error_run ( - GTK_WINDOW (shell_window), - "calendar:prompt-no-contents-offline-tasks", - NULL); - break; - - default: - task_shell_sidebar_emit_client_removed ( - task_shell_sidebar, client); - break; - } -} - -static void -task_shell_sidebar_row_changed_cb (ETaskShellSidebar *task_shell_sidebar, - GtkTreePath *tree_path, - GtkTreeIter *tree_iter, - GtkTreeModel *tree_model) -{ - ESourceSelector *selector; - ESource *source; - - /* XXX ESourceSelector's underlying tree store has only one - * column: ESource objects. While we're not supposed to - * know this, listening for "row-changed" signals from - * the model is easier to deal with than the selector's - * "selection-changed" signal, which doesn't tell you - * _which_ row changed. */ - - selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); - gtk_tree_model_get (tree_model, tree_iter, 0, &source, -1); - - /* XXX This signal gets emitted a lot while the model is being - * rebuilt, during which time we won't get a valid ESource. - * ESourceSelector should probably block this signal while - * rebuilding the model, but we'll be forgiving and not - * emit a warning. */ - if (!E_IS_SOURCE (source)) - return; - - if (e_source_selector_source_is_selected (selector, source)) - e_task_shell_sidebar_add_source (task_shell_sidebar, source); - else - e_task_shell_sidebar_remove_source (task_shell_sidebar, source); -} - -static void -task_shell_sidebar_selection_changed_cb (ETaskShellSidebar *task_shell_sidebar, - ESourceSelector *selector) -{ - GSList *list, *iter; - - /* This signal is emitted less frequently than "row-changed", - * especially when the model is being rebuilt. So we'll take - * it easy on poor GConf. */ - - list = e_source_selector_get_selection (selector); - - for (iter = list; iter != NULL; iter = iter->next) { - ESource *source = iter->data; - - iter->data = (gpointer) e_source_peek_uid (source); - g_object_unref (source); - } - - calendar_config_set_tasks_selected (list); - - g_slist_free (list); -} - -static void -task_shell_sidebar_primary_selection_changed_cb (ETaskShellSidebar *task_shell_sidebar, - ESourceSelector *selector) -{ - ESource *source; - const gchar *uid; - - /* XXX ESourceSelector needs a "primary-selection-uid" property - * so we can just bind the property with GConfBridge. */ - - source = e_source_selector_peek_primary_selection (selector); - if (source == NULL) - return; - - uid = e_source_peek_uid (source); - calendar_config_set_primary_tasks (uid); -} - -static void -task_shell_sidebar_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_SELECTOR: - g_value_set_object ( - value, e_task_shell_sidebar_get_selector ( - E_TASK_SHELL_SIDEBAR (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -task_shell_sidebar_dispose (GObject *object) -{ - ETaskShellSidebarPrivate *priv; - - priv = E_TASK_SHELL_SIDEBAR_GET_PRIVATE (object); - - if (priv->selector != NULL) { - g_object_unref (priv->selector); - priv->selector = NULL; - } - - g_hash_table_remove_all (priv->client_table); - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -task_shell_sidebar_finalize (GObject *object) -{ - ETaskShellSidebarPrivate *priv; - - priv = E_TASK_SHELL_SIDEBAR_GET_PRIVATE (object); - - g_hash_table_destroy (priv->client_table); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -task_shell_sidebar_constructed (GObject *object) -{ - ETaskShellSidebarPrivate *priv; - EShellView *shell_view; - EShellBackend *shell_backend; - EShellSidebar *shell_sidebar; - ESourceSelector *selector; - ESourceList *source_list; - ESource *source; - GtkContainer *container; - GtkTreeModel *model; - GtkWidget *widget; - AtkObject *a11y; - GSList *list, *iter; - gchar *uid; - - priv = E_TASK_SHELL_SIDEBAR_GET_PRIVATE (object); - - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (parent_class)->constructed (object); - - shell_sidebar = E_SHELL_SIDEBAR (object); - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - shell_backend = e_shell_view_get_shell_backend (shell_view); - - source_list = e_task_shell_backend_get_source_list ( - E_TASK_SHELL_BACKEND (shell_backend)); - - container = GTK_CONTAINER (shell_sidebar); - - widget = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy ( - GTK_SCROLLED_WINDOW (widget), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type ( - GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); - gtk_container_add (container, widget); - gtk_widget_show (widget); - - container = GTK_CONTAINER (widget); - - widget = e_task_list_selector_new (source_list); - e_source_selector_set_select_new (E_SOURCE_SELECTOR (widget), TRUE); - gtk_container_add (container, widget); - a11y = gtk_widget_get_accessible (widget); - atk_object_set_name (a11y, _("Task List Selector")); - priv->selector = g_object_ref (widget); - gtk_widget_show (widget); - - /* Restore the selector state from the last session. */ - - selector = E_SOURCE_SELECTOR (priv->selector); - model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); - - g_signal_connect_swapped ( - model, "row-changed", - G_CALLBACK (task_shell_sidebar_row_changed_cb), - object); - - source = NULL; - uid = calendar_config_get_primary_tasks (); - if (uid != NULL) - source = e_source_list_peek_source_by_uid (source_list, uid); - if (source == NULL) - source = e_source_list_peek_source_any (source_list); - if (source != NULL) - e_source_selector_set_primary_selection (selector, source); - g_free (uid); - - list = calendar_config_get_tasks_selected (); - for (iter = list; iter != NULL; iter = iter->next) { - uid = iter->data; - source = e_source_list_peek_source_by_uid (source_list, uid); - g_free (uid); - - if (source == NULL) - continue; - - e_source_selector_select_source (selector, source); - } - g_slist_free (list); - - /* Listen for subsequent changes to the selector. */ - - g_signal_connect_swapped ( - widget, "selection-changed", - G_CALLBACK (task_shell_sidebar_selection_changed_cb), - object); - - g_signal_connect_swapped ( - widget, "primary-selection-changed", - G_CALLBACK (task_shell_sidebar_primary_selection_changed_cb), - object); -} - -static guint32 -task_shell_sidebar_check_state (EShellSidebar *shell_sidebar) -{ - ETaskShellSidebar *task_shell_sidebar; - ESourceSelector *selector; - ESource *source; - gboolean is_system = FALSE; - guint32 state = 0; - - task_shell_sidebar = E_TASK_SHELL_SIDEBAR (shell_sidebar); - selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); - source = e_source_selector_peek_primary_selection (selector); - - if (source != NULL) { - const gchar *uri; - - uri = e_source_peek_relative_uri (source); - is_system = (uri == NULL || strcmp (uri, "system") == 0); - } - - if (source != NULL) - state |= E_TASK_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE; - if (is_system) - state |= E_TASK_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM; - - return state; -} - -static void -task_shell_sidebar_client_removed (ETaskShellSidebar *task_shell_sidebar, - ECal *client) -{ - ESourceSelector *selector; - GHashTable *client_table; - ESource *source; - const gchar *uid; - - client_table = task_shell_sidebar->priv->client_table; - selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); - - g_signal_handlers_disconnect_matched ( - client, G_SIGNAL_MATCH_DATA, 0, 0, - NULL, NULL, task_shell_sidebar); - - source = e_cal_get_source (client); - e_source_selector_unselect_source (selector, source); - - uid = e_source_peek_uid (source); - g_hash_table_remove (client_table, uid); - - task_shell_sidebar_emit_status_message (task_shell_sidebar, NULL); -} - -static void -task_shell_sidebar_class_init (ETaskShellSidebarClass *class) -{ - GObjectClass *object_class; - EShellSidebarClass *shell_sidebar_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (ETaskShellSidebarPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->get_property = task_shell_sidebar_get_property; - object_class->dispose = task_shell_sidebar_dispose; - object_class->finalize = task_shell_sidebar_finalize; - object_class->constructed = task_shell_sidebar_constructed; - - shell_sidebar_class = E_SHELL_SIDEBAR_CLASS (class); - shell_sidebar_class->check_state = task_shell_sidebar_check_state; - - class->client_removed = task_shell_sidebar_client_removed; - - g_object_class_install_property ( - object_class, - PROP_SELECTOR, - g_param_spec_object ( - "selector", - _("Source Selector Widget"), - _("This widget displays groups of task lists"), - E_TYPE_SOURCE_SELECTOR, - G_PARAM_READABLE)); - - signals[CLIENT_ADDED] = g_signal_new ( - "client-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ETaskShellSidebarClass, client_added), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - E_TYPE_CAL); - - signals[CLIENT_REMOVED] = g_signal_new ( - "client-removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ETaskShellSidebarClass, client_removed), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - E_TYPE_CAL); - - signals[STATUS_MESSAGE] = g_signal_new ( - "status-message", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (ETaskShellSidebarClass, status_message), - NULL, NULL, - e_marshal_VOID__STRING_DOUBLE, - G_TYPE_NONE, 2, - G_TYPE_STRING, - G_TYPE_DOUBLE); -} - -static void -task_shell_sidebar_init (ETaskShellSidebar *task_shell_sidebar) -{ - GHashTable *client_table; - - client_table = g_hash_table_new_full ( - g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_object_unref); - - task_shell_sidebar->priv = - E_TASK_SHELL_SIDEBAR_GET_PRIVATE (task_shell_sidebar); - - task_shell_sidebar->priv->client_table = client_table; - - /* Postpone widget construction until we have a shell view. */ -} - -GType -e_task_shell_sidebar_get_type (void) -{ - return task_shell_sidebar_type; -} - -void -e_task_shell_sidebar_register_type (GTypeModule *type_module) -{ - static const GTypeInfo type_info = { - sizeof (ETaskShellSidebarClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) task_shell_sidebar_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (ETaskShellSidebar), - 0, /* n_preallocs */ - (GInstanceInitFunc) task_shell_sidebar_init, - NULL /* value_table */ - }; - - task_shell_sidebar_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_SIDEBAR, - "ETaskShellSidebar", &type_info, 0); -} - -GtkWidget * -e_task_shell_sidebar_new (EShellView *shell_view) -{ - g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - - return g_object_new ( - E_TYPE_TASK_SHELL_SIDEBAR, - "shell-view", shell_view, NULL); -} - -GList * -e_task_shell_sidebar_get_clients (ETaskShellSidebar *task_shell_sidebar) -{ - GHashTable *client_table; - - g_return_val_if_fail ( - E_IS_TASK_SHELL_SIDEBAR (task_shell_sidebar), NULL); - - client_table = task_shell_sidebar->priv->client_table; - - return g_hash_table_get_values (client_table); -} - -ESourceSelector * -e_task_shell_sidebar_get_selector (ETaskShellSidebar *task_shell_sidebar) -{ - g_return_val_if_fail ( - E_IS_TASK_SHELL_SIDEBAR (task_shell_sidebar), NULL); - - return E_SOURCE_SELECTOR (task_shell_sidebar->priv->selector); -} - -void -e_task_shell_sidebar_add_source (ETaskShellSidebar *task_shell_sidebar, - ESource *source) -{ - ESourceSelector *selector; - GHashTable *client_table; - ECal *client; - const gchar *uid; - const gchar *uri; - gchar *message; - - g_return_if_fail (E_IS_TASK_SHELL_SIDEBAR (task_shell_sidebar)); - g_return_if_fail (E_IS_SOURCE (source)); - - client_table = task_shell_sidebar->priv->client_table; - selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); - - uid = e_source_peek_uid (source); - client = g_hash_table_lookup (client_table, uid); - - if (client != NULL) - return; - - client = auth_new_cal_from_source (source, E_CAL_SOURCE_TYPE_TODO); - g_return_if_fail (client != NULL); - - g_signal_connect_swapped ( - client, "backend-died", - G_CALLBACK (task_shell_sidebar_backend_died_cb), - task_shell_sidebar); - - g_signal_connect_swapped ( - client, "backend-error", - G_CALLBACK (task_shell_sidebar_backend_error_cb), - task_shell_sidebar); - - g_hash_table_insert (client_table, g_strdup (uid), client); - e_source_selector_select_source (selector, source); - - uri = e_cal_get_uri (client); - message = g_strdup_printf (_("Opening tasks at %s"), uri); - task_shell_sidebar_emit_status_message (task_shell_sidebar, message); - g_free (message); - - g_signal_connect_swapped ( - client, "cal-opened", - G_CALLBACK (task_shell_sidebar_client_opened_cb), - task_shell_sidebar); - - e_cal_open_async (client, FALSE); -} - -void -e_task_shell_sidebar_remove_source (ETaskShellSidebar *task_shell_sidebar, - ESource *source) -{ - ESourceSelector *selector; - GHashTable *client_table; - ECal *client; - const gchar *uid; - - g_return_if_fail (E_IS_TASK_SHELL_SIDEBAR (task_shell_sidebar)); - g_return_if_fail (E_IS_SOURCE (source)); - - client_table = task_shell_sidebar->priv->client_table; - selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); - - uid = e_source_peek_uid (source); - client = g_hash_table_lookup (client_table, uid); - - if (client == NULL) - return; - - task_shell_sidebar_emit_client_removed (task_shell_sidebar, client); -} diff --git a/calendar/module/e-task-shell-sidebar.h b/calendar/module/e-task-shell-sidebar.h deleted file mode 100644 index 5d4c74fe11..0000000000 --- a/calendar/module/e-task-shell-sidebar.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * e-task-shell-sidebar.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_TASK_SHELL_SIDEBAR_H -#define E_TASK_SHELL_SIDEBAR_H - -#include -#include - -#include -#include - -/* Standard GObject macros */ -#define E_TYPE_TASK_SHELL_SIDEBAR \ - (e_task_shell_sidebar_get_type ()) -#define E_TASK_SHELL_SIDEBAR(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_TASK_SHELL_SIDEBAR, ETaskShellSidebar)) -#define E_TASK_SHELL_SIDEBAR_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_TASK_SHELL_SIDEBAR, ETaskShellSidebarClass)) -#define E_IS_TASK_SHELL_SIDEBAR(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_TASK_SHELL_SIDEBAR)) -#define E_IS_TASK_SHELL_SIDEBAR_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_TASK_SHELL_SIDEBAR)) -#define E_TASK_SHELL_SIDEBAR_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_TASK_SHELL_SIDEBAR, ETaskShellSidebarClass)) - -G_BEGIN_DECLS - -typedef struct _ETaskShellSidebar ETaskShellSidebar; -typedef struct _ETaskShellSidebarClass ETaskShellSidebarClass; -typedef struct _ETaskShellSidebarPrivate ETaskShellSidebarPrivate; - -enum { - E_TASK_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE = 1 << 0, - E_TASK_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM = 1 << 1 -}; - -struct _ETaskShellSidebar { - EShellSidebar parent; - ETaskShellSidebarPrivate *priv; -}; - -struct _ETaskShellSidebarClass { - EShellSidebarClass parent_class; - - /* Signals */ - void (*client_added) (ETaskShellSidebar *task_shell_sidebar, - ECal *client); - void (*client_removed) (ETaskShellSidebar *task_shell_sidebar, - ECal *client); - void (*status_message) (ETaskShellSidebar *task_shell_sidebar, - const gchar *status_message, - gdouble percent); -}; - -GType e_task_shell_sidebar_get_type (void); -void e_task_shell_sidebar_register_type - (GTypeModule *type_module); -GtkWidget * e_task_shell_sidebar_new(EShellView *shell_view); -GList * e_task_shell_sidebar_get_clients - (ETaskShellSidebar *task_shell_sidebar); -ESourceSelector * - e_task_shell_sidebar_get_selector - (ETaskShellSidebar *task_shell_sidebar); -void e_task_shell_sidebar_add_source - (ETaskShellSidebar *task_shell_sidebar, - ESource *source); -void e_task_shell_sidebar_remove_source - (ETaskShellSidebar *task_shell_sidebar, - ESource *source); - -G_END_DECLS - -#endif /* E_TASK_SHELL_SIDEBAR_H */ diff --git a/calendar/module/e-task-shell-view-actions.c b/calendar/module/e-task-shell-view-actions.c deleted file mode 100644 index 4deed9fdf0..0000000000 --- a/calendar/module/e-task-shell-view-actions.c +++ /dev/null @@ -1,1154 +0,0 @@ -/* - * e-task-shell-view-actions.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-task-shell-view-private.h" - -static void -action_gal_save_custom_view_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - EShellView *shell_view; - GalViewInstance *view_instance; - - /* All shell views respond to the activation of this action, - * which is defined by EShellWindow. But only the currently - * active shell view proceeds with saving the custom view. */ - shell_view = E_SHELL_VIEW (task_shell_view); - if (!e_shell_view_is_active (shell_view)) - return; - - task_shell_content = task_shell_view->priv->task_shell_content; - view_instance = e_task_shell_content_get_view_instance (task_shell_content); - gal_view_instance_save_as (view_instance); -} - -static void -action_search_execute_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - EShellView *shell_view; - - /* All shell views respond to the activation of this action, - * which is defined by EShellWindow. But only the currently - * active shell view proceeds with executing the search. */ - shell_view = E_SHELL_VIEW (task_shell_view); - if (!e_shell_view_is_active (shell_view)) - return; - - e_task_shell_view_execute_search (task_shell_view); -} - -static void -action_search_filter_cb (GtkRadioAction *action, - GtkRadioAction *current, - ETaskShellView *task_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - - shell_view = E_SHELL_VIEW (task_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - gtk_action_activate (ACTION (SEARCH_EXECUTE)); -} - -static void -action_task_assign_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - ECalModelComponent *comp_data; - GSList *list; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - - list = e_calendar_table_get_selected (task_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - /* XXX We only open the first selected task. */ - e_task_shell_view_open_task (task_shell_view, comp_data); - - /* FIXME Need to actually assign the task. */ -} - -static void -action_task_clipboard_copy_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - - e_calendar_table_copy_clipboard (task_table); -} - -static void -action_task_clipboard_cut_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - - e_calendar_table_cut_clipboard (task_table); -} - -static void -action_task_clipboard_paste_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - - e_calendar_table_paste_clipboard (task_table); -} - -static void -action_task_delete_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - ECalComponentPreview *task_preview; - ECalendarTable *task_table; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - task_preview = e_task_shell_content_get_task_preview (task_shell_content); - - e_task_shell_view_set_status_message ( - task_shell_view, _("Deleting selected tasks..."), -1.0); - e_calendar_table_delete_selected (task_table); - e_task_shell_view_set_status_message (task_shell_view, NULL, -1.0); - - e_cal_component_preview_clear (task_preview); -} - -static void -action_task_forward_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - ECalModelComponent *comp_data; - ECalComponent *comp; - icalcomponent *clone; - GSList *list; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - - list = e_calendar_table_get_selected (task_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - /* XXX We only forward the first selected task. */ - comp = e_cal_component_new (); - clone = icalcomponent_new_clone (comp_data->icalcomp); - e_cal_component_set_icalcomponent (comp, clone); - itip_send_comp ( - E_CAL_COMPONENT_METHOD_PUBLISH, comp, - comp_data->client, NULL, NULL, NULL, TRUE); - g_object_unref (comp); -} - -static void -action_task_list_copy_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellSidebar *task_shell_sidebar; - EShellWindow *shell_window; - EShellView *shell_view; - ESourceSelector *selector; - ESource *source; - - shell_view = E_SHELL_VIEW (task_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; - selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); - source = e_source_selector_peek_primary_selection (selector); - g_return_if_fail (E_IS_SOURCE (source)); - - copy_source_dialog ( - GTK_WINDOW (shell_window), - source, E_CAL_SOURCE_TYPE_TODO); -} - -static void -action_task_list_delete_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellBackend *task_shell_backend; - ETaskShellContent *task_shell_content; - ETaskShellSidebar *task_shell_sidebar; - EShellWindow *shell_window; - EShellView *shell_view; - ECalendarTable *task_table; - ECal *client; - ECalModel *model; - ESourceSelector *selector; - ESourceGroup *source_group; - ESourceList *source_list; - ESource *source; - gint response; - gchar *uri; - GError *error = NULL; - - shell_view = E_SHELL_VIEW (task_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - task_shell_backend = task_shell_view->priv->task_shell_backend; - source_list = e_task_shell_backend_get_source_list (task_shell_backend); - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - model = e_calendar_table_get_model (task_table); - - task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; - selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); - source = e_source_selector_peek_primary_selection (selector); - g_return_if_fail (E_IS_SOURCE (source)); - - /* Ask for confirmation. */ - response = e_error_run ( - GTK_WINDOW (shell_window), - "calendar:prompt-delete-task-list", - e_source_peek_name (source)); - if (response != GTK_RESPONSE_YES) - return; - - uri = e_source_get_uri (source); - client = e_cal_model_get_client_for_uri (model, uri); - if (client == NULL) - client = e_cal_new_from_uri (uri, E_CAL_SOURCE_TYPE_JOURNAL); - g_free (uri); - - g_return_if_fail (client != NULL); - - if (!e_cal_remove (client, &error)) { - g_warning ("%s", error->message); - g_error_free (error); - return; - } - - if (e_source_selector_source_is_selected (selector, source)) { - e_task_shell_sidebar_remove_source ( - task_shell_sidebar, source); - e_source_selector_unselect_source (selector, source); - } - - source_group = e_source_peek_group (source); - e_source_group_remove_source (source_group, source); - - if (!e_source_list_sync (source_list, &error)) { - g_warning ("%s", error->message); - g_error_free (error); - } -} - -static void -action_task_list_new_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - - shell_view = E_SHELL_VIEW (task_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - calendar_setup_new_task_list (GTK_WINDOW (shell_window)); -} - -static void -action_task_list_print_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - ETable *table; - GtkPrintOperationAction print_action; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - table = e_calendar_table_get_table (task_table); - - print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; - print_table (table, _("Print Tasks"), _("Tasks"), print_action); -} - -static void -action_task_list_print_preview_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - ETable *table; - GtkPrintOperationAction print_action; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - table = e_calendar_table_get_table (task_table); - - print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW; - print_table (table, _("Print Tasks"), _("Tasks"), print_action); -} - -static void -action_task_list_properties_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellSidebar *task_shell_sidebar; - EShellView *shell_view; - EShellWindow *shell_window; - ESource *source; - ESourceSelector *selector; - - shell_view = E_SHELL_VIEW (task_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; - selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); - source = e_source_selector_peek_primary_selection (selector); - g_return_if_fail (E_IS_SOURCE (source)); - - calendar_setup_edit_task_list (GTK_WINDOW (shell_window), source); -} - -static void -action_task_list_rename_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellSidebar *task_shell_sidebar; - ESourceSelector *selector; - - task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; - selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); - - e_source_selector_edit_primary_selection (selector); -} - -static void -action_task_list_select_one_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellSidebar *task_shell_sidebar; - ESourceSelector *selector; - ESource *primary; - GSList *list, *iter; - - /* XXX ESourceSelector should provide a function for this. */ - - task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; - selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); - primary = e_source_selector_peek_primary_selection (selector); - g_return_if_fail (primary != NULL); - - list = e_source_selector_get_selection (selector); - for (iter = list; iter != NULL; iter = iter->next) { - ESource *source = iter->data; - - if (source == primary) - continue; - - e_source_selector_unselect_source (selector, source); - } - e_source_selector_free_selection (list); - - e_source_selector_select_source (selector, primary); -} - -static void -action_task_mark_complete_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - ECalModel *model; - GSList *list, *iter; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - list = e_calendar_table_get_selected (task_table); - model = e_calendar_table_get_model (task_table); - - for (iter = list; iter != NULL; iter = iter->next) { - ECalModelComponent *comp_data = iter->data; - e_cal_model_tasks_mark_comp_complete ( - E_CAL_MODEL_TASKS (model), comp_data); - } - - g_slist_free (list); -} - -static void -action_task_mark_incomplete_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - ECalModel *model; - GSList *list, *iter; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - list = e_calendar_table_get_selected (task_table); - model = e_calendar_table_get_model (task_table); - - for (iter = list; iter != NULL; iter = iter->next) { - ECalModelComponent *comp_data = iter->data; - e_cal_model_tasks_mark_comp_incomplete ( - E_CAL_MODEL_TASKS (model), comp_data); - } - - g_slist_free (list); -} - -static void -action_task_new_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - EShell *shell; - EShellView *shell_view; - EShellWindow *shell_window; - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - ECalModelComponent *comp_data; - ECal *client; - ECalComponent *comp; - CompEditor *editor; - GSList *list; - - shell_view = E_SHELL_VIEW (task_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell = e_shell_window_get_shell (shell_window); - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - - list = e_calendar_table_get_selected (task_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - client = comp_data->client; - editor = task_editor_new (client, shell, COMP_EDITOR_NEW_ITEM); - comp = cal_comp_task_new_with_defaults (client); - comp_editor_edit_comp (editor, comp); - - gtk_window_present (GTK_WINDOW (editor)); - - g_object_unref (comp); - g_object_unref (client); -} - -static void -action_task_open_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - ECalModelComponent *comp_data; - GSList *list; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - - list = e_calendar_table_get_selected (task_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - /* XXX We only open the first selected task. */ - e_task_shell_view_open_task (task_shell_view, comp_data); -} - -static void -action_task_open_url_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - ECalModelComponent *comp_data; - icalproperty *prop; - const gchar *uri; - GSList *list; - - shell_view = E_SHELL_VIEW (task_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - - list = e_calendar_table_get_selected (task_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - - /* XXX We only open the URI of the first selected task. */ - prop = icalcomponent_get_first_property ( - comp_data->icalcomp, ICAL_URL_PROPERTY); - g_return_if_fail (prop == NULL); - - uri = icalproperty_get_url (prop); - e_show_uri (GTK_WINDOW (shell_window), uri); -} - -static void -action_task_preview_cb (GtkToggleAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - gboolean visible; - - task_shell_content = task_shell_view->priv->task_shell_content; - visible = gtk_toggle_action_get_active (action); - e_task_shell_content_set_preview_visible (task_shell_content, visible); -} - -static void -action_task_print_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - ECalModelComponent *comp_data; - ECalComponent *comp; - icalcomponent *clone; - GtkPrintOperationAction print_action; - GSList *list; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - - list = e_calendar_table_get_selected (task_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - /* XXX We only print the first selected task. */ - comp = e_cal_component_new (); - clone = icalcomponent_new_clone (comp_data->icalcomp); - print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; - e_cal_component_set_icalcomponent (comp, clone); - print_comp (comp, comp_data->client, print_action); - g_object_unref (comp); -} - -static void -action_task_purge_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - GtkWidget *dialog; - GtkWidget *widget; - gboolean active; - gint response; - - shell_view = E_SHELL_VIEW (task_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - if (!calendar_config_get_confirm_purge ()) - goto purge; - - /* XXX This needs reworked. The dialog looks like ass. */ - - dialog = gtk_message_dialog_new ( - GTK_WINDOW (shell_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_YES_NO, - "%s", _("This operation will permanently erase all tasks " - "marked as completed. If you continue, you will not be able " - "to recover these tasks.\n\nReally erase these tasks?")); - - gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_NO); - - widget = gtk_check_button_new_with_label (_("Do not ask me again")); - gtk_box_pack_start ( - GTK_BOX (GTK_DIALOG (dialog)->vbox), widget, TRUE, TRUE, 6); - gtk_widget_show (widget); - - response = gtk_dialog_run (GTK_DIALOG (dialog)); - active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)); - gtk_widget_destroy (dialog); - - if (response != GTK_RESPONSE_YES) - return; - - if (active) - calendar_config_set_confirm_purge (FALSE); - -purge: - - /* FIXME */ - ; -} - -static void -action_task_save_as_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - ECalModelComponent *comp_data; - GSList *list; - gchar *filename; - gchar *string; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - - list = e_calendar_table_get_selected (task_table); - g_return_if_fail (list != NULL); - comp_data = list->data; - g_slist_free (list); - - filename = e_file_dialog_save (_("Save as..."), NULL); - if (filename == NULL) - return; - - string = e_cal_get_component_as_string ( - comp_data->client, comp_data->icalcomp); - if (string == NULL) { - g_warning ("Could not convert task to a string"); - return; - } - - e_write_file_uri (filename, string); - - g_free (filename); - g_free (string); -} - -static void -action_task_search_cb (GtkRadioAction *action, - GtkRadioAction *current, - ETaskShellView *task_shell_view) -{ - EShellView *shell_view; - EShellContent *shell_content; - const gchar *search_hint; - - /* XXX Figure out a way to handle this in EShellContent - * instead of every shell view having to handle it. - * The problem is EShellContent does not know what - * the search option actions are for this view. It - * would have to dig up the popup menu and retrieve - * the action for each menu item. Seems messy. */ - - shell_view = E_SHELL_VIEW (task_shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - - search_hint = gtk_action_get_label (GTK_ACTION (current)); - e_shell_content_set_search_hint (shell_content, search_hint); -} - -static GtkActionEntry task_entries[] = { - - { "task-assign", - NULL, - N_("_Assign Task"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_task_assign_cb) }, - - { "task-clipboard-copy", - GTK_STOCK_COPY, - NULL, - NULL, - N_("Copy selected tasks"), - G_CALLBACK (action_task_clipboard_copy_cb) }, - - { "task-clipboard-cut", - GTK_STOCK_CUT, - NULL, - NULL, - N_("Cut selected tasks"), - G_CALLBACK (action_task_clipboard_cut_cb) }, - - { "task-clipboard-paste", - GTK_STOCK_PASTE, - NULL, - NULL, - N_("Paste tasks from the clipboard"), - G_CALLBACK (action_task_clipboard_paste_cb) }, - - { "task-delete", - GTK_STOCK_DELETE, - N_("_Delete Task"), - NULL, - N_("Delete selected tasks"), - G_CALLBACK (action_task_delete_cb) }, - - { "task-forward", - "mail-forward", - N_("_Forward as iCalendar..."), - "f", - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_task_forward_cb) }, - - { "task-list-copy", - GTK_STOCK_COPY, - N_("Copy..."), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_task_list_copy_cb) }, - - { "task-list-delete", - GTK_STOCK_DELETE, - N_("_Delete"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_task_list_delete_cb) }, - - { "task-list-new", - "stock_todo", - N_("_New Task List"), - NULL, - N_("Create a new task list"), - G_CALLBACK (action_task_list_new_cb) }, - - { "task-list-properties", - GTK_STOCK_PROPERTIES, - NULL, - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_task_list_properties_cb) }, - - { "task-list-rename", - NULL, - N_("_Rename..."), - "F2", - N_("Rename the selected task list"), - G_CALLBACK (action_task_list_rename_cb) }, - - { "task-list-select-one", - "stock_check-filled", - N_("Show _Only This Task List"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_task_list_select_one_cb) }, - - { "task-mark-complete", - NULL, - N_("_Mark as Complete"), - "k", - N_("Mark selected tasks as complete"), - G_CALLBACK (action_task_mark_complete_cb) }, - - { "task-mark-incomplete", - NULL, - N_("Mar_k as Incomplete"), - NULL, - N_("Mark selected tasks as incomplete"), - G_CALLBACK (action_task_mark_incomplete_cb) }, - - { "task-new", - "stock_task", - N_("New _Task"), - NULL, - N_("Create a new task"), - G_CALLBACK (action_task_new_cb) }, - - { "task-open", - GTK_STOCK_OPEN, - N_("_Open Task"), - "o", - N_("View the selected task"), - G_CALLBACK (action_task_open_cb) }, - - { "task-open-url", - "applications-internet", - N_("Open _Web Page"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_task_open_url_cb) }, - - { "task-purge", - NULL, - N_("Purg_e"), - "e", - N_("Delete completed tasks"), - G_CALLBACK (action_task_purge_cb) }, - - { "task-save-as", - GTK_STOCK_SAVE_AS, - N_("_Save as iCalendar..."), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_task_save_as_cb) }, - - /*** Menus ***/ - - { "task-actions-menu", - NULL, - N_("_Actions"), - NULL, - NULL, - NULL } -}; - -static EPopupActionEntry task_popup_entries[] = { - - { "task-list-popup-copy", - NULL, - "task-list-copy" }, - - { "task-list-popup-delete", - NULL, - "task-list-delete" }, - - { "task-list-popup-properties", - NULL, - "task-list-properties" }, - - { "task-list-popup-rename", - NULL, - "task-list-rename" }, - - { "task-list-popup-select-one", - NULL, - "task-list-select-one" }, - - { "task-popup-assign", - NULL, - "task-assign" }, - - { "task-popup-clipboard-copy", - NULL, - "task-clipboard-copy" }, - - { "task-popup-clipboard-cut", - NULL, - "task-clipboard-cut" }, - - { "task-popup-clipboard-paste", - NULL, - "task-clipboard-paste" }, - - { "task-popup-delete", - NULL, - "task-delete" }, - - { "task-popup-forward", - NULL, - "task-forward" }, - - { "task-popup-mark-complete", - NULL, - "task-mark-complete" }, - - { "task-popup-mark-incomplete", - NULL, - "task-mark-incomplete" }, - - { "task-popup-open", - NULL, - "task-open" }, - - { "task-popup-open-url", - NULL, - "task-open-url" }, - - { "task-popup-save-as", - NULL, - "task-save-as" }, -}; - -static GtkToggleActionEntry task_toggle_entries[] = { - - { "task-preview", - NULL, - N_("Task _Preview"), - "m", - N_("Show task preview pane"), - G_CALLBACK (action_task_preview_cb), - TRUE } -}; - -static GtkRadioActionEntry task_filter_entries[] = { - - { "task-filter-active-tasks", - NULL, - N_("Active Tasks"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_FILTER_ACTIVE_TASKS }, - - { "task-filter-any-category", - NULL, - N_("Any Category"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_FILTER_ANY_CATEGORY }, - - { "task-filter-completed-tasks", - NULL, - N_("Completed Tasks"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_FILTER_COMPLETED_TASKS }, - - { "task-filter-next-7-days-tasks", - NULL, - N_("Next 7 Days' Tasks"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_FILTER_NEXT_7_DAYS_TASKS }, - - { "task-filter-overdue-tasks", - NULL, - N_("Overdue Tasks"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_FILTER_OVERDUE_TASKS }, - - { "task-filter-tasks-with-attachments", - NULL, - N_("Tasks with Attachments"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_FILTER_TASKS_WITH_ATTACHMENTS }, - - { "task-filter-unmatched", - NULL, - N_("Unmatched"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_FILTER_UNMATCHED } -}; - -static GtkRadioActionEntry task_search_entries[] = { - - { "task-search-any-field-contains", - NULL, - N_("Any field contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_SEARCH_ANY_FIELD_CONTAINS }, - - { "task-search-description-contains", - NULL, - N_("Description contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_SEARCH_DESCRIPTION_CONTAINS }, - - { "task-search-summary-contains", - NULL, - N_("Summary contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_SEARCH_SUMMARY_CONTAINS } -}; - -static GtkActionEntry lockdown_printing_entries[] = { - - { "task-list-print", - GTK_STOCK_PRINT, - NULL, - "p", - N_("Print the list of tasks"), - G_CALLBACK (action_task_list_print_cb) }, - - { "task-list-print-preview", - GTK_STOCK_PRINT_PREVIEW, - NULL, - NULL, - N_("Preview the list of tasks to be printed"), - G_CALLBACK (action_task_list_print_preview_cb) }, - - { "task-print", - GTK_STOCK_PRINT, - NULL, - NULL, - N_("Print the selected task"), - G_CALLBACK (action_task_print_cb) } -}; - -static EPopupActionEntry lockdown_printing_popup_entries[] = { - - { "task-popup-print", - NULL, - "task-print" } -}; - -void -e_task_shell_view_actions_init (ETaskShellView *task_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - GtkActionGroup *action_group; - GConfBridge *bridge; - GtkAction *action; - GObject *object; - const gchar *key; - - shell_view = E_SHELL_VIEW (task_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - /* Task Actions */ - action_group = ACTION_GROUP (TASKS); - gtk_action_group_add_actions ( - action_group, task_entries, - G_N_ELEMENTS (task_entries), task_shell_view); - e_action_group_add_popup_actions ( - action_group, task_popup_entries, - G_N_ELEMENTS (task_popup_entries)); - gtk_action_group_add_toggle_actions ( - action_group, task_toggle_entries, - G_N_ELEMENTS (task_toggle_entries), task_shell_view); - gtk_action_group_add_radio_actions ( - action_group, task_search_entries, - G_N_ELEMENTS (task_search_entries), - TASK_SEARCH_SUMMARY_CONTAINS, - G_CALLBACK (action_task_search_cb), task_shell_view); - - /* Lockdown Printing Actions */ - action_group = ACTION_GROUP (LOCKDOWN_PRINTING); - gtk_action_group_add_actions ( - action_group, lockdown_printing_entries, - G_N_ELEMENTS (lockdown_printing_entries), task_shell_view); - e_action_group_add_popup_actions ( - action_group, lockdown_printing_popup_entries, - G_N_ELEMENTS (lockdown_printing_popup_entries)); - - /* Bind GObject properties to GConf keys. */ - - bridge = gconf_bridge_get (); - - object = G_OBJECT (ACTION (TASK_PREVIEW)); - key = "/apps/evolution/calendar/display/show_task_preview"; - gconf_bridge_bind_property (bridge, key, object, "active"); - - /* Fine tuning. */ - - action = ACTION (TASK_DELETE); - g_object_set (action, "short-label", _("Delete"), NULL); - - g_signal_connect ( - ACTION (GAL_SAVE_CUSTOM_VIEW), "activate", - G_CALLBACK (action_gal_save_custom_view_cb), task_shell_view); - - g_signal_connect ( - ACTION (SEARCH_EXECUTE), "activate", - G_CALLBACK (action_search_execute_cb), task_shell_view); -} - -void -e_task_shell_view_update_search_filter (ETaskShellView *task_shell_view) -{ - EShellContent *shell_content; - EShellWindow *shell_window; - EShellView *shell_view; - GtkActionGroup *action_group; - GtkRadioAction *radio_action; - GList *list, *iter; - GSList *group; - gint ii; - - shell_view = E_SHELL_VIEW (task_shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - action_group = ACTION_GROUP (TASKS_FILTER); - e_action_group_remove_all_actions (action_group); - - /* Add the standard filter actions. */ - gtk_action_group_add_radio_actions ( - action_group, task_filter_entries, - G_N_ELEMENTS (task_filter_entries), - TASK_FILTER_ANY_CATEGORY, - G_CALLBACK (action_search_filter_cb), - task_shell_view); - - /* Retrieve the radio group from an action we just added. */ - list = gtk_action_group_list_actions (action_group); - radio_action = GTK_RADIO_ACTION (list->data); - group = gtk_radio_action_get_group (radio_action); - g_list_free (list); - - /* Build the category actions. */ - - list = e_categories_get_list (); - for (iter = list, ii = 0; iter != NULL; iter = iter->next, ii++) { - const gchar *category_name = iter->data; - const gchar *filename; - GtkAction *action; - gchar *action_name; - - action_name = g_strdup_printf ( - "task-filter-category-%d", ii); - radio_action = gtk_radio_action_new ( - action_name, category_name, NULL, NULL, ii); - g_free (action_name); - - /* Convert the category icon file to a themed icon name. */ - filename = e_categories_get_icon_file_for (category_name); - if (filename != NULL && *filename != '\0') { - gchar *basename; - gchar *cp; - - basename = g_path_get_basename (filename); - - /* Lose the file extension. */ - if ((cp = strrchr (basename, '.')) != NULL) - *cp = '\0'; - - g_object_set ( - radio_action, "icon-name", basename, NULL); - - g_free (basename); - } - - gtk_radio_action_set_group (radio_action, group); - group = gtk_radio_action_get_group (radio_action); - - /* The action group takes ownership of the action. */ - action = GTK_ACTION (radio_action); - gtk_action_group_add_action (action_group, action); - g_object_unref (radio_action); - } - g_list_free (list); - - /* Use any action in the group; doesn't matter which. */ - e_shell_content_set_filter_action (shell_content, radio_action); - - ii = TASK_FILTER_UNMATCHED; - e_shell_content_add_filter_separator_after (shell_content, ii); - - ii = TASK_FILTER_TASKS_WITH_ATTACHMENTS; - e_shell_content_add_filter_separator_after (shell_content, ii); -} diff --git a/calendar/module/e-task-shell-view-actions.h b/calendar/module/e-task-shell-view-actions.h deleted file mode 100644 index d7db39bcc9..0000000000 --- a/calendar/module/e-task-shell-view-actions.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * e-task-shell-view-actions.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_TASK_SHELL_VIEW_ACTIONS_H -#define E_TASK_SHELL_VIEW_ACTIONS_H - -#include - -/* Task Actions */ -#define E_SHELL_WINDOW_ACTION_TASK_ASSIGN(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-assign") -#define E_SHELL_WINDOW_ACTION_TASK_CLIPBOARD_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-clipboard-copy") -#define E_SHELL_WINDOW_ACTION_TASK_CLIPBOARD_CUT(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-clipboard-cut") -#define E_SHELL_WINDOW_ACTION_TASK_CLIPBOARD_PASTE(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-clipboard-paste") -#define E_SHELL_WINDOW_ACTION_TASK_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-delete") -#define E_SHELL_WINDOW_ACTION_TASK_FORWARD(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-forward") -#define E_SHELL_WINDOW_ACTION_TASK_MARK_COMPLETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-mark-complete") -#define E_SHELL_WINDOW_ACTION_TASK_MARK_INCOMPLETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-mark-incomplete") -#define E_SHELL_WINDOW_ACTION_TASK_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-new") -#define E_SHELL_WINDOW_ACTION_TASK_OPEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-open") -#define E_SHELL_WINDOW_ACTION_TASK_OPEN_URL(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-open-url") -#define E_SHELL_WINDOW_ACTION_TASK_PREVIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-preview") -#define E_SHELL_WINDOW_ACTION_TASK_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-print") -#define E_SHELL_WINDOW_ACTION_TASK_PURGE(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-purge") -#define E_SHELL_WINDOW_ACTION_TASK_SAVE_AS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-save-as") - -/* Task List Actions */ -#define E_SHELL_WINDOW_ACTION_TASK_LIST_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-copy") -#define E_SHELL_WINDOW_ACTION_TASK_LIST_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-delete") -#define E_SHELL_WINDOW_ACTION_TASK_LIST_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-new") -#define E_SHELL_WINDOW_ACTION_TASK_LIST_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-print") -#define E_SHELL_WINDOW_ACTION_TASK_LIST_PRINT_PREVIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-print-preview") -#define E_SHELL_WINDOW_ACTION_TASK_LIST_PROPERTIES(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-properties") -#define E_SHELL_WINDOW_ACTION_TASK_LIST_RENAME(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-rename") -#define E_SHELL_WINDOW_ACTION_TASK_LIST_SELECT_ONE(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-select-one") - -/* Task Query Actions */ -#define E_SHELL_WINDOW_ACTION_TASK_FILTER_ACTIVE_TASKS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-filter-active-tasks") -#define E_SHELL_WINDOW_ACTION_TASK_FILTER_ANY_CATEGORY(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-filter-any-category") -#define E_SHELL_WINDOW_ACTION_TASK_FILTER_COMPLETED_TASKS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-filter-completed-tasks") -#define E_SHELL_WINDOW_ACTION_TASK_FILTER_NEXT_7_DAYS_TASKS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-filter-next-7-days-tasks") -#define E_SHELL_WINDOW_ACTION_TASK_FILTER_OVERDUE_TASKS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-filter-overdue-tasks") -#define E_SHELL_WINDOW_ACTION_TASK_FILTER_TASKS_WITH_ATTACHMENTS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-filter-tasks-with-attachments") -#define E_SHELL_WINDOW_ACTION_TASK_FILTER_UNMATCHED(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-filter-unmatched") -#define E_SHELL_WINDOW_ACTION_TASK_SEARCH_ANY_FIELD_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-search-any-field-contains") -#define E_SHELL_WINDOW_ACTION_TASK_SEARCH_DESCRIPTION_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-search-description-contains") -#define E_SHELL_WINDOW_ACTION_TASK_SEARCH_SUMMARY_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-search-summary-contains") - -/* Action Groups */ -#define E_SHELL_WINDOW_ACTION_GROUP_TASKS(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "tasks") -#define E_SHELL_WINDOW_ACTION_GROUP_TASKS_FILTER(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "tasks-filter") - -#endif /* E_TASK_SHELL_VIEW_ACTIONS_H */ diff --git a/calendar/module/e-task-shell-view-private.c b/calendar/module/e-task-shell-view-private.c deleted file mode 100644 index d6fd8e35aa..0000000000 --- a/calendar/module/e-task-shell-view-private.c +++ /dev/null @@ -1,744 +0,0 @@ -/* - * e-task-shell-view-private.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-task-shell-view-private.h" - -#include "widgets/menus/gal-view-factory-etable.h" - -static void -task_shell_view_config_hide_completed_tasks_changed_cb (GConfClient *client, - guint id, - GConfEntry *entry, - gpointer user_data) -{ - ETaskShellView *task_shell_view = user_data; - ETaskShellContent *task_shell_content; - ETaskShellSidebar *task_shell_sidebar; - ECalendarTable *task_table; - GList *clients; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - - task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; - clients = e_task_shell_sidebar_get_clients (task_shell_sidebar); - - e_calendar_table_process_completed_tasks (task_table, clients, TRUE); - - /* Search query takes whether to show completed tasks into account, - * so if the preference has changed we need to update the query. */ - e_task_shell_view_execute_search (task_shell_view); - - g_list_free (clients); -} - -static void -task_shell_view_config_timezone_changed_cb (GConfClient *client, - guint id, - GConfEntry *entry, - gpointer user_data) -{ - ETaskShellView *task_shell_view = user_data; - - e_task_shell_view_update_timezone (task_shell_view); -} - -static void -task_shell_view_table_popup_event_cb (EShellView *shell_view, - GdkEventButton *event) -{ - const gchar *widget_path; - - widget_path = "/task-popup"; - e_shell_view_show_popup_menu (shell_view, widget_path, event); -} - -static void -task_shell_view_table_user_created_cb (ETaskShellView *task_shell_view, - ECalendarTable *task_table) -{ - ETaskShellSidebar *task_shell_sidebar; - ECalModel *model; - ECal *client; - ESource *source; - - /* This is the "Click to Add" handler. */ - - model = e_calendar_table_get_model (task_table); - client = e_cal_model_get_default_client (model); - source = e_cal_get_source (client); - - task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; - e_task_shell_sidebar_add_source (task_shell_sidebar, source); - - e_cal_model_add_client (model, client); -} - -static void -task_shell_view_selector_client_added_cb (ETaskShellView *task_shell_view, - ECal *client) -{ - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - ECalModel *model; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - model = e_calendar_table_get_model (task_table); - - e_cal_model_add_client (model, client); - e_task_shell_view_update_timezone (task_shell_view); -} - -static void -task_shell_view_selector_client_removed_cb (ETaskShellView *task_shell_view, - ECal *client) -{ - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - ECalModel *model; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - model = e_calendar_table_get_model (task_table); - - e_cal_model_remove_client (model, client); -} - -static gboolean -task_shell_view_selector_popup_event_cb (EShellView *shell_view, - ESource *primary_source, - GdkEventButton *event) -{ - const gchar *widget_path; - - widget_path = "/task-list-popup"; - e_shell_view_show_popup_menu (shell_view, widget_path, event); - - return TRUE; -} - -static gboolean -task_shell_view_update_timeout_cb (ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - ETaskShellSidebar *task_shell_sidebar; - ECalendarTable *task_table; - ECalModel *model; - GList *clients; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - model = e_calendar_table_get_model (task_table); - - task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; - clients = e_task_shell_sidebar_get_clients (task_shell_sidebar); - - e_calendar_table_process_completed_tasks (task_table, clients, FALSE); - e_cal_model_tasks_update_due_tasks (E_CAL_MODEL_TASKS (model)); - - g_list_free (clients); - - return TRUE; -} - -static void -task_shell_view_load_view_collection (EShellViewClass *shell_view_class) -{ - GalViewCollection *collection; - GalViewFactory *factory; - ETableSpecification *spec; - const gchar *base_dir; - gchar *filename; - - collection = shell_view_class->view_collection; - - base_dir = EVOLUTION_ETSPECDIR; - spec = e_table_specification_new (); - filename = g_build_filename (base_dir, ETSPEC_FILENAME, NULL); - if (!e_table_specification_load_from_file (spec, filename)) - g_critical ("Unable to load ETable specification file " - "for tasks"); - g_free (filename); - - factory = gal_view_factory_etable_new (spec); - gal_view_collection_add_factory (collection, factory); - g_object_unref (factory); - g_object_unref (spec); - - gal_view_collection_load (collection); -} - -static void -task_shell_view_notify_view_id_cb (ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - GalViewInstance *view_instance; - const gchar *view_id; - - task_shell_content = task_shell_view->priv->task_shell_content; - view_instance = - e_task_shell_content_get_view_instance (task_shell_content); - view_id = e_shell_view_get_view_id (E_SHELL_VIEW (task_shell_view)); - - /* A NULL view ID implies we're in a custom view. But you can - * only get to a custom view via the "Define Views" dialog, which - * would have already modified the view instance appropriately. - * Furthermore, there's no way to refer to a custom view by ID - * anyway, since custom views have no IDs. */ - if (view_id == NULL) - return; - - gal_view_instance_set_current_view_id (view_instance, view_id); -} - -void -e_task_shell_view_private_init (ETaskShellView *task_shell_view, - EShellViewClass *shell_view_class) -{ - if (!gal_view_collection_loaded (shell_view_class->view_collection)) - task_shell_view_load_view_collection (shell_view_class); - - g_signal_connect ( - task_shell_view, "notify::view-id", - G_CALLBACK (task_shell_view_notify_view_id_cb), NULL); -} - -void -e_task_shell_view_private_constructed (ETaskShellView *task_shell_view) -{ - ETaskShellViewPrivate *priv = task_shell_view->priv; - ETaskShellContent *task_shell_content; - ETaskShellSidebar *task_shell_sidebar; - EShellView *shell_view; - EShellBackend *shell_backend; - EShellContent *shell_content; - EShellSidebar *shell_sidebar; - EShellWindow *shell_window; - ECalendarTable *task_table; - ECalModel *model; - ETable *table; - ESourceSelector *selector; - guint id; - - shell_view = E_SHELL_VIEW (task_shell_view); - shell_backend = e_shell_view_get_shell_backend (shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - e_shell_window_add_action_group (shell_window, "tasks"); - e_shell_window_add_action_group (shell_window, "tasks-filter"); - - /* Cache these to avoid lots of awkward casting. */ - priv->task_shell_backend = g_object_ref (shell_backend); - priv->task_shell_content = g_object_ref (shell_content); - priv->task_shell_sidebar = g_object_ref (shell_sidebar); - - task_shell_content = E_TASK_SHELL_CONTENT (shell_content); - task_table = e_task_shell_content_get_task_table (task_shell_content); - model = e_calendar_table_get_model (task_table); - table = e_calendar_table_get_table (task_table); - - task_shell_sidebar = E_TASK_SHELL_SIDEBAR (shell_sidebar); - selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); - - g_signal_connect_swapped ( - task_table, "open-component", - G_CALLBACK (e_task_shell_view_open_task), - task_shell_view); - - g_signal_connect_swapped ( - task_table, "popup-event", - G_CALLBACK (task_shell_view_table_popup_event_cb), - task_shell_view); - - g_signal_connect_swapped ( - task_table, "status-message", - G_CALLBACK (e_task_shell_view_set_status_message), - task_shell_view); - - g_signal_connect_swapped ( - task_table, "user-created", - G_CALLBACK (task_shell_view_table_user_created_cb), - task_shell_view); - - g_signal_connect_swapped ( - model, "model-changed", - G_CALLBACK (e_task_shell_view_update_sidebar), - task_shell_view); - - g_signal_connect_swapped ( - model, "model-rows-deleted", - G_CALLBACK (e_task_shell_view_update_sidebar), - task_shell_view); - - g_signal_connect_swapped ( - model, "model-rows-inserted", - G_CALLBACK (e_task_shell_view_update_sidebar), - task_shell_view); - - g_signal_connect_swapped ( - table, "selection-change", - G_CALLBACK (e_task_shell_view_update_sidebar), - task_shell_view); - - g_signal_connect_swapped ( - task_shell_sidebar, "client-added", - G_CALLBACK (task_shell_view_selector_client_added_cb), - task_shell_view); - - g_signal_connect_swapped ( - task_shell_sidebar, "client-removed", - G_CALLBACK (task_shell_view_selector_client_removed_cb), - task_shell_view); - - g_signal_connect_swapped ( - task_shell_sidebar, "status-message", - G_CALLBACK (e_task_shell_view_set_status_message), - task_shell_view); - - g_signal_connect_swapped ( - selector, "popup-event", - G_CALLBACK (task_shell_view_selector_popup_event_cb), - task_shell_view); - - g_signal_connect_swapped ( - selector, "primary-selection-changed", - G_CALLBACK (e_shell_view_update_actions), - task_shell_view); - - e_categories_register_change_listener ( - G_CALLBACK (e_task_shell_view_update_search_filter), - task_shell_view); - - task_shell_view_update_timeout_cb (task_shell_view); - priv->update_timeout = g_timeout_add_full ( - G_PRIORITY_LOW, 60000, (GSourceFunc) - task_shell_view_update_timeout_cb, - task_shell_view, NULL); - - /* Listen for configuration changes. */ - - /* Timezone */ - id = calendar_config_add_notification_timezone ( - task_shell_view_config_timezone_changed_cb, task_shell_view); - priv->notifications = g_list_prepend ( - priv->notifications, GUINT_TO_POINTER (id)); - - /* Hide Completed Tasks (enable/units/value) */ - id = calendar_config_add_notification_hide_completed_tasks ( - task_shell_view_config_hide_completed_tasks_changed_cb, - task_shell_view); - priv->notifications = g_list_prepend ( - priv->notifications, GUINT_TO_POINTER (id)); - id = calendar_config_add_notification_hide_completed_tasks_units ( - task_shell_view_config_hide_completed_tasks_changed_cb, - task_shell_view); - priv->notifications = g_list_prepend ( - priv->notifications, GUINT_TO_POINTER (id)); - id = calendar_config_add_notification_hide_completed_tasks_value ( - task_shell_view_config_hide_completed_tasks_changed_cb, - task_shell_view); - priv->notifications = g_list_prepend ( - priv->notifications, GUINT_TO_POINTER (id)); - - e_task_shell_view_actions_init (task_shell_view); - e_task_shell_view_update_sidebar (task_shell_view); - e_task_shell_view_update_search_filter (task_shell_view); - e_task_shell_view_update_timezone (task_shell_view); - - e_task_shell_view_execute_search (task_shell_view); -} - -void -e_task_shell_view_private_dispose (ETaskShellView *task_shell_view) -{ - ETaskShellViewPrivate *priv = task_shell_view->priv; - GList *iter; - - DISPOSE (priv->task_shell_backend); - DISPOSE (priv->task_shell_content); - DISPOSE (priv->task_shell_sidebar); - - if (task_shell_view->priv->activity != NULL) { - /* XXX Activity is no cancellable. */ - e_activity_complete (task_shell_view->priv->activity); - g_object_unref (task_shell_view->priv->activity); - task_shell_view->priv->activity = NULL; - } - - if (priv->update_timeout > 0) { - g_source_remove (priv->update_timeout); - priv->update_timeout = 0; - } - - for (iter = priv->notifications; iter != NULL; iter = iter->next) { - guint notification_id = GPOINTER_TO_UINT (iter->data); - calendar_config_remove_notification (notification_id); - } - g_list_free (priv->notifications); - priv->notifications = NULL; -} - -void -e_task_shell_view_private_finalize (ETaskShellView *task_shell_view) -{ - /* XXX Nothing to do? */ -} - -void -e_task_shell_view_execute_search (ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - EShellView *shell_view; - EShellWindow *shell_window; - EShellContent *shell_content; - GtkAction *action; - GString *string; - ECalComponentPreview *task_preview; - ECalendarTable *task_table; - ECalModel *model; - FilterRule *rule; - const gchar *format; - const gchar *text; - time_t start_range; - time_t end_range; - gchar *start, *end; - gchar *query; - gchar *temp; - gint value; - - shell_view = E_SHELL_VIEW (task_shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - text = e_shell_content_get_search_text (shell_content); - - shell_window = e_shell_view_get_shell_window (shell_view); - action = ACTION (TASK_SEARCH_ANY_FIELD_CONTAINS); - value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); - - if (text == NULL || *text == '\0') { - text = ""; - value = TASK_SEARCH_SUMMARY_CONTAINS; - } - - switch (value) { - default: - text = ""; - /* fall through */ - - case TASK_SEARCH_SUMMARY_CONTAINS: - format = "(contains? \"summary\" %s)"; - break; - - case TASK_SEARCH_DESCRIPTION_CONTAINS: - format = "(contains? \"description\" %s)"; - break; - - case TASK_SEARCH_ANY_FIELD_CONTAINS: - format = "(contains? \"any\" %s)"; - break; - } - - /* Build the query. */ - string = g_string_new (""); - e_sexp_encode_string (string, text); - query = g_strdup_printf (format, string->str); - g_string_free (string, TRUE); - - /* Apply selected filter. */ - value = e_shell_content_get_filter_value (shell_content); - switch (value) { - case TASK_FILTER_ANY_CATEGORY: - break; - - case TASK_FILTER_UNMATCHED: - temp = g_strdup_printf ( - "(and (has-categories? #f) %s)", query); - g_free (query); - query = temp; - break; - - case TASK_FILTER_NEXT_7_DAYS_TASKS: - start_range = time (NULL); - end_range = time_add_day (start_range, 7); - start = isodate_from_time_t (start_range); - end = isodate_from_time_t (end_range); - - temp = g_strdup_printf ( - "(and %s (due-in-time-range? " - "(make-time \"%s\") (make-time \"%s\")))", - query, start, end); - g_free (query); - query = temp; - break; - - case TASK_FILTER_ACTIVE_TASKS: - start_range = time (NULL); - end_range = time_add_day (start_range, 365); - start = isodate_from_time_t (start_range); - end = isodate_from_time_t (end_range); - - temp = g_strdup_printf ( - "(and %s (due-in-time-range? " - "(make-time \"%s\") (make-time \"%s\")) " - "(not (is-completed?)))", - query, start, end); - g_free (query); - query = temp; - break; - - case TASK_FILTER_OVERDUE_TASKS: - start_range = 0; - end_range = time (NULL); - start = isodate_from_time_t (start_range); - end = isodate_from_time_t (end_range); - - temp = g_strdup_printf ( - "(and %s (due-in-time-range? " - "(make-time \"%s\") (make-time \"%s\")) " - "(not (is-completed?)))", - query, start, end); - g_free (query); - query = temp; - break; - - case TASK_FILTER_COMPLETED_TASKS: - temp = g_strdup_printf ( - "(and (is-completed?) %s)", query); - g_free (query); - query = temp; - break; - - case TASK_FILTER_TASKS_WITH_ATTACHMENTS: - temp = g_strdup_printf ( - "(and (has-attachments?) %s)", query); - g_free (query); - query = temp; - break; - - default: - { - GList *categories; - const gchar *category_name; - - categories = e_categories_get_list (); - category_name = g_list_nth_data (categories, value); - g_list_free (categories); - - temp = g_strdup_printf ( - "(and (has-categories? \"%s\") %s)", - category_name, query); - g_free (query); - query = temp; - break; - } - } - - /* Honor the user's preference to hide completed tasks. */ - temp = calendar_config_get_hide_completed_tasks_sexp (FALSE); - if (temp != NULL) { - gchar *temp2; - - temp2 = g_strdup_printf ("(and %s %s)", temp, query); - g_free (query); - g_free (temp); - query = temp2; - } - - /* XXX This is wrong. We need to programmatically construct a - * FilterRule, tell it to build code, and pass the resulting - * expression string to ECalModel. */ - rule = filter_rule_new (); - e_shell_content_set_search_rule (shell_content, rule); - g_object_unref (rule); - - /* Submit the query. */ - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - model = e_calendar_table_get_model (task_table); - e_cal_model_set_search_query (model, query); - g_free (query); - - task_preview = - e_task_shell_content_get_task_preview (task_shell_content); - e_cal_component_preview_clear (task_preview); -} - -void -e_task_shell_view_open_task (ETaskShellView *task_shell_view, - ECalModelComponent *comp_data) -{ - EShell *shell; - EShellView *shell_view; - EShellWindow *shell_window; - CompEditor *editor; - CompEditorFlags flags = 0; - ECalComponent *comp; - icalcomponent *clone; - icalproperty *prop; - const gchar *uid; - - g_return_if_fail (E_IS_TASK_SHELL_VIEW (task_shell_view)); - g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data)); - - shell_view = E_SHELL_VIEW (task_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell = e_shell_window_get_shell (shell_window); - - uid = icalcomponent_get_uid (comp_data->icalcomp); - editor = comp_editor_find_instance (uid); - - if (editor != NULL) - goto exit; - - comp = e_cal_component_new (); - clone = icalcomponent_new_clone (comp_data->icalcomp); - e_cal_component_set_icalcomponent (comp, clone); - - prop = icalcomponent_get_first_property ( - comp_data->icalcomp, ICAL_ATTENDEE_PROPERTY); - if (prop != NULL) - flags |= COMP_EDITOR_IS_ASSIGNED; - - if (itip_organizer_is_user (comp, comp_data->client)) - flags |= COMP_EDITOR_USER_ORG; - - if (!e_cal_component_has_attendees (comp)) - flags |= COMP_EDITOR_USER_ORG; - - editor = task_editor_new (comp_data->client, shell, flags); - comp_editor_edit_comp (editor, comp); - - g_object_ref (comp); - - if (flags & COMP_EDITOR_IS_ASSIGNED) - task_editor_show_assignment (TASK_EDITOR (editor)); - -exit: - gtk_window_present (GTK_WINDOW (editor)); -} - -void -e_task_shell_view_set_status_message (ETaskShellView *task_shell_view, - const gchar *status_message, - gdouble percent) -{ - EActivity *activity; - EShellView *shell_view; - EShellBackend *shell_backend; - - g_return_if_fail (E_IS_TASK_SHELL_VIEW (task_shell_view)); - - activity = task_shell_view->priv->activity; - shell_view = E_SHELL_VIEW (task_shell_view); - shell_backend = e_shell_view_get_shell_backend (shell_view); - - if (status_message == NULL || *status_message == '\0') { - if (activity != NULL) { - e_activity_complete (activity); - g_object_unref (activity); - activity = NULL; - } - - } else if (activity == NULL) { - activity = e_activity_new (status_message); - e_activity_set_percent (activity, percent); - e_shell_backend_add_activity (shell_backend, activity); - - } else { - e_activity_set_percent (activity, percent); - e_activity_set_primary_text (activity, status_message); - } - - task_shell_view->priv->activity = activity; -} - -void -e_task_shell_view_update_sidebar (ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - EShellView *shell_view; - EShellSidebar *shell_sidebar; - ECalendarTable *task_table; - ECalModel *model; - ETable *table; - GString *string; - const gchar *format; - gint n_rows; - gint n_selected; - - shell_view = E_SHELL_VIEW (task_shell_view); - shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - - model = e_calendar_table_get_model (task_table); - table = e_calendar_table_get_table (task_table); - - n_rows = e_table_model_row_count (E_TABLE_MODEL (model)); - n_selected = e_table_selected_count (table); - - string = g_string_sized_new (64); - - format = ngettext ("%d task", "%d tasks", n_rows); - g_string_append_printf (string, format, n_rows); - - if (n_selected > 0) { - format = _("%d selected"); - g_string_append_len (string, ", ", 2); - g_string_append_printf (string, format, n_selected); - } - - e_shell_sidebar_set_secondary_text (shell_sidebar, string->str); - - g_string_free (string, TRUE); -} - -void -e_task_shell_view_update_timezone (ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - ETaskShellSidebar *task_shell_sidebar; - ECalComponentPreview *task_preview; - icaltimezone *timezone; - GList *clients, *iter; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_preview = e_task_shell_content_get_task_preview (task_shell_content); - - task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; - clients = e_task_shell_sidebar_get_clients (task_shell_sidebar); - - timezone = calendar_config_get_icaltimezone (); - - for (iter = clients; iter != NULL; iter = iter->next) { - ECal *client = iter->data; - - if (e_cal_get_load_state (client) == E_CAL_LOAD_LOADED) - e_cal_set_default_timezone (client, timezone, NULL); - } - - e_cal_component_preview_set_default_timezone (task_preview, timezone); - - g_list_free (clients); -} diff --git a/calendar/module/e-task-shell-view-private.h b/calendar/module/e-task-shell-view-private.h deleted file mode 100644 index d3bb3cf086..0000000000 --- a/calendar/module/e-task-shell-view-private.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * e-task-shell-view-private.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_TASK_SHELL_VIEW_PRIVATE_H -#define E_TASK_SHELL_VIEW_PRIVATE_H - -#include "e-task-shell-view.h" - -#include -#include -#include -#include -#include - -#include "e-util/e-dialog-utils.h" -#include "e-util/e-error.h" -#include "e-util/e-util.h" -#include "e-util/gconf-bridge.h" -#include "widgets/misc/e-popup-action.h" - -#include "calendar/common/authentication.h" -#include "calendar/gui/calendar-config.h" -#include "calendar/gui/comp-util.h" -#include "calendar/gui/e-cal-component-preview.h" -#include "calendar/gui/e-cal-model-tasks.h" -#include "calendar/gui/e-calendar-selector.h" -#include "calendar/gui/print.h" -#include "calendar/gui/dialogs/calendar-setup.h" -#include "calendar/gui/dialogs/copy-source-dialog.h" -#include "calendar/gui/dialogs/task-editor.h" - -#include "e-task-shell-backend.h" -#include "e-task-shell-content.h" -#include "e-task-shell-sidebar.h" -#include "e-task-shell-view-actions.h" - -#define E_TASK_SHELL_VIEW_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_TASK_SHELL_VIEW, ETaskShellViewPrivate)) - -/* Shorthand, requires a variable named "shell_window". */ -#define ACTION(name) \ - (E_SHELL_WINDOW_ACTION_##name (shell_window)) -#define ACTION_GROUP(name) \ - (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) - -/* For use in dispose() methods. */ -#define DISPOSE(obj) \ - G_STMT_START { \ - if ((obj) != NULL) { g_object_unref (obj); (obj) = NULL; } \ - } G_STMT_END - -/* ETable Specifications */ -#define ETSPEC_FILENAME "e-calendar-table.etspec" - -G_BEGIN_DECLS - -/* Filter items are displayed in ascending order. - * Non-negative values are reserved for categories. */ -enum { - TASK_FILTER_ANY_CATEGORY = -7, - TASK_FILTER_UNMATCHED = -6, - TASK_FILTER_NEXT_7_DAYS_TASKS = -5, - TASK_FILTER_ACTIVE_TASKS = -4, - TASK_FILTER_OVERDUE_TASKS = -3, - TASK_FILTER_COMPLETED_TASKS = -2, - TASK_FILTER_TASKS_WITH_ATTACHMENTS = -1 -}; - -/* Search items are displayed in ascending order. */ -enum { - TASK_SEARCH_SUMMARY_CONTAINS, - TASK_SEARCH_DESCRIPTION_CONTAINS, - TASK_SEARCH_ANY_FIELD_CONTAINS -}; - -struct _ETaskShellViewPrivate { - - /* These are just for convenience. */ - ETaskShellBackend *task_shell_backend; - ETaskShellContent *task_shell_content; - ETaskShellSidebar *task_shell_sidebar; - - EActivity *activity; - guint update_timeout; - - /* GConf notification IDs */ - GList *notifications; -}; - -void e_task_shell_view_private_init - (ETaskShellView *task_shell_view, - EShellViewClass *shell_view_class); -void e_task_shell_view_private_constructed - (ETaskShellView *task_shell_view); -void e_task_shell_view_private_dispose - (ETaskShellView *task_shell_view); -void e_task_shell_view_private_finalize - (ETaskShellView *task_shell_view); - -/* Private Utilities */ - -void e_task_shell_view_actions_init - (ETaskShellView *task_shell_view); -void e_task_shell_view_execute_search - (ETaskShellView *task_shell_view); -void e_task_shell_view_open_task - (ETaskShellView *task_shell_view, - ECalModelComponent *comp_data); -void e_task_shell_view_set_status_message - (ETaskShellView *task_shell_view, - const gchar *status_message, - gdouble percent); -void e_task_shell_view_update_sidebar - (ETaskShellView *task_shell_view); -void e_task_shell_view_update_search_filter - (ETaskShellView *task_shell_view); -void e_task_shell_view_update_timezone - (ETaskShellView *task_shell_view); - -G_END_DECLS - -#endif /* E_TASK_SHELL_VIEW_PRIVATE_H */ diff --git a/calendar/module/e-task-shell-view.c b/calendar/module/e-task-shell-view.c deleted file mode 100644 index ce1b53a43c..0000000000 --- a/calendar/module/e-task-shell-view.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * e-task-shell-view.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-task-shell-view-private.h" - -static gpointer parent_class; -static GType task_shell_view_type; - -static void -task_shell_view_dispose (GObject *object) -{ - e_task_shell_view_private_dispose (E_TASK_SHELL_VIEW (object)); - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -task_shell_view_finalize (GObject *object) -{ - e_task_shell_view_private_finalize (E_TASK_SHELL_VIEW (object)); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -task_shell_view_constructed (GObject *object) -{ - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (parent_class)->constructed (object); - - e_task_shell_view_private_constructed (E_TASK_SHELL_VIEW (object)); -} - -static void -task_shell_view_update_actions (EShellView *shell_view) -{ - ETaskShellViewPrivate *priv; - EShellContent *shell_content; - EShellSidebar *shell_sidebar; - EShellWindow *shell_window; - GtkAction *action; - const gchar *label; - gboolean sensitive; - guint32 state; - - /* Be descriptive. */ - gboolean any_tasks_selected; - gboolean has_primary_source; - gboolean multiple_tasks_selected; - gboolean primary_source_is_system; - gboolean selection_has_url; - gboolean selection_is_assignable; - gboolean single_task_selected; - gboolean some_tasks_complete; - gboolean some_tasks_incomplete; - gboolean sources_are_editable; - - priv = E_TASK_SHELL_VIEW_GET_PRIVATE (shell_view); - - shell_window = e_shell_view_get_shell_window (shell_view); - - shell_content = e_shell_view_get_shell_content (shell_view); - state = e_shell_content_check_state (shell_content); - - single_task_selected = - (state & E_TASK_SHELL_CONTENT_SELECTION_SINGLE); - multiple_tasks_selected = - (state & E_TASK_SHELL_CONTENT_SELECTION_MULTIPLE); - selection_is_assignable = - (state & E_TASK_SHELL_CONTENT_SELECTION_CAN_ASSIGN); - sources_are_editable = - (state & E_TASK_SHELL_CONTENT_SELECTION_CAN_EDIT); - some_tasks_complete = - (state & E_TASK_SHELL_CONTENT_SELECTION_HAS_COMPLETE); - some_tasks_incomplete = - (state & E_TASK_SHELL_CONTENT_SELECTION_HAS_INCOMPLETE); - selection_has_url = - (state & E_TASK_SHELL_CONTENT_SELECTION_HAS_URL); - - shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - state = e_shell_sidebar_check_state (shell_sidebar); - - has_primary_source = - (state & E_TASK_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE); - primary_source_is_system = - (state & E_TASK_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM); - - any_tasks_selected = - (single_task_selected || multiple_tasks_selected); - - action = ACTION (TASK_ASSIGN); - sensitive = - single_task_selected && sources_are_editable && - selection_is_assignable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (TASK_CLIPBOARD_COPY); - sensitive = any_tasks_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (TASK_CLIPBOARD_CUT); - sensitive = any_tasks_selected && sources_are_editable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (TASK_CLIPBOARD_PASTE); - sensitive = sources_are_editable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (TASK_DELETE); - sensitive = any_tasks_selected && sources_are_editable; - gtk_action_set_sensitive (action, sensitive); - if (multiple_tasks_selected) - label = _("Delete Tasks"); - else - label = _("Delete Task"); - g_object_set (action, "label", label, NULL); - - action = ACTION (TASK_FORWARD); - sensitive = single_task_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (TASK_LIST_COPY); - sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (TASK_LIST_DELETE); - sensitive = has_primary_source && !primary_source_is_system; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (TASK_LIST_PROPERTIES); - sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (TASK_LIST_RENAME); - sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (TASK_MARK_COMPLETE); - sensitive = - any_tasks_selected && - sources_are_editable && - some_tasks_incomplete; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (TASK_MARK_INCOMPLETE); - sensitive = - any_tasks_selected && - sources_are_editable && - some_tasks_complete; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (TASK_OPEN); - sensitive = single_task_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (TASK_OPEN_URL); - sensitive = single_task_selected && selection_has_url; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (TASK_PRINT); - sensitive = single_task_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (TASK_PURGE); - sensitive = sources_are_editable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (TASK_SAVE_AS); - sensitive = single_task_selected; - gtk_action_set_sensitive (action, sensitive); -} - -static void -task_shell_view_class_init (ETaskShellViewClass *class, - GTypeModule *type_module) -{ - GObjectClass *object_class; - EShellViewClass *shell_view_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (ETaskShellViewPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->dispose = task_shell_view_dispose; - object_class->finalize = task_shell_view_finalize; - object_class->constructed = task_shell_view_constructed; - - shell_view_class = E_SHELL_VIEW_CLASS (class); - shell_view_class->label = _("Tasks"); - shell_view_class->icon_name = "evolution-tasks"; - shell_view_class->ui_definition = "evolution-tasks.ui"; - shell_view_class->ui_manager_id = "org.gnome.evolution.tasks"; - shell_view_class->search_options = "/task-search-options"; - shell_view_class->search_rules = "tasktypes.xml"; - shell_view_class->new_shell_content = e_task_shell_content_new; - shell_view_class->new_shell_sidebar = e_task_shell_sidebar_new; - shell_view_class->update_actions = task_shell_view_update_actions; -} - -static void -task_shell_view_init (ETaskShellView *task_shell_view, - EShellViewClass *shell_view_class) -{ - task_shell_view->priv = - E_TASK_SHELL_VIEW_GET_PRIVATE (task_shell_view); - - e_task_shell_view_private_init (task_shell_view, shell_view_class); -} - -GType -e_task_shell_view_get_type (void) -{ - return task_shell_view_type; -} - -void -e_task_shell_view_register_type (GTypeModule *type_module) -{ - const GTypeInfo type_info = { - sizeof (ETaskShellViewClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) task_shell_view_class_init, - (GClassFinalizeFunc) NULL, - type_module, - sizeof (ETaskShellView), - 0, /* n_preallocs */ - (GInstanceInitFunc) task_shell_view_init, - NULL /* value_table */ - }; - - task_shell_view_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_VIEW, - "ETaskShellView", &type_info, 0); -} diff --git a/calendar/module/e-task-shell-view.h b/calendar/module/e-task-shell-view.h deleted file mode 100644 index 8478e53cc2..0000000000 --- a/calendar/module/e-task-shell-view.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * e-task-shell-view.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_TASK_SHELL_VIEW_H -#define E_TASK_SHELL_VIEW_H - -#include -#include - -/* Standard GObject macros */ -#define E_TYPE_TASK_SHELL_VIEW \ - (e_task_shell_view_get_type ()) -#define E_TASK_SHELL_VIEW(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_TASK_SHELL_VIEW, ETaskShellView)) -#define E_TASK_SHELL_VIEW_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_TASK_SHELL_VIEW, ETaskShellViewClass)) -#define E_IS_TASK_SHELL_VIEW(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_TASK_SHELL_VIEW)) -#define E_IS_TASK_SHELL_VIEW_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_TASK_SHELL_VIEW)) -#define E_TASK_SHELL_VIEW_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_TASK_SHELL_VIEW, ETaskShellViewClass)) - -G_BEGIN_DECLS - -typedef struct _ETaskShellView ETaskShellView; -typedef struct _ETaskShellViewClass ETaskShellViewClass; -typedef struct _ETaskShellViewPrivate ETaskShellViewPrivate; - -struct _ETaskShellView { - EShellView parent; - ETaskShellViewPrivate *priv; -}; - -struct _ETaskShellViewClass { - EShellViewClass parent_class; -}; - -GType e_task_shell_view_get_type (void); -void e_task_shell_view_register_type (GTypeModule *type_module); - -G_END_DECLS - -#endif /* E_TASK_SHELL_VIEW_H */ diff --git a/calendar/module/evolution-module-calendar.c b/calendar/module/evolution-module-calendar.c deleted file mode 100644 index 63bf98ead9..0000000000 --- a/calendar/module/evolution-module-calendar.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * evolution-module-calendar.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-cal-shell-backend.h" -#include "e-cal-shell-content.h" -#include "e-cal-shell-sidebar.h" -#include "e-cal-shell-view.h" - -#include "e-memo-shell-backend.h" -#include "e-memo-shell-content.h" -#include "e-memo-shell-sidebar.h" -#include "e-memo-shell-view.h" - -#include "e-task-shell-backend.h" -#include "e-task-shell-content.h" -#include "e-task-shell-sidebar.h" -#include "e-task-shell-view.h" - -/* Module Entry Points */ -void e_module_load (GTypeModule *type_module); -void e_module_unload (GTypeModule *type_module); - -G_MODULE_EXPORT void -e_module_load (GTypeModule *type_module) -{ - /* Register dynamically loaded types. */ - - e_cal_shell_backend_register_type (type_module); - e_cal_shell_content_register_type (type_module); - e_cal_shell_sidebar_register_type (type_module); - e_cal_shell_view_register_type (type_module); - - e_memo_shell_backend_register_type (type_module); - e_memo_shell_content_register_type (type_module); - e_memo_shell_sidebar_register_type (type_module); - e_memo_shell_view_register_type (type_module); - - e_task_shell_backend_register_type (type_module); - e_task_shell_content_register_type (type_module); - e_task_shell_sidebar_register_type (type_module); - e_task_shell_view_register_type (type_module); -} - -G_MODULE_EXPORT void -e_module_unload (GTypeModule *type_module) -{ -} diff --git a/configure.ac b/configure.ac index bd90aee9e4..80bde6b9c1 100644 --- a/configure.ac +++ b/configure.ac @@ -25,9 +25,12 @@ AM_INIT_AUTOMAKE([gnu 1.9]) AC_CONFIG_HEADERS(config.h) AC_CONFIG_SRCDIR(README) -# Gnome Doc Initialization +# User Documentation GNOME_DOC_INIT +# Developer Documentation +GTK_DOC_CHECK(1.9) + # Automake 1.11 - Silent Build Rules m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) @@ -1787,7 +1790,7 @@ plugins_experimental="$plugins_experimental_always $IPOD_SYNC $TNEF_ATTACHMENTS all_plugins_experimental="$plugins_experimental_always ipod-sync tnef-attachments" dnl Temporary KILL-BONOBO hack -enable_plugins="attachment-reminder addressbook-file audio-inline bbdb bogo-junk-plugin caldav calendar-file calendar-http default-source external-editor google-account-setup hula-account-setup imap-features mail-notification mark-all-read plugin-manager profiler sa-junk-plugin save-calendar subject-thread $TNEF_ATTACHMENTS vcard-inline webdav-account-setup" +enable_plugins="attachment-reminder addressbook-file audio-inline bbdb bogo-junk-plugin caldav calendar-file calendar-http default-source external-editor google-account-setup hula-account-setup imap-features mail-notification plugin-manager profiler sa-junk-plugin save-calendar subject-thread $TNEF_ATTACHMENTS vcard-inline webdav-account-setup" dnl PLUGINS NOT BUILDING YET dnl ------------------------ @@ -1803,6 +1806,7 @@ dnl ipod-sync dnl itip-formatter dnl mailing-list-actions dnl mail-to-task +dnl mark-all-read dnl mono dnl prefer-plain dnl pst-import @@ -1994,7 +1998,6 @@ a11y/Makefile addressbook/Makefile addressbook/conduit/Makefile addressbook/gui/Makefile -addressbook/gui/component/Makefile addressbook/gui/contact-editor/Makefile addressbook/gui/contact-list-editor/Makefile addressbook/gui/merging/Makefile @@ -2056,7 +2059,6 @@ calendar/conduits/memo/Makefile calendar/gui/Makefile calendar/gui/alarm-notify/Makefile calendar/gui/dialogs/Makefile -calendar/module/Makefile composer/Makefile mail/Makefile mail/default/Makefile @@ -2080,6 +2082,11 @@ mail/default/sr/Makefile mail/default/sr@latin/Makefile mail/default/sv/Makefile mail/default/hu/Makefile +mail/importers/Makefile +modules/Makefile +modules/addressbook/Makefile +modules/calendar/Makefile +modules/mail/Makefile plugins/Makefile plugins/addressbook-file/Makefile plugins/attachment-reminder/Makefile diff --git a/doc/reference/shell/tmpl/e-shell-backend.sgml b/doc/reference/shell/tmpl/e-shell-backend.sgml new file mode 100644 index 0000000000..4d50f53e94 --- /dev/null +++ b/doc/reference/shell/tmpl/e-shell-backend.sgml @@ -0,0 +1,132 @@ + +EShellBackend + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@eshellbackend: the object which received the signal. +@arg1: + + + + + + + + + + + +@shell_backend_a: +@shell_backend_b: +@Returns: + + + + + + + +@shell_backend: +@Returns: + + + + + + + +@shell_backend: +@Returns: + + + + + + + +@shell_backend: +@Returns: + + + + + + + +@shell_backend: +@Returns: + + + + + + + +@shell_backend: +@activity: + + + + + + + +@shell_backend: + + + + + + + +@shell_backend: +@Returns: + + + + + + + +@shell_backend: +@Returns: + + + + + + + +@shell_backend: +@major: +@minor: +@micro: +@error: +@Returns: + + diff --git a/doc/reference/shell/tmpl/e-shell-settings.sgml b/doc/reference/shell/tmpl/e-shell-settings.sgml new file mode 100644 index 0000000000..1e1d2452e0 --- /dev/null +++ b/doc/reference/shell/tmpl/e-shell-settings.sgml @@ -0,0 +1,151 @@ + +EShellSettings + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@pspec: + + + + + + + +@shell_settings: +@property_name: +@gconf_key: + + + + + + + +@shell_settings: + + + + + + + +@shell_settings: +@property_name: +@Returns: + + + + + + + +@shell_settings: +@property_name: +@v_boolean: + + + + + + + +@shell_settings: +@property_name: +@Returns: + + + + + + + +@shell_settings: +@property_name: +@v_int: + + + + + + + +@shell_settings: +@property_name: +@Returns: + + + + + + + +@shell_settings: +@property_name: +@v_string: + + + + + + + +@shell_settings: +@property_name: +@Returns: + + + + + + + +@shell_settings: +@property_name: +@v_object: + + + + + + + +@shell_setting: +@property_name: +@Returns: + + + + + + + +@shell_setting: +@property_name: +@v_pointer: + + diff --git a/mail/Makefile.am b/mail/Makefile.am index 5e9a7b9781..8b7a123994 100644 --- a/mail/Makefile.am +++ b/mail/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = default +SUBDIRS = . default importers mailincludedir = $(privincludedir)/mail @@ -31,158 +31,125 @@ INCLUDES = \ -DPREFIX=\""$(prefix)"\" \ -DG_LOG_DOMAIN=\"evolution-mail\" -module_LTLIBRARIES = \ - libevolution-module-mail.la +privsolib_LTLIBRARIES = libevolution-mail.la -libevolution_module_mail_la_SOURCES = \ - evolution-module-mail.c \ - e-attachment-handler-mail.c \ - e-attachment-handler-mail.h \ - e-mail-attachment-bar.c \ +mailinclude_HEADERS = \ e-mail-attachment-bar.h \ - e-mail-browser.c \ e-mail-browser.h \ - e-mail-display.c \ e-mail-display.h \ - e-mail-label-dialog.c \ e-mail-label-dialog.h \ - e-mail-label-list-store.c \ e-mail-label-list-store.h \ - e-mail-label-manager.c \ e-mail-label-manager.h \ - e-mail-label-tree-view.c \ e-mail-label-tree-view.h \ - e-mail-local.c \ e-mail-local.h \ - e-mail-reader.c \ e-mail-reader.h \ - e-mail-reader-utils.c \ e-mail-reader-utils.h \ - e-mail-search-bar.c \ e-mail-search-bar.h \ - e-mail-shell-backend.c \ - e-mail-shell-backend.h \ - e-mail-shell-content.c \ - e-mail-shell-content.h \ - e-mail-shell-migrate.c \ - e-mail-shell-migrate.h \ - e-mail-shell-settings.c \ - e-mail-shell-settings.h \ - e-mail-shell-sidebar.c \ - e-mail-shell-sidebar.h \ - e-mail-shell-view.c \ - e-mail-shell-view.h \ - e-mail-shell-view-actions.c \ - e-mail-shell-view-actions.h \ - e-mail-shell-view-private.c \ - e-mail-shell-view-private.h \ - e-mail-store.c \ e-mail-store.h \ - e-searching-tokenizer.c \ e-searching-tokenizer.h \ - em-account-editor.c \ - em-account-editor.h \ - em-account-prefs.c \ - em-account-prefs.h \ - em-composer-prefs.c \ - em-composer-prefs.h \ - em-composer-utils.c \ em-composer-utils.h \ - em-config.c \ em-config.h \ - em-event.c \ em-event.h \ - em-filter-context.c \ em-filter-context.h \ - em-filter-editor.c \ em-filter-editor.h \ - em-filter-folder-element.c \ em-filter-folder-element.h \ - em-filter-rule.c \ em-filter-rule.h \ - em-filter-source-element.c \ em-filter-source-element.h \ - em-folder-properties.c \ em-folder-properties.h \ - em-folder-selection.c \ em-folder-selection.h \ - em-folder-selector.c \ em-folder-selector.h \ - em-folder-selection-button.c \ em-folder-selection-button.h \ - em-folder-tree.c \ em-folder-tree.h \ - em-folder-tree-model.c \ em-folder-tree-model.h \ - em-folder-utils.c \ em-folder-utils.h \ - em-format-hook.c \ em-format-hook.h \ - em-format-html.c \ em-format-html.h \ - em-format-html-display.c \ em-format-html-display.h \ - em-format-html-print.c \ em-format-html-print.h \ - em-html-stream.c \ em-html-stream.h \ - em-icon-stream.c \ em-icon-stream.h \ - em-inline-filter.c \ em-inline-filter.h \ - em-junk-hook.c \ em-junk-hook.h \ - em-mailer-prefs.c \ - em-mailer-prefs.h \ - em-menu.c \ em-menu.h \ - em-network-prefs.c \ - em-network-prefs.h \ - em-popup.c \ em-popup.h \ - em-search-context.c \ em-search-context.h \ - em-subscribe-editor.c \ em-subscribe-editor.h \ - em-sync-stream.c \ em-sync-stream.h \ - em-utils.c \ em-utils.h \ - em-vfolder-context.c \ em-vfolder-context.h \ - em-vfolder-editor.c \ em-vfolder-editor.h \ - em-vfolder-rule.c \ em-vfolder-rule.h \ - mail-autofilter.c \ mail-autofilter.h \ - mail-config.c \ mail-config.h \ - mail-folder-cache.c \ mail-folder-cache.h \ - mail-mt.c \ mail-mt.h \ - mail-ops.c \ mail-ops.h \ - mail-send-recv.c \ mail-send-recv.h \ - mail-session.c \ mail-session.h \ - mail-tools.c \ mail-tools.h \ - mail-vfolder.c \ mail-vfolder.h \ - message-list.c \ message-list.h \ - message-tag-editor.c \ message-tag-editor.h \ - message-tag-followup.c \ - message-tag-followup.h \ - importers/mail-importer.c \ - importers/mail-importer.h \ - importers/elm-importer.c \ - importers/pine-importer.c \ - importers/evolution-mbox-importer.c + message-tag-followup.h + +libevolution_mail_la_SOURCES = \ + e-mail-attachment-bar.c \ + e-mail-browser.c \ + e-mail-display.c \ + e-mail-label-dialog.c \ + e-mail-label-list-store.c \ + e-mail-label-manager.c \ + e-mail-label-tree-view.c \ + e-mail-local.c \ + e-mail-reader.c \ + e-mail-reader-utils.c \ + e-mail-search-bar.c \ + e-mail-store.c \ + e-searching-tokenizer.c \ + em-composer-utils.c \ + em-config.c \ + em-event.c \ + em-filter-context.c \ + em-filter-editor.c \ + em-filter-folder-element.c \ + em-filter-rule.c \ + em-filter-source-element.c \ + em-folder-properties.c \ + em-folder-selection.c \ + em-folder-selector.c \ + em-folder-selection-button.c \ + em-folder-tree.c \ + em-folder-tree-model.c \ + em-folder-utils.c \ + em-format-hook.c \ + em-format-html.c \ + em-format-html-display.c \ + em-format-html-print.c \ + em-html-stream.c \ + em-icon-stream.c \ + em-inline-filter.c \ + em-junk-hook.c \ + em-menu.c \ + em-popup.c \ + em-search-context.c \ + em-subscribe-editor.c \ + em-sync-stream.c \ + em-utils.c \ + em-vfolder-context.c \ + em-vfolder-editor.c \ + em-vfolder-rule.c \ + mail-autofilter.c \ + mail-config.c \ + mail-folder-cache.c \ + mail-mt.c \ + mail-ops.c \ + mail-send-recv.c \ + mail-session.c \ + mail-tools.c \ + mail-vfolder.c \ + message-list.c \ + message-tag-editor.c \ + message-tag-followup.c if ENABLE_SMIME SMIME_LIBS = \ @@ -190,7 +157,7 @@ SMIME_LIBS = \ $(top_builddir)/smime/gui/libevolution-smime.la endif -libevolution_module_mail_la_LIBADD = \ +libevolution_mail_la_LIBADD = \ $(top_builddir)/e-util/libeutil.la \ $(top_builddir)/shell/libeshell.la \ $(top_builddir)/composer/libcomposer.la \ @@ -199,20 +166,10 @@ libevolution_module_mail_la_LIBADD = \ $(top_builddir)/widgets/misc/libemiscwidgets.la \ $(top_builddir)/addressbook/gui/contact-editor/libecontacteditor.la \ $(top_builddir)/addressbook/gui/contact-list-editor/libecontactlisteditor.la \ + $(GTKHTML_LIBS) \ $(SMIME_LIBS) -#libevolution_mail_la_LIBADD = \ -# $(top_builddir)/widgets/misc/libefilterbar.la \ -# $(top_builddir)/filter/libfilter.la \ -# $(top_builddir)/widgets/menus/libmenus.la \ -# $(top_builddir)/addressbook/util/libeabutil.la \ -# $(EVOLUTION_MAIL_LIBS) \ -# $(GTKHTML_LIBS) \ -# $(REGEX_LIBS) \ -# $(THREADS_LIBS) - -libevolution_module_mail_la_LDFLAGS = \ - -avoid-version -module $(NO_UNDEFINED) +libevolution_mail_la_LDFLAGS = $(NO_UNDEFINED) libevolution_mail_la_DEPENDENCIES = em-filter-i18n.h diff --git a/mail/e-attachment-handler-mail.c b/mail/e-attachment-handler-mail.c deleted file mode 100644 index c17c97d8ca..0000000000 --- a/mail/e-attachment-handler-mail.c +++ /dev/null @@ -1,524 +0,0 @@ -/* - * e-attachment-handler-mail.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-attachment-handler-mail.h" - -#include -#include -#include - -#include "e-util/e-error.h" -#include "mail/em-composer-utils.h" -#include "mail/mail-tools.h" - -#define E_ATTACHMENT_HANDLER_MAIL_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_ATTACHMENT_HANDLER_MAIL, EAttachmentHandlerMailPrivate)) - -struct _EAttachmentHandlerMailPrivate { - gint placeholder; -}; - -static gpointer parent_class; - -static const gchar *ui = -"" -" " -" " -" " -" " -" " -" " -" " -""; - -/* Note: Do not use the info field. */ -static GtkTargetEntry target_table[] = { - { (gchar *) "message/rfc822", 0, 0 }, - { (gchar *) "x-uid-list", 0, 0 } -}; - -static void -attachment_handler_mail_forward (GtkAction *action, - EAttachmentView *view) -{ - EAttachment *attachment; - CamelMimePart *mime_part; - CamelDataWrapper *wrapper; - GList *selected; - - selected = e_attachment_view_get_selected_attachments (view); - g_return_if_fail (g_list_length (selected) == 1); - - attachment = E_ATTACHMENT (selected->data); - mime_part = e_attachment_get_mime_part (attachment); - wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); - - em_utils_forward_message (CAMEL_MIME_MESSAGE (wrapper), NULL); - - g_list_foreach (selected, (GFunc) g_object_unref, NULL); - g_list_free (selected); -} - -static void -attachment_handler_mail_reply_all (GtkAction *action, - EAttachmentView *view) -{ - EAttachment *attachment; - CamelMimePart *mime_part; - CamelDataWrapper *wrapper; - GList *selected; - - selected = e_attachment_view_get_selected_attachments (view); - g_return_if_fail (g_list_length (selected) == 1); - - attachment = E_ATTACHMENT (selected->data); - mime_part = e_attachment_get_mime_part (attachment); - wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); - - em_utils_reply_to_message ( - NULL, NULL, CAMEL_MIME_MESSAGE (wrapper), - REPLY_MODE_ALL, NULL); - - g_list_foreach (selected, (GFunc) g_object_unref, NULL); - g_list_free (selected); -} - -static void -attachment_handler_mail_reply_sender (GtkAction *action, - EAttachmentView *view) -{ - EAttachment *attachment; - CamelMimePart *mime_part; - CamelDataWrapper *wrapper; - GList *selected; - - selected = e_attachment_view_get_selected_attachments (view); - g_return_if_fail (g_list_length (selected) == 1); - - attachment = E_ATTACHMENT (selected->data); - mime_part = e_attachment_get_mime_part (attachment); - wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); - - em_utils_reply_to_message ( - NULL, NULL, CAMEL_MIME_MESSAGE (wrapper), - REPLY_MODE_SENDER, NULL); - - g_list_foreach (selected, (GFunc) g_object_unref, NULL); - g_list_free (selected); -} - -static GtkActionEntry standard_entries[] = { - - { "mail-forward", - "mail-forward", - N_("_Forward"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (attachment_handler_mail_forward) }, - - { "mail-reply-all", - "mail-reply-all", - N_("Reply to _All"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (attachment_handler_mail_reply_all) }, - - { "mail-reply-sender", - "mail-reply-sender", - N_("_Reply to Sender"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (attachment_handler_mail_reply_sender) } -}; - -static void -attachment_handler_mail_message_rfc822 (EAttachmentView *view, - GdkDragContext *drag_context, - gint x, - gint y, - GtkSelectionData *selection_data, - guint info, - guint time) -{ - static GdkAtom atom = GDK_NONE; - EAttachmentStore *store; - EAttachment *attachment; - CamelMimeMessage *message; - CamelDataWrapper *wrapper; - CamelStream *stream; - const gchar *data; - gboolean success = FALSE; - gpointer parent; - gint length; - - if (G_UNLIKELY (atom == GDK_NONE)) - atom = gdk_atom_intern_static_string ("message/rfc822"); - - if (gtk_selection_data_get_target (selection_data) != atom) - return; - - g_signal_stop_emission_by_name (view, "drag-data-received"); - - data = (const gchar *) gtk_selection_data_get_data (selection_data); - length = gtk_selection_data_get_length (selection_data); - - stream = camel_stream_mem_new (); - camel_stream_write (stream, data, length); - camel_stream_reset (stream); - - message = camel_mime_message_new (); - wrapper = CAMEL_DATA_WRAPPER (message); - - if (camel_data_wrapper_construct_from_stream (wrapper, stream) == -1) - goto exit; - - store = e_attachment_view_get_store (view); - - parent = gtk_widget_get_toplevel (GTK_WIDGET (view)); - parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; - - attachment = e_attachment_new_for_message (message); - e_attachment_store_add_attachment (store, attachment); - e_attachment_load_async ( - attachment, (GAsyncReadyCallback) - e_attachment_load_handle_error, parent); - g_object_unref (attachment); - - success = TRUE; - -exit: - camel_object_unref (message); - camel_object_unref (stream); - - gtk_drag_finish (drag_context, success, FALSE, time); -} - -static void -attachment_handler_mail_x_uid_list (EAttachmentView *view, - GdkDragContext *drag_context, - gint x, - gint y, - GtkSelectionData *selection_data, - guint info, - guint time) -{ - static GdkAtom atom = GDK_NONE; - CamelException ex = CAMEL_EXCEPTION_INITIALISER; - CamelDataWrapper *wrapper; - CamelMimeMessage *message; - CamelMultipart *multipart; - CamelMimePart *mime_part; - CamelFolder *folder = NULL; - EAttachment *attachment; - EAttachmentStore *store; - GPtrArray *uids; - const gchar *data; - const gchar *cp, *end; - gchar *description; - gpointer parent; - gint length; - guint ii; - - if (G_UNLIKELY (atom == GDK_NONE)) - atom = gdk_atom_intern_static_string ("x-uid-list"); - - if (gtk_selection_data_get_target (selection_data) != atom) - return; - - store = e_attachment_view_get_store (view); - - parent = gtk_widget_get_toplevel (GTK_WIDGET (view)); - parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; - - uids = g_ptr_array_new (); - - data = (const gchar *) gtk_selection_data_get_data (selection_data); - length = gtk_selection_data_get_length (selection_data); - - /* The UID list is delimited by NUL characters. - * Brilliant. So we can't use g_strsplit(). */ - - cp = data; - end = data + length; - - while (cp < end) { - const gchar *start = cp; - - while (cp < end && *cp != '\0') - cp++; - - /* Skip the first string. */ - if (start > data) - g_ptr_array_add (uids, g_strndup (start, cp - start)); - - cp++; - } - - if (uids->len == 0) - goto exit; - - /* The first string is the folder URI. */ - folder = mail_tool_uri_to_folder (data, 0, &ex); - if (folder == NULL) - goto exit; - - /* Handle one message. */ - if (uids->len == 1) { - message = camel_folder_get_message ( - folder, uids->pdata[0], &ex); - if (message == NULL) - goto exit; - - attachment = e_attachment_new_for_message (message); - e_attachment_store_add_attachment (store, attachment); - e_attachment_load_async ( - attachment, (GAsyncReadyCallback) - e_attachment_load_handle_error, parent); - g_object_unref (attachment); - - camel_object_unref (message); - goto exit; - } - - /* Build a multipart/digest message out of the UIDs. */ - - multipart = camel_multipart_new (); - wrapper = CAMEL_DATA_WRAPPER (multipart); - camel_data_wrapper_set_mime_type (wrapper, "multipart/digest"); - camel_multipart_set_boundary (multipart, NULL); - - for (ii = 0; ii < uids->len; ii++) { - message = camel_folder_get_message ( - folder, uids->pdata[ii], &ex); - if (message == NULL) { - camel_object_unref (multipart); - goto exit; - } - - mime_part = camel_mime_part_new (); - wrapper = CAMEL_DATA_WRAPPER (message); - camel_mime_part_set_disposition (mime_part, "inline"); - camel_medium_set_content_object ( - CAMEL_MEDIUM (mime_part), wrapper); - camel_mime_part_set_content_type (mime_part, "message/rfc822"); - camel_multipart_add_part (multipart, mime_part); - camel_object_unref (mime_part); - - camel_object_unref (message); - } - - mime_part = camel_mime_part_new (); - wrapper = CAMEL_DATA_WRAPPER (multipart); - camel_medium_set_content_object (CAMEL_MEDIUM (mime_part), wrapper); - - /* Translators: This is only for multiple messages. */ - description = g_strdup_printf (_("%d attached messages"), uids->len); - camel_mime_part_set_description (mime_part, description); - g_free (description); - - attachment = e_attachment_new (); - e_attachment_set_mime_part (attachment, mime_part); - e_attachment_store_add_attachment (store, attachment); - e_attachment_load_async ( - attachment, (GAsyncReadyCallback) - e_attachment_load_handle_error, parent); - g_object_unref (attachment); - - camel_object_unref (mime_part); - camel_object_unref (multipart); - -exit: - if (camel_exception_is_set (&ex)) { - gchar *folder_name; - - if (folder != NULL) - camel_object_get ( - folder, NULL, CAMEL_FOLDER_NAME, - &folder_name, NULL); - else - folder_name = g_strdup (data); - - e_error_run ( - parent, "mail-composer:attach-nomessages", - folder_name, camel_exception_get_description (&ex), - NULL); - - if (folder != NULL) - camel_object_free ( - folder, CAMEL_FOLDER_NAME, folder_name); - else - g_free (folder_name); - - camel_exception_clear (&ex); - } - - if (folder != NULL) - camel_object_unref (folder); - - g_ptr_array_free (uids, TRUE); - - g_signal_stop_emission_by_name (view, "drag-data-received"); -} - -static void -attachment_handler_mail_update_actions (EAttachmentView *view) -{ - EAttachment *attachment; - CamelMimePart *mime_part; - CamelDataWrapper *wrapper; - GtkActionGroup *action_group; - GList *selected; - gboolean visible = FALSE; - - selected = e_attachment_view_get_selected_attachments (view); - - if (g_list_length (selected) != 1) - goto exit; - - attachment = E_ATTACHMENT (selected->data); - mime_part = e_attachment_get_mime_part (attachment); - - if (!CAMEL_IS_MIME_PART (mime_part)) - goto exit; - - wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); - - visible = CAMEL_IS_MIME_MESSAGE (wrapper); - -exit: - action_group = e_attachment_view_get_action_group (view, "mail"); - gtk_action_group_set_visible (action_group, visible); - - g_list_foreach (selected, (GFunc) g_object_unref, NULL); - g_list_free (selected); -} - -static void -attachment_handler_mail_constructed (GObject *object) -{ - EAttachmentHandler *handler; - EAttachmentView *view; - GtkActionGroup *action_group; - GtkUIManager *ui_manager; - GError *error = NULL; - - handler = E_ATTACHMENT_HANDLER (object); - - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (parent_class)->constructed (object); - - view = e_attachment_handler_get_view (handler); - - action_group = e_attachment_view_add_action_group (view, "mail"); - gtk_action_group_add_actions ( - action_group, standard_entries, - G_N_ELEMENTS (standard_entries), view); - - ui_manager = e_attachment_view_get_ui_manager (view); - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - - if (error != NULL) { - g_warning ("%s", error->message); - g_error_free (error); - } - - g_signal_connect ( - view, "update-actions", - G_CALLBACK (attachment_handler_mail_update_actions), - NULL); - - g_signal_connect ( - view, "drag-data-received", - G_CALLBACK (attachment_handler_mail_message_rfc822), - NULL); - - g_signal_connect ( - view, "drag-data-received", - G_CALLBACK (attachment_handler_mail_x_uid_list), - NULL); -} - -static GdkDragAction -attachment_handler_mail_get_drag_actions (EAttachmentHandler *handler) -{ - return GDK_ACTION_COPY; -} - -static const GtkTargetEntry * -attachment_handler_mail_get_target_table (EAttachmentHandler *handler, - guint *n_targets) -{ - if (n_targets != NULL) - *n_targets = G_N_ELEMENTS (target_table); - - return target_table; -} - -static void -attachment_handler_mail_class_init (EAttachmentHandlerMailClass *class) -{ - GObjectClass *object_class; - EAttachmentHandlerClass *handler_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (EAttachmentHandlerMailPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->constructed = attachment_handler_mail_constructed; - - handler_class = E_ATTACHMENT_HANDLER_CLASS (class); - handler_class->get_drag_actions = attachment_handler_mail_get_drag_actions; - handler_class->get_target_table = attachment_handler_mail_get_target_table; -} - -static void -attachment_handler_mail_init (EAttachmentHandlerMail *handler) -{ - handler->priv = E_ATTACHMENT_HANDLER_MAIL_GET_PRIVATE (handler); -} - -GType -e_attachment_handler_mail_get_type (void) -{ - static GType type = 0; - - if (G_UNLIKELY (type == 0)) { - static const GTypeInfo type_info = { - sizeof (EAttachmentHandlerMailClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) attachment_handler_mail_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (EAttachmentHandlerMail), - 0, /* n_preallocs */ - (GInstanceInitFunc) attachment_handler_mail_init, - NULL /* value_table */ - }; - - type = g_type_register_static ( - E_TYPE_ATTACHMENT_HANDLER, - "EAttachmentHandlerMail", &type_info, 0); - } - - return type; -} diff --git a/mail/e-attachment-handler-mail.h b/mail/e-attachment-handler-mail.h deleted file mode 100644 index c62ea99cab..0000000000 --- a/mail/e-attachment-handler-mail.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * e-attachment-handler-mail.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_ATTACHMENT_HANDLER_MAIL_H -#define E_ATTACHMENT_HANDLER_MAIL_H - -#include - -/* Standard GObject macros */ -#define E_TYPE_ATTACHMENT_HANDLER_MAIL \ - (e_attachment_handler_mail_get_type ()) -#define E_ATTACHMENT_HANDLER_MAIL(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_ATTACHMENT_HANDLER_MAIL, EAttachmentHandlerMail)) -#define E_ATTACHMENT_HANDLER_MAIL_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_ATTACHMENT_HANDLER_MAIL, EAttachmentHandlerMailClass)) -#define E_IS_ATTACHMENT_HANDLER_MAIL(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_ATTACHMENT_HANDLER_MAIL)) -#define E_IS_ATTACHMENT_HANDLER_MAIL_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_ATTACHMENT_HANDLER_MAIL)) -#define E_ATTACHMENT_HANDLER_MAIL_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_ATTACHMENT_HANDLER_MAIL, EAttachmentHandlerMailClass)) - -G_BEGIN_DECLS - -typedef struct _EAttachmentHandlerMail EAttachmentHandlerMail; -typedef struct _EAttachmentHandlerMailClass EAttachmentHandlerMailClass; -typedef struct _EAttachmentHandlerMailPrivate EAttachmentHandlerMailPrivate; - -struct _EAttachmentHandlerMail { - EAttachmentHandler parent; - EAttachmentHandlerMailPrivate *priv; -}; - -struct _EAttachmentHandlerMailClass { - EAttachmentHandlerClass parent_class; -}; - -GType e_attachment_handler_mail_get_type (void); - -G_END_DECLS - -#endif /* E_ATTACHMENT_HANDLER_MAIL_H */ diff --git a/mail/e-mail-browser.c b/mail/e-mail-browser.c index e4013c5004..1dd3fae587 100644 --- a/mail/e-mail-browser.c +++ b/mail/e-mail-browser.c @@ -32,7 +32,6 @@ #include "mail/e-mail-reader.h" #include "mail/e-mail-reader-utils.h" #include "mail/e-mail-search-bar.h" -#include "mail/e-mail-shell-backend.h" #include "mail/em-folder-tree-model.h" #include "mail/em-format-html-display.h" #include "mail/message-list.h" @@ -705,14 +704,13 @@ e_mail_browser_get_type (void) } GtkWidget * -e_mail_browser_new (EMailShellBackend *mail_shell_backend) +e_mail_browser_new (EShellBackend *shell_backend) { - g_return_val_if_fail ( - E_IS_MAIL_SHELL_BACKEND (mail_shell_backend), NULL); + g_return_val_if_fail (E_IS_SHELL_BACKEND (shell_backend), NULL); return g_object_new ( E_TYPE_MAIL_BROWSER, - "shell-backend", mail_shell_backend, NULL); + "shell-backend", shell_backend, NULL); } void diff --git a/mail/e-mail-browser.h b/mail/e-mail-browser.h index 2605b2e04c..f2fd4d9131 100644 --- a/mail/e-mail-browser.h +++ b/mail/e-mail-browser.h @@ -23,7 +23,7 @@ #define E_MAIL_BROWSER_H #include -#include +#include /* Standard GObject macros */ #define E_TYPE_MAIL_BROWSER \ @@ -60,7 +60,7 @@ struct _EMailBrowserClass { }; GType e_mail_browser_get_type (void); -GtkWidget * e_mail_browser_new (EMailShellBackend *mail_shell_backend); +GtkWidget * e_mail_browser_new (EShellBackend *shell_backend); void e_mail_browser_close (EMailBrowser *browser); gboolean e_mail_browser_get_show_deleted (EMailBrowser *browser); void e_mail_browser_set_show_deleted (EMailBrowser *browser, diff --git a/mail/e-mail-reader-utils.c b/mail/e-mail-reader-utils.c index f0999be97e..b9bde5b370 100644 --- a/mail/e-mail-reader-utils.c +++ b/mail/e-mail-reader-utils.c @@ -190,7 +190,6 @@ e_mail_reader_mark_selected (EMailReader *reader, guint e_mail_reader_open_selected (EMailReader *reader) { - EMailShellBackend *mail_shell_backend; EShellBackend *shell_backend; MessageList *message_list; CamelFolder *folder; @@ -206,8 +205,6 @@ e_mail_reader_open_selected (EMailReader *reader) shell_backend = e_mail_reader_get_shell_backend (reader); window = e_mail_reader_get_window (reader); - mail_shell_backend = E_MAIL_SHELL_BACKEND (shell_backend); - folder = message_list->folder; folder_uri = message_list->folder_uri; uids = message_list_get_selected (message_list); @@ -280,7 +277,7 @@ e_mail_reader_open_selected (EMailReader *reader) const gchar *uid = views->pdata[ii]; GtkWidget *browser; - browser = e_mail_browser_new (mail_shell_backend); + browser = e_mail_browser_new (shell_backend); e_mail_reader_set_folder ( E_MAIL_READER (browser), folder, folder_uri); e_mail_reader_set_message ( @@ -405,9 +402,6 @@ e_mail_reader_reply_to_message (EMailReader *reader, uid = message_list->cursor_uid; g_return_if_fail (uid != NULL); - if (!em_utils_check_user_can_send_mail (window)) - return; - if (!gtk_html_command (html, "is-selection-active")) goto whole_message; diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c index a58e0acd46..6d680aebe1 100644 --- a/mail/e-mail-reader.c +++ b/mail/e-mail-reader.c @@ -40,7 +40,6 @@ #include "mail/e-mail-browser.h" #include "mail/e-mail-display.h" #include "mail/e-mail-reader-utils.h" -#include "mail/e-mail-shell-backend.h" #include "mail/em-composer-utils.h" #include "mail/em-event.h" #include "mail/em-folder-selector.h" @@ -342,9 +341,6 @@ action_mail_forward_cb (GtkAction *action, message_list = e_mail_reader_get_message_list (reader); window = e_mail_reader_get_window (reader); - if (!em_utils_check_user_can_send_mail (window)) - return; - folder = message_list->folder; folder_uri = message_list->folder_uri; uids = message_list_get_selected (message_list); @@ -365,9 +361,6 @@ action_mail_forward_attached_cb (GtkAction *action, message_list = e_mail_reader_get_message_list (reader); window = e_mail_reader_get_window (reader); - if (!em_utils_check_user_can_send_mail (window)) - return; - folder = message_list->folder; folder_uri = message_list->folder_uri; uids = message_list_get_selected (message_list); @@ -388,9 +381,6 @@ action_mail_forward_inline_cb (GtkAction *action, message_list = e_mail_reader_get_message_list (reader); window = e_mail_reader_get_window (reader); - if (!em_utils_check_user_can_send_mail (window)) - return; - folder = message_list->folder; folder_uri = message_list->folder_uri; uids = message_list_get_selected (message_list); @@ -411,9 +401,6 @@ action_mail_forward_quoted_cb (GtkAction *action, message_list = e_mail_reader_get_message_list (reader); window = e_mail_reader_get_window (reader); - if (!em_utils_check_user_can_send_mail (window)) - return; - folder = message_list->folder; folder_uri = message_list->folder_uri; uids = message_list_get_selected (message_list); @@ -517,9 +504,6 @@ action_mail_message_edit_cb (GtkAction *action, window = e_mail_reader_get_window (reader); message_list = e_mail_reader_get_message_list (reader); - if (!em_utils_check_user_can_send_mail (window)) - return; - folder = message_list->folder; uids = message_list_get_selected (message_list); @@ -536,9 +520,6 @@ action_mail_message_new_cb (GtkAction *action, message_list = e_mail_reader_get_message_list (reader); window = e_mail_reader_get_window (reader); - if (!em_utils_check_user_can_send_mail (window)) - return; - em_utils_compose_new_message (message_list->folder_uri); } @@ -746,9 +727,6 @@ action_mail_redirect_cb (GtkAction *action, uid = message_list->cursor_uid; g_return_if_fail (uid != NULL); - if (!em_utils_check_user_can_send_mail (window)) - return; - em_utils_redirect_message_by_uid (folder, uid); } @@ -861,7 +839,6 @@ action_mail_show_source_cb (GtkAction *action, EMailReader *reader) { EMFormatHTMLDisplay *html_display; - EMailShellBackend *mail_shell_backend; EShellBackend *shell_backend; MessageList *message_list; CamelFolder *folder; @@ -871,14 +848,13 @@ action_mail_show_source_cb (GtkAction *action, message_list = e_mail_reader_get_message_list (reader); shell_backend = e_mail_reader_get_shell_backend (reader); - mail_shell_backend = E_MAIL_SHELL_BACKEND (shell_backend); folder = message_list->folder; folder_uri = message_list->folder_uri; uids = message_list_get_selected (message_list); g_return_if_fail (uids->len > 0); - browser = e_mail_browser_new (mail_shell_backend); + browser = e_mail_browser_new (shell_backend); reader = E_MAIL_READER (browser); html_display = e_mail_reader_get_html_display (reader); em_format_set_mode (EM_FORMAT (html_display), EM_FORMAT_SOURCE); @@ -2251,6 +2227,8 @@ e_mail_reader_check_state (EMailReader *reader) can_flag_for_followup = TRUE; } + if (em_utils_check_user_can_send_mail ()) + state |= E_MAIL_READER_HAVE_ACCOUNT; if (uids->len == 1) state |= E_MAIL_READER_SELECTION_SINGLE; if (uids->len > 1) @@ -2284,8 +2262,6 @@ e_mail_reader_check_state (EMailReader *reader) if (has_unread) state |= E_MAIL_READER_SELECTION_HAS_UNREAD; #if 0 /* FIXME */ - if (has_callto_uri) - state |= E_MAIL_READER_SELECTION_HAS_URI_CALLTO; if (has_http_uri) state |= E_MAIL_READER_SELECTION_HAS_URI_HTTP; if (has_mailto_uri) @@ -2318,7 +2294,7 @@ e_mail_reader_update_actions (EMailReader *reader) gboolean enable_flag_clear; gboolean enable_flag_completed; gboolean enable_flag_for_followup; - gboolean single_message_selected; + gboolean have_an_account; gboolean multiple_messages_selected; gboolean selection_has_deleted_messages; gboolean selection_has_important_messages; @@ -2329,6 +2305,7 @@ e_mail_reader_update_actions (EMailReader *reader) gboolean selection_has_unimportant_messages; gboolean selection_has_unread_messages; gboolean selection_is_mailing_list; + gboolean single_message_selected; g_return_if_fail (E_IS_MAIL_READER (reader)); @@ -2342,6 +2319,8 @@ e_mail_reader_update_actions (EMailReader *reader) disable_printing = e_shell_settings_get_boolean ( shell_settings, "disable-printing"); + have_an_account = + (state & E_MAIL_READER_HAVE_ACCOUNT); single_message_selected = (state & E_MAIL_READER_SELECTION_SINGLE); multiple_messages_selected = @@ -2397,22 +2376,22 @@ e_mail_reader_update_actions (EMailReader *reader) gtk_action_set_sensitive (action, sensitive); action_name = "mail-forward"; - sensitive = any_messages_selected; + sensitive = have_an_account && any_messages_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-forward-attached"; - sensitive = any_messages_selected; + sensitive = have_an_account && any_messages_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-forward-inline"; - sensitive = single_message_selected; + sensitive = have_an_account && single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-forward-quoted"; - sensitive = single_message_selected; + sensitive = have_an_account && single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); @@ -2452,7 +2431,12 @@ e_mail_reader_update_actions (EMailReader *reader) gtk_action_set_sensitive (action, sensitive); action_name = "mail-message-edit"; - sensitive = single_message_selected; + sensitive = have_an_account && single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-message-new"; + sensitive = have_an_account; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); @@ -2502,22 +2486,23 @@ e_mail_reader_update_actions (EMailReader *reader) gtk_action_set_sensitive (action, sensitive); action_name = "mail-redirect"; - sensitive = single_message_selected; + sensitive = have_an_account && single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-reply-all"; - sensitive = single_message_selected; + sensitive = have_an_account && single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-reply-list"; - sensitive = single_message_selected && selection_is_mailing_list; + sensitive = have_an_account && single_message_selected && + selection_is_mailing_list; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-reply-sender"; - sensitive = single_message_selected; + sensitive = have_an_account && single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); diff --git a/mail/e-mail-reader.h b/mail/e-mail-reader.h index c55ba92abd..08d6f23e51 100644 --- a/mail/e-mail-reader.h +++ b/mail/e-mail-reader.h @@ -56,22 +56,22 @@ typedef struct _EMailReader EMailReader; typedef struct _EMailReaderIface EMailReaderIface; enum { - E_MAIL_READER_SELECTION_SINGLE = 1 << 0, - E_MAIL_READER_SELECTION_MULTIPLE = 1 << 1, - E_MAIL_READER_SELECTION_CAN_ADD_SENDER = 1 << 2, - E_MAIL_READER_SELECTION_CAN_EDIT = 1 << 3, - E_MAIL_READER_SELECTION_FLAG_CLEAR = 1 << 4, - E_MAIL_READER_SELECTION_FLAG_COMPLETED = 1 << 5, - E_MAIL_READER_SELECTION_FLAG_FOLLOWUP = 1 << 6, - E_MAIL_READER_SELECTION_HAS_DELETED = 1 << 7, - E_MAIL_READER_SELECTION_HAS_IMPORTANT = 1 << 8, - E_MAIL_READER_SELECTION_HAS_JUNK = 1 << 9, - E_MAIL_READER_SELECTION_HAS_NOT_JUNK = 1 << 10, - E_MAIL_READER_SELECTION_HAS_READ = 1 << 11, - E_MAIL_READER_SELECTION_HAS_UNDELETED = 1 << 12, - E_MAIL_READER_SELECTION_HAS_UNIMPORTANT = 1 << 13, - E_MAIL_READER_SELECTION_HAS_UNREAD = 1 << 14, - E_MAIL_READER_SELECTION_HAS_URI_CALLTO = 1 << 15, + E_MAIL_READER_HAVE_ACCOUNT = 1 << 0, + E_MAIL_READER_SELECTION_SINGLE = 1 << 1, + E_MAIL_READER_SELECTION_MULTIPLE = 1 << 2, + E_MAIL_READER_SELECTION_CAN_ADD_SENDER = 1 << 3, + E_MAIL_READER_SELECTION_CAN_EDIT = 1 << 4, + E_MAIL_READER_SELECTION_FLAG_CLEAR = 1 << 5, + E_MAIL_READER_SELECTION_FLAG_COMPLETED = 1 << 6, + E_MAIL_READER_SELECTION_FLAG_FOLLOWUP = 1 << 7, + E_MAIL_READER_SELECTION_HAS_DELETED = 1 << 8, + E_MAIL_READER_SELECTION_HAS_IMPORTANT = 1 << 9, + E_MAIL_READER_SELECTION_HAS_JUNK = 1 << 10, + E_MAIL_READER_SELECTION_HAS_NOT_JUNK = 1 << 11, + E_MAIL_READER_SELECTION_HAS_READ = 1 << 12, + E_MAIL_READER_SELECTION_HAS_UNDELETED = 1 << 13, + E_MAIL_READER_SELECTION_HAS_UNIMPORTANT = 1 << 14, + E_MAIL_READER_SELECTION_HAS_UNREAD = 1 << 15, E_MAIL_READER_SELECTION_HAS_URI_HTTP = 1 << 16, E_MAIL_READER_SELECTION_HAS_URI_MAILTO = 1 << 17, E_MAIL_READER_SELECTION_IS_MAILING_LIST = 1 << 18 diff --git a/mail/e-mail-shell-backend.c b/mail/e-mail-shell-backend.c deleted file mode 100644 index 906312ccff..0000000000 --- a/mail/e-mail-shell-backend.c +++ /dev/null @@ -1,766 +0,0 @@ -/* - * e-mail-shell-backend.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-mail-shell-backend.h" - -#include -#include -#include -#include -#include - -#include "e-util/e-account-utils.h" -#include "e-util/e-binding.h" -#include "e-util/e-import.h" -#include "e-util/e-util.h" -#include "shell/e-shell.h" -#include "shell/e-shell-window.h" -#include "composer/e-msg-composer.h" -#include "widgets/misc/e-preferences-window.h" - -#include "e-mail-shell-migrate.h" -#include "e-mail-shell-settings.h" -#include "e-mail-shell-sidebar.h" -#include "e-mail-shell-view.h" - -#include "e-attachment-handler-mail.h" -#include "e-mail-browser.h" -#include "e-mail-reader.h" -#include "e-mail-store.h" -#include "em-account-prefs.h" -#include "em-composer-prefs.h" -#include "em-composer-utils.h" -#include "em-config.h" -#include "em-event.h" -#include "em-folder-utils.h" -#include "em-format-hook.h" -#include "em-format-html-display.h" -#include "em-junk-hook.h" -#include "em-mailer-prefs.h" -#include "em-network-prefs.h" -#include "em-utils.h" -#include "mail-config.h" -#include "mail-ops.h" -#include "mail-send-recv.h" -#include "mail-session.h" -#include "mail-vfolder.h" -#include "importers/mail-importer.h" - -#define E_MAIL_SHELL_BACKEND_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_MAIL_SHELL_BACKEND, EMailShellBackendPrivate)) - -#define BACKEND_NAME "mail" - -struct _EMailShellBackendPrivate { - gint mail_sync_in_progress; - guint mail_sync_timeout_source_id; -}; - -/* XXX Make this a preprocessor definition. */ -const gchar *x_mailer = "Evolution " VERSION SUB_VERSION " " VERSION_COMMENT; - -static gpointer parent_class; -static GType mail_shell_backend_type; - -/* XXX So many things need the shell backend that it's - * just easier for now to make it globally available. - * We should fix this, though. */ -EMailShellBackend *global_mail_shell_backend = NULL; - -extern gint camel_application_is_exiting; - -static void -mail_shell_backend_init_hooks (void) -{ - e_plugin_hook_register_type (em_config_hook_get_type ()); - e_plugin_hook_register_type (em_event_hook_get_type ()); - e_plugin_hook_register_type (em_junk_hook_get_type ()); - - /* EMFormat classes must be registered before EMFormatHook. */ - em_format_hook_register_type (em_format_get_type ()); - em_format_hook_register_type (em_format_html_get_type ()); - em_format_hook_register_type (em_format_html_display_get_type ()); - e_plugin_hook_register_type (em_format_hook_get_type ()); - - em_junk_hook_register_type (emj_get_type ()); -} - -static void -mail_shell_backend_init_importers (void) -{ - EImportClass *import_class; - EImportImporter *importer; - - import_class = g_type_class_ref (e_import_get_type ()); - - importer = mbox_importer_peek (); - e_import_class_add_importer (import_class, importer, NULL, NULL); - - importer = elm_importer_peek (); - e_import_class_add_importer (import_class, importer, NULL, NULL); - - importer = pine_importer_peek (); - e_import_class_add_importer (import_class, importer, NULL, NULL); -} - -static void -mail_shell_backend_mail_icon_cb (EShellWindow *shell_window, - const gchar *icon_name) -{ - GtkAction *action; - - action = e_shell_window_get_shell_view_action ( - shell_window, BACKEND_NAME); - g_object_set (action, "icon-name", icon_name, NULL); -} - -static void -action_mail_folder_new_cb (GtkAction *action, - EShellWindow *shell_window) -{ - EMFolderTree *folder_tree = NULL; - EMailShellSidebar *mail_shell_sidebar; - EShellSidebar *shell_sidebar; - EShellView *shell_view; - const gchar *view_name; - - /* Take care not to unnecessarily load the mail shell view. */ - view_name = e_shell_window_get_active_view (shell_window); - if (g_strcmp0 (view_name, BACKEND_NAME) != 0) - goto exit; - - shell_view = e_shell_window_get_shell_view (shell_window, view_name); - shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - - mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar); - folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); - -exit: - em_folder_utils_create_folder ( - NULL, folder_tree, GTK_WINDOW (shell_window)); -} - -static void -action_mail_message_new_cb (GtkAction *action, - EShellWindow *shell_window) -{ - GtkWindow *window = GTK_WINDOW (shell_window); - EMailShellSidebar *mail_shell_sidebar; - EShellSidebar *shell_sidebar; - EShellView *shell_view; - EMFolderTree *folder_tree; - const gchar *view_name; - gchar *uri = NULL; - - if (!em_utils_check_user_can_send_mail (window)) - return; - - /* Take care not to unnecessarily load the mail shell view. */ - view_name = e_shell_window_get_active_view (shell_window); - if (g_strcmp0 (view_name, BACKEND_NAME) != 0) - goto exit; - - shell_view = e_shell_window_get_shell_view (shell_window, view_name); - shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - - mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar); - folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); - uri = em_folder_tree_get_selected_uri (folder_tree); - -exit: - em_utils_compose_new_message (uri); - - g_free (uri); -} - -static GtkActionEntry item_entries[] = { - - { "mail-message-new", - "mail-message-new", - NC_("New", "_Mail Message"), - "m", - N_("Compose a new mail message"), - G_CALLBACK (action_mail_message_new_cb) } -}; - -static GtkActionEntry source_entries[] = { - - { "mail-folder-new", - "folder-new", - NC_("New", "Mail _Folder"), - NULL, - N_("Create a new mail folder"), - G_CALLBACK (action_mail_folder_new_cb) } -}; - -static void -mail_shell_backend_init_preferences (EShell *shell) -{ - EAccountList *account_list; - GtkWidget *preferences_window; - - account_list = e_get_account_list (); - preferences_window = e_shell_get_preferences_window (shell); - - e_preferences_window_add_page ( - E_PREFERENCES_WINDOW (preferences_window), - "mail-accounts", - "preferences-mail-accounts", - _("Mail Accounts"), - em_account_prefs_new (account_list), - 100); - - e_preferences_window_add_page ( - E_PREFERENCES_WINDOW (preferences_window), - "mail", - "preferences-mail", - _("Mail Preferences"), - em_mailer_prefs_new (shell), - 300); - - e_preferences_window_add_page ( - E_PREFERENCES_WINDOW (preferences_window), - "composer", - "preferences-composer", - _("Composer Preferences"), - em_composer_prefs_new (shell), - 400); - - e_preferences_window_add_page ( - E_PREFERENCES_WINDOW (preferences_window), - "system-network-proxy", - "preferences-system-network-proxy", - _("Network Preferences"), - em_network_prefs_new (), - 500); -} - -static void -mail_shell_backend_sync_store_done_cb (CamelStore *store, - gpointer user_data) -{ - EMailShellBackend *mail_shell_backend = user_data; - - mail_shell_backend->priv->mail_sync_in_progress--; -} - -static void -mail_shell_backend_sync_store_cb (CamelStore *store, - EMailShellBackend *mail_shell_backend) -{ - if (!camel_application_is_exiting) { - mail_shell_backend->priv->mail_sync_in_progress++; - mail_sync_store ( - store, FALSE, - mail_shell_backend_sync_store_done_cb, - mail_shell_backend); - } -} - -static gboolean -mail_shell_backend_mail_sync (EMailShellBackend *mail_shell_backend) -{ - if (camel_application_is_exiting) - return FALSE; - - if (mail_shell_backend->priv->mail_sync_in_progress) - goto exit; - - if (session == NULL || !camel_session_is_online (session)) - goto exit; - - e_mail_store_foreach ( - (GHFunc) mail_shell_backend_sync_store_cb, - mail_shell_backend); - -exit: - return !camel_application_is_exiting; -} - -static void -mail_shell_backend_notify_online_cb (EShell *shell, - GParamSpec *pspec, - EShellBackend *shell_backend) -{ - gboolean online; - - online = e_shell_get_online (shell); - camel_session_set_online (session, online); -} - -static void -mail_shell_backend_handle_email_uri_cb (gchar *folder_uri, - CamelFolder *folder, - gpointer user_data) -{ - EMailShellBackend *mail_shell_backend = user_data; - CamelURL *url = user_data; - const gchar *forward; - const gchar *reply; - const gchar *uid; - - if (folder == NULL) { - g_warning ("Could not open folder '%s'", folder_uri); - goto exit; - } - - forward = camel_url_get_param (url, "forward"); - reply = camel_url_get_param (url, "reply"); - uid = camel_url_get_param (url, "uid"); - - if (reply != NULL) { - gint mode; - - if (g_strcmp0 (reply, "all") == 0) - mode = REPLY_MODE_ALL; - else if (g_strcmp0 (reply, "list") == 0) - mode = REPLY_MODE_LIST; - else - mode = REPLY_MODE_SENDER; - - em_utils_reply_to_message (folder, uid, NULL, mode, NULL); - - } else if (forward != NULL) { - GPtrArray *uids; - - uids = g_ptr_array_new (); - g_ptr_array_add (uids, g_strdup (uid)); - - if (g_strcmp0 (forward, "attached") == 0) - em_utils_forward_attached (folder, uids, folder_uri); - else if (g_strcmp0 (forward, "inline") == 0) - em_utils_forward_inline (folder, uids, folder_uri); - else if (g_strcmp0 (forward, "quoted") == 0) - em_utils_forward_quoted (folder, uids, folder_uri); - else - em_utils_forward_messages (folder, uids, folder_uri); - - } else { - GtkWidget *browser; - - /* FIXME Should pass in the shell module. */ - browser = e_mail_browser_new (mail_shell_backend); - e_mail_reader_set_folder ( - E_MAIL_READER (browser), folder, folder_uri); - e_mail_reader_set_message ( - E_MAIL_READER (browser), uid, FALSE); - gtk_widget_show (browser); - } - -exit: - camel_url_free (url); -} - -static gboolean -mail_shell_backend_handle_uri_cb (EShell *shell, - const gchar *uri, - EMailShellBackend *mail_shell_backend) -{ - gboolean handled = TRUE; - - if (g_str_has_prefix (uri, "mailto:")) { - if (em_utils_check_user_can_send_mail (NULL)) - em_utils_compose_new_message_with_mailto (uri, NULL); - - } else if (g_str_has_prefix (uri, "email:")) { - CamelURL *url; - - url = camel_url_new (uri, NULL); - if (camel_url_get_param (url, "uid") != NULL) { - gchar *curi = em_uri_to_camel (uri); - - mail_get_folder ( - curi, 0, - mail_shell_backend_handle_email_uri_cb, - mail_shell_backend, mail_msg_unordered_push); - g_free (curi); - - } else { - g_warning ("Email URI's must include a uid parameter"); - camel_url_free (url); - } - } else - handled = FALSE; - - return TRUE; -} - -/* Helper for mail_shell_backend_prepare_for_[off|on]line_cb() */ -static void -mail_shell_store_line_transition_done_cb (CamelStore *store, - gpointer user_data) -{ - EActivity *activity = user_data; - - g_object_unref (activity); -} - -/* Helper for mail_shell_backend_prepare_for_offline_cb() */ -static void -mail_shell_store_prepare_for_offline_cb (CamelService *service, - gpointer unused, - EActivity *activity) -{ - if (CAMEL_IS_DISCO_STORE (service) || CAMEL_IS_OFFLINE_STORE (service)) - mail_store_set_offline ( - CAMEL_STORE (service), TRUE, - mail_shell_store_line_transition_done_cb, - g_object_ref (activity)); -} - -static void -mail_shell_backend_prepare_for_offline_cb (EShell *shell, - EActivity *activity, - EMailShellBackend *mail_shell_backend) -{ - GList *watched_windows; - GtkWidget *parent = NULL; - gboolean synchronize = FALSE; - - watched_windows = e_shell_get_watched_windows (shell); - if (watched_windows != NULL) - parent = GTK_WIDGET (watched_windows->data); - - if (e_shell_get_network_available (shell)) - synchronize = em_utils_prompt_user ( - GTK_WINDOW (parent), - "/apps/evolution/mail/prompts/quick_offline", - "mail:ask-quick-offline", NULL); - - if (!synchronize) { - mail_cancel_all (); - camel_session_set_network_state (session, FALSE); - } - - e_mail_store_foreach ( - (GHFunc) mail_shell_store_prepare_for_offline_cb, activity); -} - -/* Helper for mail_shell_backend_prepare_for_online_cb() */ -static void -mail_shell_store_prepare_for_online_cb (CamelService *service, - gpointer unused, - EActivity *activity) -{ - if (CAMEL_IS_DISCO_STORE (service) || CAMEL_IS_OFFLINE_STORE (service)) - mail_store_set_offline ( - CAMEL_STORE (service), FALSE, - mail_shell_store_line_transition_done_cb, - g_object_ref (activity)); -} - -static void -mail_shell_backend_prepare_for_online_cb (EShell *shell, - EActivity *activity, - EMailShellBackend *mail_shell_backend) -{ - camel_session_set_online (session, TRUE); - - e_mail_store_foreach ( - (GHFunc) mail_shell_store_prepare_for_online_cb, activity); -} - -static void -mail_shell_backend_send_receive_cb (EShell *shell, - GtkWindow *parent, - EShellBackend *shell_backend) -{ - em_utils_clear_get_password_canceled_accounts_flag (); - mail_send_receive (parent); -} - -static void -mail_shell_backend_window_weak_notify_cb (EShell *shell, - GObject *where_the_object_was) -{ - g_signal_handlers_disconnect_by_func ( - shell, mail_shell_backend_mail_icon_cb, - where_the_object_was); -} - -static void -mail_shell_backend_window_created_cb (EShell *shell, - GtkWindow *window, - EShellBackend *shell_backend) -{ - EShellSettings *shell_settings; - static gboolean first_time = TRUE; - const gchar *backend_name; - - shell_settings = e_shell_get_shell_settings (shell); - - /* This applies to both the composer and signature editor. */ - if (GTKHTML_IS_EDITOR (window)) { - GList *spell_languages; - - e_binding_new ( - G_OBJECT (shell_settings), "composer-inline-spelling", - G_OBJECT (window), "inline-spelling"); - - e_binding_new ( - G_OBJECT (shell_settings), "composer-magic-links", - G_OBJECT (window), "magic-links"); - - e_binding_new ( - G_OBJECT (shell_settings), "composer-magic-smileys", - G_OBJECT (window), "magic-smileys"); - - spell_languages = e_load_spell_languages (); - gtkhtml_editor_set_spell_languages ( - GTKHTML_EDITOR (window), spell_languages); - g_list_free (spell_languages); - } - - if (E_IS_MSG_COMPOSER (window)) { - /* Integrate the new composer into the mail module. */ - em_configure_new_composer (E_MSG_COMPOSER (window)); - return; - } - - if (!E_IS_SHELL_WINDOW (window)) - return; - - backend_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name; - - e_shell_window_register_new_item_actions ( - E_SHELL_WINDOW (window), backend_name, - item_entries, G_N_ELEMENTS (item_entries)); - - e_shell_window_register_new_source_actions ( - E_SHELL_WINDOW (window), backend_name, - source_entries, G_N_ELEMENTS (source_entries)); - - g_signal_connect_swapped ( - shell, "event::mail-icon", - G_CALLBACK (mail_shell_backend_mail_icon_cb), window); - - g_object_weak_ref ( - G_OBJECT (window), (GWeakNotify) - mail_shell_backend_window_weak_notify_cb, shell); - - if (first_time) { - g_signal_connect ( - window, "map-event", - G_CALLBACK (e_msg_composer_check_autosave), NULL); - first_time = FALSE; - } -} - -static void -mail_shell_backend_constructed (GObject *object) -{ - EMailShellBackendPrivate *priv; - EShell *shell; - EShellBackend *shell_backend; - const gchar *data_dir; - - priv = E_MAIL_SHELL_BACKEND_GET_PRIVATE (object); - - shell_backend = E_SHELL_BACKEND (object); - shell = e_shell_backend_get_shell (shell_backend); - - /* This also initializes Camel, so it needs to happen early. */ - mail_session_init (E_MAIL_SHELL_BACKEND (shell_backend)); - - mail_shell_backend_init_hooks (); - mail_shell_backend_init_importers (); - - e_attachment_handler_mail_get_type (); - - /* XXX This never gets unreffed. */ - global_mail_shell_backend = g_object_ref (shell_backend); - - g_signal_connect ( - shell, "notify::online", - G_CALLBACK (mail_shell_backend_notify_online_cb), - shell_backend); - - g_signal_connect ( - shell, "handle-uri", - G_CALLBACK (mail_shell_backend_handle_uri_cb), - shell_backend); - - g_signal_connect ( - shell, "prepare-for-offline", - G_CALLBACK (mail_shell_backend_prepare_for_offline_cb), - shell_backend); - - g_signal_connect ( - shell, "prepare-for-online", - G_CALLBACK (mail_shell_backend_prepare_for_online_cb), - shell_backend); - - g_signal_connect ( - shell, "send-receive", - G_CALLBACK (mail_shell_backend_send_receive_cb), - shell_backend); - - g_signal_connect ( - shell, "window-created", - G_CALLBACK (mail_shell_backend_window_created_cb), - shell_backend); - - mail_config_init (); - mail_msg_init (); - - data_dir = e_shell_backend_get_data_dir (shell_backend); - e_mail_store_init (data_dir); - - /* Initialize settings before initializing preferences, - * since the preferences bind to the shell settings. */ - e_mail_shell_settings_init (shell); - mail_shell_backend_init_preferences (shell); -} - -static void -mail_shell_backend_start (EShellBackend *shell_backend) -{ - EMailShellBackendPrivate *priv; - EShell *shell; - EShellSettings *shell_settings; - gboolean enable_search_folders; - - priv = E_MAIL_SHELL_BACKEND_GET_PRIVATE (shell_backend); - - shell = e_shell_backend_get_shell (shell_backend); - shell_settings = e_shell_get_shell_settings (shell); - - /* XXX Do we really still need this flag? */ - mail_session_set_interactive (TRUE); - - enable_search_folders = e_shell_settings_get_boolean ( - shell_settings, "mail-enable-search-folders"); - if (enable_search_folders) - vfolder_load_storage (); - - mail_autoreceive_init (shell_backend, session); - - if (g_getenv ("CAMEL_FLUSH_CHANGES") != NULL) - priv->mail_sync_timeout_source_id = g_timeout_add_seconds ( - mail_config_get_sync_timeout (), - (GSourceFunc) mail_shell_backend_mail_sync, - shell_backend); -} - -static void -mail_shell_backend_class_init (EMailShellBackendClass *class) -{ - GObjectClass *object_class; - EShellBackendClass *shell_backend_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (EMailShellBackendPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->constructed = mail_shell_backend_constructed; - - shell_backend_class = E_SHELL_BACKEND_CLASS (class); - shell_backend_class->shell_view_type = E_TYPE_MAIL_SHELL_VIEW; - shell_backend_class->name = BACKEND_NAME; - shell_backend_class->aliases = ""; - shell_backend_class->schemes = "mailto:email"; - shell_backend_class->sort_order = 200; - shell_backend_class->start = mail_shell_backend_start; - shell_backend_class->is_busy = NULL; - shell_backend_class->shutdown = NULL; - shell_backend_class->migrate = e_mail_shell_migrate; -} - -static void -mail_shell_backend_init (EMailShellBackend *mail_shell_backend) -{ - mail_shell_backend->priv = - E_MAIL_SHELL_BACKEND_GET_PRIVATE (mail_shell_backend); -} - -GType -e_mail_shell_backend_get_type (void) -{ - return mail_shell_backend_type; -} - -void -e_mail_shell_backend_register_type (GTypeModule *type_module) -{ - const GTypeInfo type_info = { - sizeof (EMailShellBackendClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) mail_shell_backend_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (EMailShellBackend), - 0, /* n_preallocs */ - (GInstanceInitFunc) mail_shell_backend_init, - NULL /* value_table */ - }; - - mail_shell_backend_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_BACKEND, - "EMailShellBackend", &type_info, 0); -} - -/******************* Code below here belongs elsewhere. *******************/ - -#include "filter/filter-option.h" -#include "shell/e-shell-settings.h" -#include "mail/e-mail-label-list-store.h" - -GSList * -e_mail_labels_get_filter_options (void) -{ - EShell *shell; - EShellSettings *shell_settings; - EMailLabelListStore *list_store; - GtkTreeModel *model; - GtkTreeIter iter; - GSList *list = NULL; - gboolean valid; - - shell = e_shell_get_default (); - shell_settings = e_shell_get_shell_settings (shell); - list_store = e_shell_settings_get_object ( - shell_settings, "mail-label-list-store"); - - model = GTK_TREE_MODEL (list_store); - valid = gtk_tree_model_get_iter_first (model, &iter); - - while (valid) { - struct _filter_option *option; - gchar *name, *tag; - - name = e_mail_label_list_store_get_name (list_store, &iter); - tag = e_mail_label_list_store_get_tag (list_store, &iter); - - option = g_new0 (struct _filter_option, 1); - option->title = e_str_without_underscores (name); - option->value = tag; /* takes ownership */ - - g_free (name); - - valid = gtk_tree_model_iter_next (model, &iter); - } - - g_object_unref (list_store); - - return list; -} diff --git a/mail/e-mail-shell-backend.h b/mail/e-mail-shell-backend.h deleted file mode 100644 index 4bc1a36706..0000000000 --- a/mail/e-mail-shell-backend.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * e-mail-shell-backend.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_MAIL_SHELL_BACKEND_H -#define E_MAIL_SHELL_BACKEND_H - -#include - -#include -#include -#include -#include - -/* Standard GObject macros */ -#define E_TYPE_MAIL_SHELL_BACKEND \ - (e_mail_shell_backend_get_type ()) -#define E_MAIL_SHELL_BACKEND(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_MAIL_SHELL_BACKEND, EMailShellBackend)) -#define E_MAIL_SHELL_BACKEND_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_MAIL_SHELL_BACKEND, EMailShellBackendClass)) -#define E_IS_MAIL_SHELL_BACKEND(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_MAIL_SHELL_BACKEND)) -#define E_IS_MAIL_SHELL_BACKEND_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_MAIL_SHELL_BACKEND)) -#define E_MAIL_SHELL_BACKEND_GET_CLASS(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_MAIL_SHELL_BACKEND, EMailShellBackendClass)) - -G_BEGIN_DECLS - -typedef struct _EMailShellBackend EMailShellBackend; -typedef struct _EMailShellBackendClass EMailShellBackendClass; -typedef struct _EMailShellBackendPrivate EMailShellBackendPrivate; - -struct _EMailShellBackend { - EShellBackend parent; - EMailShellBackendPrivate *priv; -}; - -struct _EMailShellBackendClass { - EShellBackendClass parent_class; -}; - -/* Globally available shell backend. - * - * XXX I don't like having this globally available but passing it around - * to all the various utilities that need to access the backend's data - * directory is too much of a pain for now. */ -extern EMailShellBackend *global_mail_shell_backend; - -GType e_mail_shell_backend_get_type (void); -void e_mail_shell_backend_register_type - (GTypeModule *type_module); - -/* XXX Find a better place for this function. */ -GSList * e_mail_labels_get_filter_options(void); - -G_END_DECLS - -#endif /* E_MAIL_SHELL_BACKEND_H */ diff --git a/mail/e-mail-shell-content.c b/mail/e-mail-shell-content.c deleted file mode 100644 index b801093116..0000000000 --- a/mail/e-mail-shell-content.c +++ /dev/null @@ -1,1053 +0,0 @@ -/* - * e-mail-shell-content.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-mail-shell-content.h" - -#include -#include -#include - -#include "e-util/gconf-bridge.h" -#include "widgets/menus/gal-view-etable.h" -#include "widgets/menus/gal-view-instance.h" - -#include "em-search-context.h" -#include "em-utils.h" -#include "mail-config.h" -#include "mail-ops.h" - -#include "e-mail-reader.h" -#include "e-mail-search-bar.h" -#include "e-mail-shell-backend.h" -#include "e-mail-shell-view-actions.h" - -#define E_MAIL_SHELL_CONTENT_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_MAIL_SHELL_CONTENT, EMailShellContentPrivate)) - -#define STATE_KEY_SCROLLBAR_POSITION "ScrollbarPosition" -#define STATE_KEY_SELECTED_MESSAGE "SelectedMessage" - -struct _EMailShellContentPrivate { - GtkWidget *paned; - GtkWidget *message_list; - GtkWidget *search_bar; - - EMFormatHTMLDisplay *html_display; - GalViewInstance *view_instance; - - /* ETable scrolling hack */ - gdouble default_scrollbar_position; - - guint paned_binding_id; - guint scroll_timeout_id; - - /* Signal handler IDs */ - guint message_list_built_id; - guint message_list_scrolled_id; - - guint preview_visible : 1; - guint suppress_message_selection : 1; - guint vertical_view : 1; - guint show_deleted : 1; -}; - -enum { - PROP_0, - PROP_PREVIEW_VISIBLE, - PROP_SHOW_DELETED, - PROP_VERTICAL_VIEW -}; - -static gpointer parent_class; -static GType mail_shell_content_type; - -static void -mail_shell_content_etree_unfreeze (MessageList *message_list, - GdkEvent *event) -{ - ETableItem *item; - GObject *object; - - item = e_tree_get_item (message_list->tree); - object = G_OBJECT (((GnomeCanvasItem *) item)->canvas); - - g_object_set_data (object, "freeze-cursor", 0); -} - -static void -mail_shell_content_message_list_scrolled_cb (EMailShellContent *mail_shell_content, - MessageList *message_list) -{ - EShellContent *shell_content; - EShellView *shell_view; - GKeyFile *key_file; - const gchar *folder_uri; - const gchar *key; - gchar *group_name; - gdouble position; - - /* Save the scrollbar position for the current folder. */ - - folder_uri = message_list->folder_uri; - - if (folder_uri == NULL) - return; - - shell_content = E_SHELL_CONTENT (mail_shell_content); - shell_view = e_shell_content_get_shell_view (shell_content); - key_file = e_shell_view_get_state_key_file (shell_view); - - key = STATE_KEY_SCROLLBAR_POSITION; - group_name = g_strdup_printf ("Folder %s", folder_uri); - position = message_list_get_scrollbar_position (message_list); - - g_key_file_set_double (key_file, group_name, key, position); - e_shell_view_set_state_dirty (shell_view); - - g_free (group_name); -} - -static gboolean -mail_shell_content_scroll_timeout_cb (EMailShellContent *mail_shell_content) -{ - EMailShellContentPrivate *priv = mail_shell_content->priv; - EShellContent *shell_content; - EShellView *shell_view; - MessageList *message_list; - EMailReader *reader; - GKeyFile *key_file; - const gchar *folder_uri; - const gchar *key; - gchar *group_name; - - /* Initialize the scrollbar position for the current folder - * and setup a callback to handle scrollbar position changes. */ - - shell_content = E_SHELL_CONTENT (mail_shell_content); - shell_view = e_shell_content_get_shell_view (shell_content); - key_file = e_shell_view_get_state_key_file (shell_view); - - reader = E_MAIL_READER (mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - folder_uri = message_list->folder_uri; - - if (folder_uri == NULL) - goto skip; - - /* Restore the message list scrollbar position. */ - - key = STATE_KEY_SCROLLBAR_POSITION; - group_name = g_strdup_printf ("Folder %s", folder_uri); - - if (g_key_file_has_key (key_file, group_name, key, NULL)) { - gdouble position; - - position = g_key_file_get_double ( - key_file, group_name, key, NULL); - message_list_set_scrollbar_position (message_list, position); - } - - g_free (group_name); - -skip: - priv->message_list_scrolled_id = g_signal_connect_swapped ( - message_list, "message-list-scrolled", - G_CALLBACK (mail_shell_content_message_list_scrolled_cb), - mail_shell_content); - - priv->scroll_timeout_id = 0; - - return FALSE; -} - -static void -mail_shell_content_message_list_built_cb (EMailShellContent *mail_shell_content, - MessageList *message_list) -{ - EMailShellContentPrivate *priv = mail_shell_content->priv; - EShellContent *shell_content; - EShellView *shell_view; - GtkScrolledWindow *scrolled_window; - GtkWidget *vscrollbar; - GKeyFile *key_file; - gchar *uid; - - g_signal_handler_disconnect ( - message_list, priv->message_list_built_id); - priv->message_list_built_id = 0; - - shell_content = E_SHELL_CONTENT (mail_shell_content); - shell_view = e_shell_content_get_shell_view (shell_content); - key_file = e_shell_view_get_state_key_file (shell_view); - - if (message_list->cursor_uid != NULL) - uid = NULL; - - else if (message_list->folder_uri == NULL) - uid = NULL; - - else if (mail_shell_content->priv->suppress_message_selection) - uid = NULL; - - else { - const gchar *folder_uri; - const gchar *key; - gchar *group_name; - - key = STATE_KEY_SELECTED_MESSAGE; - folder_uri = message_list->folder_uri; - group_name = g_strdup_printf ("Folder %s", folder_uri); - uid = g_key_file_get_string (key_file, group_name, key, NULL); - g_free (group_name); - } - - if (uid != NULL) { - CamelFolder *folder; - CamelMessageInfo *info; - - folder = message_list->folder; - info = camel_folder_get_message_info (folder, uid); - if (info != NULL) { - EMailReader *reader; - - reader = E_MAIL_READER (mail_shell_content); - e_mail_reader_set_message (reader, uid, TRUE); - camel_folder_free_message_info (folder, info); - } - - g_free (uid); - } - - /* FIXME This is a gross workaround for an ETable bug that I can't - * fix (Ximian bug #55303). - * - * Since e_canvas_item_region_show_relay() uses a timeout, - * we have to use a timeout of the same interval but a lower - * priority. */ - priv->scroll_timeout_id = g_timeout_add_full ( - G_PRIORITY_LOW, 250, (GSourceFunc) - mail_shell_content_scroll_timeout_cb, - mail_shell_content, NULL); - - /* FIXME This is another ugly hack to hide a side-effect of the - * previous workaround. */ - scrolled_window = GTK_SCROLLED_WINDOW (message_list); - vscrollbar = gtk_scrolled_window_get_vscrollbar (scrolled_window); - g_signal_connect_swapped ( - vscrollbar, "button-press-event", - G_CALLBACK (mail_shell_content_etree_unfreeze), - message_list); -} - -static void -mail_shell_content_display_view_cb (EMailShellContent *mail_shell_content, - GalView *gal_view) -{ - EMailReader *reader; - MessageList *message_list; - - reader = E_MAIL_READER (mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - - if (GAL_IS_VIEW_ETABLE (gal_view)) - gal_view_etable_attach_tree ( - GAL_VIEW_ETABLE (gal_view), message_list->tree); -} - -static void -mail_shell_content_message_selected_cb (EMailShellContent *mail_shell_content, - const gchar *message_uid, - MessageList *message_list) -{ - EShellContent *shell_content; - EShellView *shell_view; - GKeyFile *key_file; - const gchar *folder_uri; - const gchar *key; - gchar *group_name; - - folder_uri = message_list->folder_uri; - - /* This also gets triggered when selecting a store name on - * the sidebar such as "On This Computer", in which case - * 'folder_uri' will be NULL. */ - if (folder_uri == NULL) - return; - - shell_content = E_SHELL_CONTENT (mail_shell_content); - shell_view = e_shell_content_get_shell_view (shell_content); - key_file = e_shell_view_get_state_key_file (shell_view); - - key = STATE_KEY_SELECTED_MESSAGE; - group_name = g_strdup_printf ("Folder %s", folder_uri); - - if (message_uid != NULL) - g_key_file_set_string (key_file, group_name, key, message_uid); - else - g_key_file_remove_key (key_file, group_name, key, NULL); - e_shell_view_set_state_dirty (shell_view); - - g_free (group_name); -} - -static void -mail_shell_content_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_PREVIEW_VISIBLE: - e_mail_shell_content_set_preview_visible ( - E_MAIL_SHELL_CONTENT (object), - g_value_get_boolean (value)); - return; - - case PROP_SHOW_DELETED: - e_mail_shell_content_set_show_deleted ( - E_MAIL_SHELL_CONTENT (object), - g_value_get_boolean (value)); - return; - - case PROP_VERTICAL_VIEW: - e_mail_shell_content_set_vertical_view ( - E_MAIL_SHELL_CONTENT (object), - g_value_get_boolean (value)); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -mail_shell_content_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_PREVIEW_VISIBLE: - g_value_set_boolean ( - value, - e_mail_shell_content_get_preview_visible ( - E_MAIL_SHELL_CONTENT (object))); - return; - - case PROP_SHOW_DELETED: - g_value_set_boolean ( - value, - e_mail_shell_content_get_show_deleted ( - E_MAIL_SHELL_CONTENT (object))); - return; - - case PROP_VERTICAL_VIEW: - g_value_set_boolean ( - value, - e_mail_shell_content_get_vertical_view ( - E_MAIL_SHELL_CONTENT (object))); - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -mail_shell_content_dispose (GObject *object) -{ - EMailShellContentPrivate *priv; - - priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (object); - - if (priv->paned != NULL) { - g_object_unref (priv->paned); - priv->paned = NULL; - } - - if (priv->message_list != NULL) { - g_object_unref (priv->message_list); - priv->message_list = NULL; - } - - if (priv->search_bar != NULL) { - g_object_unref (priv->search_bar); - priv->search_bar = NULL; - } - - if (priv->html_display != NULL) { - g_object_unref (priv->html_display); - priv->html_display = NULL; - } - - if (priv->view_instance != NULL) { - g_object_unref (priv->view_instance); - priv->view_instance = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -mail_shell_content_constructed (GObject *object) -{ - EMailShellContentPrivate *priv; - EShellContent *shell_content; - EShellBackend *shell_backend; - EShellView *shell_view; - EShellViewClass *shell_view_class; - EMailReader *reader; - MessageList *message_list; - GConfBridge *bridge; - GtkWidget *container; - GtkWidget *widget; - GtkHTML *html; - GalViewCollection *view_collection; - const gchar *key; - - priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (object); - priv->html_display = em_format_html_display_new (); - - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (parent_class)->constructed (object); - - shell_content = E_SHELL_CONTENT (object); - shell_view = e_shell_content_get_shell_view (shell_content); - shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); - shell_backend = e_shell_view_get_shell_backend (shell_view); - view_collection = shell_view_class->view_collection; - - html = EM_FORMAT_HTML (priv->html_display)->html; - - /* Build content widgets. */ - - container = GTK_WIDGET (object); - - widget = gtk_vpaned_new (); - gtk_container_add (GTK_CONTAINER (container), widget); - priv->paned = g_object_ref (widget); - gtk_widget_show (widget); - - container = widget; - - widget = message_list_new (shell_backend); - gtk_paned_add1 (GTK_PANED (container), widget); - priv->message_list = g_object_ref (widget); - gtk_widget_show (widget); - - widget = gtk_vbox_new (FALSE, 1); - gtk_paned_add2 (GTK_PANED (container), widget); - gtk_widget_show (widget); - - container = widget; - - widget = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy ( - GTK_SCROLLED_WINDOW (widget), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type ( - GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); - gtk_container_add (GTK_CONTAINER (widget), GTK_WIDGET (html)); - gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); - gtk_widget_show (GTK_WIDGET (html)); - gtk_widget_show (widget); - - widget = e_mail_search_bar_new (html); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - priv->search_bar = g_object_ref (widget); - gtk_widget_hide (widget); - - g_signal_connect_swapped ( - widget, "changed", - G_CALLBACK (em_format_redraw), priv->html_display); - - /* Load the view instance. */ - - e_mail_shell_content_update_view_instance ( - E_MAIL_SHELL_CONTENT (shell_content)); - - /* Bind GObject properties to GConf keys. */ - - bridge = gconf_bridge_get (); - - object = G_OBJECT (priv->paned); - key = "/apps/evolution/mail/display/paned_size"; - gconf_bridge_bind_property_delayed (bridge, key, object, "position"); - - object = G_OBJECT (shell_content); - key = "/apps/evolution/mail/display/show_deleted"; - gconf_bridge_bind_property (bridge, key, object, "show-deleted"); - - /* Message list customizations. */ - - reader = E_MAIL_READER (shell_content); - message_list = e_mail_reader_get_message_list (reader); - - g_signal_connect_swapped ( - message_list, "message-selected", - G_CALLBACK (mail_shell_content_message_selected_cb), - shell_content); -} - -static guint32 -mail_shell_content_check_state (EShellContent *shell_content) -{ - return e_mail_reader_check_state (E_MAIL_READER (shell_content)); -} - -static GtkActionGroup * -mail_shell_content_get_action_group (EMailReader *reader) -{ - EShellContent *shell_content; - EShellWindow *shell_window; - EShellView *shell_view; - - shell_content = E_SHELL_CONTENT (reader); - shell_view = e_shell_content_get_shell_view (shell_content); - shell_window = e_shell_view_get_shell_window (shell_view); - - return E_SHELL_WINDOW_ACTION_GROUP_MAIL (shell_window); -} - -static gboolean -mail_shell_content_get_hide_deleted (EMailReader *reader) -{ - EMailShellContent *mail_shell_content; - - mail_shell_content = E_MAIL_SHELL_CONTENT (reader); - - return !e_mail_shell_content_get_show_deleted (mail_shell_content); -} - -static EMFormatHTMLDisplay * -mail_shell_content_get_html_display (EMailReader *reader) -{ - EMailShellContentPrivate *priv; - - priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (reader); - - return priv->html_display; -} - -static MessageList * -mail_shell_content_get_message_list (EMailReader *reader) -{ - EMailShellContentPrivate *priv; - - priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (reader); - - return MESSAGE_LIST (priv->message_list); -} - -static EShellBackend * -mail_shell_content_get_shell_backend (EMailReader *reader) -{ - EShellContent *shell_content; - EShellView *shell_view; - - shell_content = E_SHELL_CONTENT (reader); - shell_view = e_shell_content_get_shell_view (shell_content); - - return e_shell_view_get_shell_backend (shell_view); -} - -static GtkWindow * -mail_shell_content_get_window (EMailReader *reader) -{ - EShellContent *shell_content; - EShellWindow *shell_window; - EShellView *shell_view; - - shell_content = E_SHELL_CONTENT (reader); - shell_view = e_shell_content_get_shell_view (shell_content); - shell_window = e_shell_view_get_shell_window (shell_view); - - return GTK_WINDOW (shell_window); -} - -static void -mail_shell_content_set_folder (EMailReader *reader, - CamelFolder *folder, - const gchar *folder_uri) -{ - EMailShellContentPrivate *priv; - EMailReaderIface *default_iface; - MessageList *message_list; - gboolean different_folder; - - priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (reader); - - message_list = e_mail_reader_get_message_list (reader); - - message_list_freeze (message_list); - - different_folder = - message_list->folder != NULL && - folder != message_list->folder; - - /* Chain up to interface's default set_folder() method. */ - default_iface = g_type_default_interface_peek (E_TYPE_MAIL_READER); - default_iface->set_folder (reader, folder, folder_uri); - - if (folder == NULL) - goto exit; - - mail_refresh_folder (folder, NULL, NULL); - - /* This function gets triggered several times at startup, - * so we don't want to reset the message suppression state - * unless we're actually switching to a different folder. */ - if (different_folder) - priv->suppress_message_selection = FALSE; - - /* This is a one-time-only callback. */ - if (message_list->cursor_uid == NULL && priv->message_list_built_id == 0) - priv->message_list_built_id = g_signal_connect_swapped ( - message_list, "message-list-built", - G_CALLBACK (mail_shell_content_message_list_built_cb), - reader); - -exit: - message_list_thaw (message_list); -} - -static void -mail_shell_content_show_search_bar (EMailReader *reader) -{ - EMailShellContentPrivate *priv; - - priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (reader); - - gtk_widget_show (priv->search_bar); -} - -static void -mail_shell_content_class_init (EMailShellContentClass *class) -{ - GObjectClass *object_class; - EShellContentClass *shell_content_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (EMailShellContentPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->set_property = mail_shell_content_set_property; - object_class->get_property = mail_shell_content_get_property; - object_class->dispose = mail_shell_content_dispose; - object_class->constructed = mail_shell_content_constructed; - - shell_content_class = E_SHELL_CONTENT_CLASS (class); - shell_content_class->new_search_context = em_search_context_new; - shell_content_class->check_state = mail_shell_content_check_state; - - g_object_class_install_property ( - object_class, - PROP_PREVIEW_VISIBLE, - g_param_spec_boolean ( - "preview-visible", - _("Preview is Visible"), - _("Whether the preview pane is visible"), - TRUE, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_SHOW_DELETED, - g_param_spec_boolean ( - "show-deleted", - "Show Deleted", - NULL, - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_VERTICAL_VIEW, - g_param_spec_boolean ( - "vertical-view", - _("Vertical View"), - _("Whether vertical view is enabled"), - FALSE, - G_PARAM_READWRITE)); -} - -static void -mail_shell_content_iface_init (EMailReaderIface *iface) -{ - iface->get_action_group = mail_shell_content_get_action_group; - iface->get_hide_deleted = mail_shell_content_get_hide_deleted; - iface->get_html_display = mail_shell_content_get_html_display; - iface->get_message_list = mail_shell_content_get_message_list; - iface->get_shell_backend = mail_shell_content_get_shell_backend; - iface->get_window = mail_shell_content_get_window; - iface->set_folder = mail_shell_content_set_folder; - iface->show_search_bar = mail_shell_content_show_search_bar; -} - -static void -mail_shell_content_init (EMailShellContent *mail_shell_content) -{ - mail_shell_content->priv = - E_MAIL_SHELL_CONTENT_GET_PRIVATE (mail_shell_content); - - mail_shell_content->priv->preview_visible = TRUE; - - /* Postpone widget construction until we have a shell view. */ -} - -GType -e_mail_shell_content_get_type (void) -{ - return mail_shell_content_type; -} - -void -e_mail_shell_content_register_type (GTypeModule *type_module) -{ - static const GTypeInfo type_info = { - sizeof (EMailShellContentClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) mail_shell_content_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (EMailShellContent), - 0, /* n_preallocs */ - (GInstanceInitFunc) mail_shell_content_init, - NULL /* value_table */ - }; - - static const GInterfaceInfo iface_info = { - (GInterfaceInitFunc) mail_shell_content_iface_init, - (GInterfaceFinalizeFunc) NULL, - NULL /* interface_data */ - }; - - mail_shell_content_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_CONTENT, - "EMailShellContent", &type_info, 0); - - g_type_module_add_interface ( - type_module, mail_shell_content_type, - E_TYPE_MAIL_READER, &iface_info); -} - -GtkWidget * -e_mail_shell_content_new (EShellView *shell_view) -{ - g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - - return g_object_new ( - E_TYPE_MAIL_SHELL_CONTENT, - "shell-view", shell_view, NULL); -} - -gboolean -e_mail_shell_content_get_preview_visible (EMailShellContent *mail_shell_content) -{ - g_return_val_if_fail ( - E_IS_MAIL_SHELL_CONTENT (mail_shell_content), FALSE); - - return mail_shell_content->priv->preview_visible; -} - -void -e_mail_shell_content_set_preview_visible (EMailShellContent *mail_shell_content, - gboolean preview_visible) -{ - GtkPaned *paned; - GtkWidget *child; - - g_return_if_fail (E_IS_MAIL_SHELL_CONTENT (mail_shell_content)); - - if (preview_visible == mail_shell_content->priv->preview_visible) - return; - - paned = GTK_PANED (mail_shell_content->priv->paned); - child = gtk_paned_get_child2 (paned); - - if (preview_visible) - gtk_widget_show (child); - else - gtk_widget_hide (child); - - mail_shell_content->priv->preview_visible = preview_visible; - - g_object_notify (G_OBJECT (mail_shell_content), "preview-visible"); -} - -gboolean -e_mail_shell_content_get_show_deleted (EMailShellContent *mail_shell_content) -{ - g_return_val_if_fail ( - E_IS_MAIL_SHELL_CONTENT (mail_shell_content), FALSE); - - return mail_shell_content->priv->show_deleted; -} - -void -e_mail_shell_content_set_show_deleted (EMailShellContent *mail_shell_content, - gboolean show_deleted) -{ - g_return_if_fail (E_IS_MAIL_SHELL_CONTENT (mail_shell_content)); - - mail_shell_content->priv->show_deleted = show_deleted; - - g_object_notify (G_OBJECT (mail_shell_content), "show-deleted"); -} - -gboolean -e_mail_shell_content_get_vertical_view (EMailShellContent *mail_shell_content) -{ - g_return_val_if_fail ( - E_IS_MAIL_SHELL_CONTENT (mail_shell_content), FALSE); - - return mail_shell_content->priv->vertical_view; -} - -void -e_mail_shell_content_set_vertical_view (EMailShellContent *mail_shell_content, - gboolean vertical_view) -{ - GConfBridge *bridge; - GtkWidget *old_paned; - GtkWidget *new_paned; - GtkWidget *child1; - GtkWidget *child2; - guint binding_id; - const gchar *key; - - g_return_if_fail (E_IS_MAIL_SHELL_CONTENT (mail_shell_content)); - - if (vertical_view == mail_shell_content->priv->vertical_view) - return; - - bridge = gconf_bridge_get (); - old_paned = mail_shell_content->priv->paned; - binding_id = mail_shell_content->priv->paned_binding_id; - - child1 = gtk_paned_get_child1 (GTK_PANED (old_paned)); - child2 = gtk_paned_get_child2 (GTK_PANED (old_paned)); - - if (binding_id > 0) - gconf_bridge_unbind (bridge, binding_id); - - if (vertical_view) { - new_paned = gtk_hpaned_new (); - key = "/apps/evolution/mail/display/hpaned_size"; - } else { - new_paned = gtk_vpaned_new (); - key = "/apps/evolution/mail/display/paned_size"; - } - - gtk_widget_reparent (child1, new_paned); - gtk_widget_reparent (child2, new_paned); - gtk_widget_show (new_paned); - - gtk_widget_destroy (old_paned); - gtk_container_add (GTK_CONTAINER (mail_shell_content), new_paned); - - binding_id = gconf_bridge_bind_property_delayed ( - bridge, key, G_OBJECT (new_paned), "position"); - - mail_shell_content->priv->vertical_view = vertical_view; - mail_shell_content->priv->paned_binding_id = binding_id; - mail_shell_content->priv->paned = g_object_ref (new_paned); - - e_mail_shell_content_update_view_instance (mail_shell_content); - - g_object_notify (G_OBJECT (mail_shell_content), "vertical-view"); -} - -GalViewInstance * -e_mail_shell_content_get_view_instance (EMailShellContent *mail_shell_content) -{ - g_return_val_if_fail ( - E_IS_MAIL_SHELL_CONTENT (mail_shell_content), NULL); - - return mail_shell_content->priv->view_instance; -} - -void -e_mail_shell_content_set_search_strings (EMailShellContent *mail_shell_content, - GSList *search_strings) -{ - EMailSearchBar *search_bar; - ESearchingTokenizer *tokenizer; - - g_return_if_fail (E_IS_MAIL_SHELL_CONTENT (mail_shell_content)); - - search_bar = E_MAIL_SEARCH_BAR (mail_shell_content->priv->search_bar); - tokenizer = e_mail_search_bar_get_tokenizer (search_bar); - - e_searching_tokenizer_set_secondary_case_sensitivity (tokenizer, FALSE); - e_searching_tokenizer_set_secondary_search_string (tokenizer, NULL); - - while (search_strings != NULL) { - e_searching_tokenizer_add_secondary_search_string ( - tokenizer, search_strings->data); - search_strings = g_slist_next (search_strings); - } - - e_mail_search_bar_changed (search_bar); -} - -void -e_mail_shell_content_update_view_instance (EMailShellContent *mail_shell_content) -{ - EMailReader *reader; - EShellContent *shell_content; - EShellView *shell_view; - EShellViewClass *shell_view_class; - GalViewCollection *view_collection; - GalViewInstance *view_instance; - MessageList *message_list; - gboolean outgoing_folder; - gboolean show_vertical_view; - gchar *view_id; - - g_return_if_fail (E_IS_MAIL_SHELL_CONTENT (mail_shell_content)); - - shell_content = E_SHELL_CONTENT (mail_shell_content); - shell_view = e_shell_content_get_shell_view (shell_content); - shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); - view_collection = shell_view_class->view_collection; - - reader = E_MAIL_READER (mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - - /* If no folder is selected, return silently. */ - if (message_list->folder == NULL) - return; - - /* If we have a folder, we should also have a URI. */ - g_return_if_fail (message_list->folder_uri != NULL); - - if (mail_shell_content->priv->view_instance != NULL) { - g_object_unref (mail_shell_content->priv->view_instance); - mail_shell_content->priv->view_instance = NULL; - } - - view_id = mail_config_folder_to_safe_url (message_list->folder); - view_instance = e_shell_view_new_view_instance (shell_view, view_id); - mail_shell_content->priv->view_instance = view_instance; - - show_vertical_view = - e_mail_shell_content_get_vertical_view (mail_shell_content); - - if (show_vertical_view) { - gchar *filename; - gchar *safe_view_id; - - /* Force the view instance into vertical view. */ - - g_free (view_instance->custom_filename); - g_free (view_instance->current_view_filename); - - safe_view_id = g_strdup (view_id); - e_filename_make_safe (safe_view_id); - - filename = g_strdup_printf ( - "custom_wide_view-%s.xml", safe_view_id); - view_instance->custom_filename = g_build_filename ( - view_collection->local_dir, filename, NULL); - g_free (filename); - - filename = g_strdup_printf ( - "current_wide_view-%s.xml", safe_view_id); - view_instance->current_view_filename = g_build_filename ( - view_collection->local_dir, filename, NULL); - g_free (filename); - - g_free (safe_view_id); - } - - g_free (view_id); - - outgoing_folder = - em_utils_folder_is_drafts ( - message_list->folder, message_list->folder_uri) || - em_utils_folder_is_outbox ( - message_list->folder, message_list->folder_uri) || - em_utils_folder_is_sent ( - message_list->folder, message_list->folder_uri); - - if (outgoing_folder) { - if (show_vertical_view) - gal_view_instance_set_default_view ( - view_instance, "Wide_View_Sent"); - else - gal_view_instance_set_default_view ( - view_instance, "As_Sent_Folder"); - } else if (show_vertical_view) { - gal_view_instance_set_default_view ( - view_instance, "Wide_View_Normal"); - } - - gal_view_instance_load (view_instance); - - if (!gal_view_instance_exists (view_instance)) { - gchar *state_filename; - - state_filename = mail_config_folder_to_cachename ( - message_list->folder, "et-header-"); - - if (g_file_test (state_filename, G_FILE_TEST_IS_REGULAR)) { - ETableSpecification *spec; - ETableState *state; - GalView *view; - gchar *spec_filename; - - spec = e_table_specification_new (); - spec_filename = g_build_filename ( - EVOLUTION_ETSPECDIR, - "message-list.etspec", - NULL); - e_table_specification_load_from_file ( - spec, spec_filename); - g_free (spec_filename); - - state = e_table_state_new (); - view = gal_view_etable_new (spec, ""); - - e_table_state_load_from_file ( - state, state_filename); - gal_view_etable_set_state ( - GAL_VIEW_ETABLE (view), state); - gal_view_instance_set_custom_view ( - view_instance, view); - - g_object_unref (state); - g_object_unref (view); - g_object_unref (spec); - } - - g_free (state_filename); - } - - g_signal_connect ( - view_instance, "display-view", - G_CALLBACK (mail_shell_content_display_view_cb), - mail_shell_content); - - mail_shell_content_display_view_cb ( - mail_shell_content, - gal_view_instance_get_current_view (view_instance)); -} diff --git a/mail/e-mail-shell-content.h b/mail/e-mail-shell-content.h deleted file mode 100644 index 57d2438705..0000000000 --- a/mail/e-mail-shell-content.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * e-mail-shell-content.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_MAIL_SHELL_CONTENT_H -#define E_MAIL_SHELL_CONTENT_H - -#include -#include - -#include - -/* Standard GObject macros */ -#define E_TYPE_MAIL_SHELL_CONTENT \ - (e_mail_shell_content_get_type ()) -#define E_MAIL_SHELL_CONTENT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_MAIL_SHELL_CONTENT, EMailShellContent)) -#define E_MAIL_SHELL_CONTENT_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_MAIL_SHELL_CONTENT, EMailShellContentClass)) -#define E_IS_MAIL_SHELL_CONTENT(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_MAIL_SHELL_CONTENT)) -#define E_IS_MAIL_SHELL_CONTENT_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_MAIL_SHELL_CONTENT)) -#define E_MAIL_SHELL_CONTENT_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_MAIL_SHELL_CONTENT, EMailShellContentClass)) - -G_BEGIN_DECLS - -typedef struct _EMailShellContent EMailShellContent; -typedef struct _EMailShellContentClass EMailShellContentClass; -typedef struct _EMailShellContentPrivate EMailShellContentPrivate; - -struct _EMailShellContent { - EShellContent parent; - EMailShellContentPrivate *priv; -}; - -struct _EMailShellContentClass { - EShellContentClass parent_class; -}; - -GType e_mail_shell_content_get_type (void); -void e_mail_shell_content_register_type - (GTypeModule *type_module); -GtkWidget * e_mail_shell_content_new(EShellView *shell_view); -gboolean e_mail_shell_content_get_preview_visible - (EMailShellContent *mail_shell_content); -void e_mail_shell_content_set_preview_visible - (EMailShellContent *mail_shell_content, - gboolean preview_visible); -gboolean e_mail_shell_content_get_show_deleted - (EMailShellContent *mail_shell_content); -void e_mail_shell_content_set_show_deleted - (EMailShellContent *mail_shell_content, - gboolean show_deleted); -gboolean e_mail_shell_content_get_vertical_view - (EMailShellContent *mail_shell_content); -void e_mail_shell_content_set_vertical_view - (EMailShellContent *mail_shell_content, - gboolean vertical_view); -GalViewInstance * - e_mail_shell_content_get_view_instance - (EMailShellContent *mail_shell_content); -void e_mail_shell_content_set_search_strings - (EMailShellContent *mail_shell_content, - GSList *search_strings); -void e_mail_shell_content_update_view_instance - (EMailShellContent *mail_shell_content); - -G_END_DECLS - -#endif /* E_MAIL_SHELL_CONTENT_H */ diff --git a/mail/e-mail-shell-migrate.c b/mail/e-mail-shell-migrate.c deleted file mode 100644 index 2158580bf9..0000000000 --- a/mail/e-mail-shell-migrate.c +++ /dev/null @@ -1,3104 +0,0 @@ -/* - * e-mail-shell-migrate.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-mail-shell-migrate.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "e-util/e-account-utils.h" -#include "e-util/e-bconf-map.h" -#include "e-util/e-error.h" -#include "e-util/e-util-private.h" -#include "e-util/e-plugin.h" -#include "e-util/e-signature-utils.h" - -#include "e-mail-shell-backend.h" -#include "shell/e-shell-migrate.h" - -#include "e-mail-store.h" -#include "mail-config.h" -#include "em-utils.h" - -#define d(x) x - -#ifndef G_OS_WIN32 -/* No versions previous to 2.8 or thereabouts have been available on - * Windows, so don't bother with upgrade support from earlier versions - * on Win32. Do try to support upgrades from 2.12 and later to the - * current version. - */ - -/* upgrade helper functions */ -static xmlDocPtr -emm_load_xml (const gchar *dirname, const gchar *filename) -{ - xmlDocPtr doc; - struct stat st; - gchar *path; - - path = g_strdup_printf ("%s/%s", dirname, filename); - if (stat (path, &st) == -1 || !(doc = xmlParseFile (path))) { - g_free (path); - return NULL; - } - - g_free (path); - - return doc; -} - -static gint -emm_save_xml (xmlDocPtr doc, const gchar *dirname, const gchar *filename) -{ - gchar *path; - gint retval; - - path = g_strdup_printf ("%s/%s", dirname, filename); - retval = e_xml_save_file (path, doc); - g_free (path); - - return retval; -} - -static xmlNodePtr -xml_find_node (xmlNodePtr parent, const gchar *name) -{ - xmlNodePtr node; - - node = parent->children; - while (node != NULL) { - if (node->name && !strcmp ((gchar *)node->name, name)) - return node; - - node = node->next; - } - - return NULL; -} - -static void -upgrade_xml_uris (xmlDocPtr doc, gchar * (* upgrade_uri) (const gchar *uri)) -{ - xmlNodePtr root, node; - gchar *uri, *new; - - if (!doc || !(root = xmlDocGetRootElement (doc))) - return; - - if (!root->name || strcmp ((gchar *)root->name, "filteroptions") != 0) { - /* root node is not , nothing to upgrade */ - return; - } - - if (!(node = xml_find_node (root, "ruleset"))) { - /* no ruleset node, nothing to upgrade */ - return; - } - - node = node->children; - while (node != NULL) { - if (node->name && !strcmp ((gchar *)node->name, "rule")) { - xmlNodePtr actionset, part, val, n; - - if ((actionset = xml_find_node (node, "actionset"))) { - /* filters.xml */ - part = actionset->children; - while (part != NULL) { - if (part->name && !strcmp ((gchar *)part->name, "part")) { - val = part->children; - while (val != NULL) { - if (val->name && !strcmp ((gchar *)val->name, "value")) { - gchar *type; - - type = (gchar *)xmlGetProp (val, (const guchar *)"type"); - if (type && !strcmp ((gchar *)type, "folder")) { - if ((n = xml_find_node (val, "folder"))) { - uri = (gchar *)xmlGetProp (n, (const guchar *)"uri"); - new = upgrade_uri (uri); - xmlFree (uri); - - xmlSetProp (n, (const guchar *)"uri", (guchar *)new); - g_free (new); - } - } - - xmlFree (type); - } - - val = val->next; - } - } - - part = part->next; - } - } else if ((actionset = xml_find_node (node, "sources"))) { - /* vfolders.xml */ - n = actionset->children; - while (n != NULL) { - if (n->name && !strcmp ((gchar *)n->name, "folder")) { - uri = (gchar *)xmlGetProp (n, (const guchar *)"uri"); - new = upgrade_uri (uri); - xmlFree (uri); - - xmlSetProp (n, (const guchar *)"uri", (guchar *)new); - g_free (new); - } - - n = n->next; - } - } - } - - node = node->next; - } -} - -/* 1.0 upgrade functions & data */ - -/* as much info as we have on a given account */ -struct _account_info_1_0 { - gchar *name; - gchar *uri; - gchar *base_uri; - union { - struct { - /* for imap */ - gchar *namespace; - gchar *namespace_full; - guint32 capabilities; - GHashTable *folders; - gchar dir_sep; - } imap; - } u; -}; - -struct _imap_folder_info_1_0 { - gchar *folder; - /* encoded? decoded? canonicalised? */ - gchar dir_sep; -}; - -static GHashTable *accounts_1_0 = NULL; -static GHashTable *accounts_name_1_0 = NULL; - -static void -imap_folder_info_1_0_free (struct _imap_folder_info_1_0 *fi) -{ - g_free(fi->folder); - g_free(fi); -} - -static void -account_info_1_0_free (struct _account_info_1_0 *ai) -{ - g_free(ai->name); - g_free(ai->uri); - g_free(ai->base_uri); - g_free(ai->u.imap.namespace); - g_free(ai->u.imap.namespace_full); - g_hash_table_destroy(ai->u.imap.folders); - g_free(ai); -} - -static gchar * -get_base_uri(const gchar *val) -{ - const gchar *tmp; - - tmp = strchr(val, ':'); - if (tmp) { - tmp++; - if (strncmp(tmp, "//", 2) == 0) - tmp += 2; - tmp = strchr(tmp, '/'); - } - - if (tmp) - return g_strndup(val, tmp-val); - else - return g_strdup(val); -} - -static gchar * -upgrade_xml_uris_1_0 (const gchar *uri) -{ - gchar *out = NULL; - - /* upgrades camel uri's */ - if (strncmp (uri, "imap:", 5) == 0) { - gchar *base_uri, dir_sep, *folder, *p; - struct _account_info_1_0 *ai; - - /* add namespace, canonicalise dir_sep to / */ - base_uri = get_base_uri (uri); - ai = g_hash_table_lookup (accounts_1_0, base_uri); - - if (ai == NULL) { - g_free (base_uri); - return NULL; - } - - dir_sep = ai->u.imap.dir_sep; - if (dir_sep == 0) { - /* no dir_sep listed, try get it from the namespace, if set */ - if (ai->u.imap.namespace != NULL) { - p = ai->u.imap.namespace; - while ((dir_sep = *p++)) { - if (dir_sep < '0' - || (dir_sep > '9' && dir_sep < 'A') - || (dir_sep > 'Z' && dir_sep < 'a') - || (dir_sep > 'z')) { - break; - } - p++; - } - } - - /* give up ... */ - if (dir_sep == 0) { - g_free (base_uri); - return NULL; - } - } - - folder = g_strdup (uri + strlen (base_uri) + 1); - - /* Add the namespace before the mailbox name, unless the mailbox is INBOX */ - if (ai->u.imap.namespace && strcmp ((gchar *)folder, "INBOX") != 0) - out = g_strdup_printf ("%s/%s/%s", base_uri, ai->u.imap.namespace, folder); - else - out = g_strdup_printf ("%s/%s", base_uri, folder); - - p = out; - while (*p) { - if (*p == dir_sep) - *p = '/'; - p++; - } - - g_free (folder); - g_free (base_uri); - } else if (strncmp (uri, "exchange:", 9) == 0) { - gchar *base_uri, *folder, *p; - - /* exchange://user@host/exchange/ * -> exchange://user@host/personal/ * */ - /* Any url encoding (%xx) in the folder name is also removed */ - base_uri = get_base_uri (uri); - uri += strlen (base_uri) + 1; - if (strncmp (uri, "exchange/", 9) == 0) { - folder = e_bconf_url_decode (uri + 9); - p = strchr (folder, '/'); - out = g_strdup_printf ("%s/personal%s", base_uri, p ? p : "/"); - g_free (folder); - } - } else if (strncmp (uri, "exchanget:", 10) == 0) { - /* these should be converted in the accounts table when it is loaded */ - g_warning ("exchanget: uri not converted: '%s'", uri); - } - - return out; -} - -static gchar * -parse_lsub (const gchar *lsub, gchar *dir_sep) -{ - static gint comp; - static regex_t pat; - regmatch_t match[3]; - const gchar *m = "^\\* LSUB \\([^)]*\\) \"?([^\" ]+)\"? \"?(.*)\"?$"; - - if (!comp) { - if (regcomp (&pat, m, REG_EXTENDED|REG_ICASE) == -1) { - g_warning ("reg comp '%s' failed: %s", m, g_strerror (errno)); - return NULL; - } - comp = 1; - } - - if (regexec (&pat, lsub, 3, match, 0) == 0) { - if (match[1].rm_so != -1 && match[2].rm_so != -1) { - if (dir_sep) - *dir_sep = (match[1].rm_eo - match[1].rm_so == 1) ? lsub[match[1].rm_so] : 0; - return g_strndup (lsub + match[2].rm_so, match[2].rm_eo - match[2].rm_so); - } - } - - return NULL; -} - -static gboolean -read_imap_storeinfo (struct _account_info_1_0 *si) -{ - FILE *storeinfo; - guint32 tmp; - gchar *buf, *folder, dir_sep, *path, *name, *p; - struct _imap_folder_info_1_0 *fi; - - si->u.imap.folders = g_hash_table_new_full ( - g_str_hash, g_str_equal, - (GDestroyNotify) NULL, - (GDestroyNotify) imap_folder_info_1_0_free); - - /* get details from uri first */ - name = strstr (si->uri, ";override_namespace"); - if (name) { - name = strstr (si->uri, ";namespace="); - if (name) { - gchar *end; - - name += strlen (";namespace="); - if (*name == '\"') { - name++; - end = strchr (name, '\"'); - } else { - end = strchr (name, ';'); - } - - if (end) { - /* try get the dir_sep from the namespace */ - si->u.imap.namespace = g_strndup (name, end-name); - - p = si->u.imap.namespace; - while ((dir_sep = *p++)) { - if (dir_sep < '0' - || (dir_sep > '9' && dir_sep < 'A') - || (dir_sep > 'Z' && dir_sep < 'a') - || (dir_sep > 'z')) { - si->u.imap.dir_sep = dir_sep; - break; - } - p++; - } - } - } - } - - /* now load storeinfo if it exists */ - path = g_build_filename (g_get_home_dir (), "evolution", "mail", "imap", si->base_uri + 7, "storeinfo", NULL); - storeinfo = fopen (path, "r"); - g_free (path); - if (storeinfo == NULL) { - g_warning ("could not find imap store info '%s'", path); - return FALSE; - } - - /* ignore version */ - camel_file_util_decode_uint32 (storeinfo, &tmp); - camel_file_util_decode_uint32 (storeinfo, &si->u.imap.capabilities); - g_free (si->u.imap.namespace); - camel_file_util_decode_string (storeinfo, &si->u.imap.namespace); - camel_file_util_decode_uint32 (storeinfo, &tmp); - si->u.imap.dir_sep = tmp; - /* strip trailing dir_sep or / */ - if (si->u.imap.namespace - && (si->u.imap.namespace[strlen (si->u.imap.namespace) - 1] == si->u.imap.dir_sep - || si->u.imap.namespace[strlen (si->u.imap.namespace) - 1] == '/')) { - si->u.imap.namespace[strlen (si->u.imap.namespace) - 1] = 0; - } - - d(printf ("namespace '%s' dir_sep '%c'\n", si->u.imap.namespace, si->u.imap.dir_sep ? si->u.imap.dir_sep : '?')); - - while (camel_file_util_decode_string (storeinfo, &buf) == 0) { - folder = parse_lsub (buf, &dir_sep); - if (folder) { - fi = g_new0 (struct _imap_folder_info_1_0, 1); - fi->folder = folder; - fi->dir_sep = dir_sep; -#if d(!)0 - printf (" add folder '%s' ", folder); - if (dir_sep) - printf ("'%c'\n", dir_sep); - else - printf ("NIL\n"); -#endif - g_hash_table_insert (si->u.imap.folders, fi->folder, fi); - } else { - g_warning ("Could not parse LIST result '%s'\n", buf); - } - } - - fclose (storeinfo); - - return TRUE; -} - -static gboolean -load_accounts_1_0 (xmlDocPtr doc) -{ - xmlNodePtr source; - gchar *val, *tmp; - gint count = 0, i; - gchar key[32]; - - if (!(source = e_bconf_get_path (doc, "/Mail/Accounts"))) - return TRUE; - - if ((val = e_bconf_get_value (source, "num"))) { - count = atoi (val); - xmlFree (val); - } - - /* load account upgrade info for each account */ - for (i = 0; i < count; i++) { - struct _account_info_1_0 *ai; - gchar *rawuri; - - sprintf (key, "source_url_%d", i); - if (!(rawuri = e_bconf_get_value (source, key))) - continue; - - ai = g_malloc0 (sizeof (struct _account_info_1_0)); - ai->uri = e_bconf_hex_decode (rawuri); - ai->base_uri = get_base_uri (ai->uri); - sprintf (key, "account_name_%d", i); - ai->name = e_bconf_get_string (source, key); - - d(printf("load account '%s'\n", ai->uri)); - - if (!strncmp (ai->uri, "imap:", 5)) { - read_imap_storeinfo (ai); - } else if (!strncmp (ai->uri, "exchange:", 9)) { - xmlNodePtr node; - - d(printf (" upgrade exchange account\n")); - /* small hack, poke the source_url into the transport_url for exchanget: transports - - this will be picked up later in the conversion */ - sprintf (key, "transport_url_%d", i); - node = e_bconf_get_entry (source, key); - if (node && (val = (gchar *)xmlGetProp (node, (const guchar *)"value"))) { - tmp = e_bconf_hex_decode (val); - xmlFree (val); - if (strncmp (tmp, "exchanget:", 10) == 0) - xmlSetProp (node, (const guchar *)"value", (guchar *)rawuri); - g_free (tmp); - } else { - d(printf (" couldn't find transport uri?\n")); - } - } - xmlFree (rawuri); - - g_hash_table_insert (accounts_1_0, ai->base_uri, ai); - if (ai->name) - g_hash_table_insert (accounts_name_1_0, ai->name, ai); - } - - return TRUE; -} - -static gboolean -em_migrate_1_0 (const gchar *data_dir, xmlDocPtr config_xmldb, xmlDocPtr filters, xmlDocPtr vfolders, GError **error) -{ - accounts_1_0 = g_hash_table_new_full ( - g_str_hash, g_str_equal, - (GDestroyNotify) NULL, - (GDestroyNotify) account_info_1_0_free); - accounts_name_1_0 = g_hash_table_new (g_str_hash, g_str_equal); - load_accounts_1_0 (config_xmldb); - - upgrade_xml_uris(filters, upgrade_xml_uris_1_0); - upgrade_xml_uris(vfolders, upgrade_xml_uris_1_0); - - g_hash_table_destroy (accounts_1_0); - g_hash_table_destroy (accounts_name_1_0); - - return TRUE; -} - -/* 1.2 upgrade functions */ -static gboolean -is_xml1encoded (const gchar *txt) -{ - const guchar *p; - gint isxml1 = FALSE; - gint is8bit = FALSE; - - p = (const guchar *)txt; - while (*p) { - if (p[0] == '\\' && p[1] == 'U' && p[2] == '+' - && isxdigit (p[3]) && isxdigit (p[4]) && isxdigit (p[5]) && isxdigit (p[6]) - && p[7] == '\\') { - isxml1 = TRUE; - p+=7; - } else if (p[0] >= 0x80) - is8bit = TRUE; - p++; - } - - /* check for invalid utf8 that needs cleaning */ - if (is8bit && !isxml1) - isxml1 = !g_utf8_validate (txt, -1, NULL); - - return isxml1; -} - -static gchar * -decode_xml1 (const gchar *txt) -{ - GString *out = g_string_new (""); - const guchar *p; - gchar *res; - - /* convert: - \U+XXXX\ -> utf8 - 8 bit characters -> utf8 (iso-8859-1) */ - - p = (const guchar *) txt; - while (*p) { - if (p[0] > 0x80 - || (p[0] == '\\' && p[1] == 'U' && p[2] == '+' - && isxdigit (p[3]) && isxdigit (p[4]) && isxdigit (p[5]) && isxdigit (p[6]) - && p[7] == '\\')) { - gchar utf8[8]; - gunichar u; - - if (p[0] == '\\') { - memcpy (utf8, p + 3, 4); - utf8[4] = 0; - u = strtoul (utf8, NULL, 16); - p+=7; - } else - u = p[0]; - utf8[g_unichar_to_utf8 (u, utf8)] = 0; - g_string_append (out, utf8); - } else { - g_string_append_c (out, *p); - } - p++; - } - - res = out->str; - g_string_free (out, FALSE); - - return res; -} - -static gchar * -utf8_reencode (const gchar *txt) -{ - GString *out = g_string_new (""); - gchar *p; - gchar *res; - - /* convert: - libxml1 8 bit utf8 converted to xml entities byte-by-byte chars -> utf8 */ - - p = (gchar *)txt; - - while (*p) { - g_string_append_c (out, (gchar)g_utf8_get_char ((const gchar *)p)); - p = (gchar *)g_utf8_next_char (p); - } - - res = out->str; - if (g_utf8_validate (res, -1, NULL)) { - g_string_free (out, FALSE); - return res; - } else { - g_string_free (out, TRUE); - return g_strdup (txt); - } -} - -static gboolean -upgrade_xml_1_2_rec (xmlNodePtr node) -{ - const gchar *value_tags[] = { "string", "address", "regex", "file", "command", NULL }; - const gchar *rule_tags[] = { "title", NULL }; - const gchar *item_props[] = { "name", NULL }; - struct { - const gchar *name; - const gchar **tags; - const gchar **props; - } tags[] = { - { "value", value_tags, NULL }, - { "rule", rule_tags, NULL }, - { "item", NULL, item_props }, - { 0 }, - }; - xmlNodePtr work; - gint i,j; - gchar *txt, *tmp; - - /* upgrades the content of a node, if the node has a specific parent/node name */ - - for (i = 0; tags[i].name; i++) { - if (!strcmp ((gchar *)node->name, tags[i].name)) { - if (tags[i].tags != NULL) { - work = node->children; - while (work) { - for (j = 0; tags[i].tags[j]; j++) { - if (!strcmp ((gchar *)work->name, tags[i].tags[j])) { - txt = (gchar *)xmlNodeGetContent (work); - if (is_xml1encoded (txt)) { - tmp = decode_xml1 (txt); - d(printf ("upgrading xml node %s/%s '%s' -> '%s'\n", - tags[i].name, tags[i].tags[j], txt, tmp)); - xmlNodeSetContent (work, (guchar *)tmp); - g_free (tmp); - } - xmlFree (txt); - } - } - work = work->next; - } - break; - } - - if (tags[i].props != NULL) { - for (j = 0; tags[i].props[j]; j++) { - txt = (gchar *)xmlGetProp (node, (guchar *)tags[i].props[j]); - tmp = utf8_reencode (txt); - d(printf ("upgrading xml property %s on node %s '%s' -> '%s'\n", - tags[i].props[j], tags[i].name, txt, tmp)); - xmlSetProp (node, (const guchar *)tags[i].props[j], (guchar *)tmp); - g_free (tmp); - xmlFree (txt); - } - } - } - } - - node = node->children; - while (node) { - upgrade_xml_1_2_rec (node); - node = node->next; - } - - return TRUE; -} - -static gboolean -em_upgrade_xml_1_2 (xmlDocPtr doc) -{ - xmlNodePtr root; - - if (!doc || !(root = xmlDocGetRootElement (doc))) - return TRUE; - - return upgrade_xml_1_2_rec (root); -} - -/* ********************************************************************** */ -/* Tables for converting flat bonobo conf -> gconf xml blob */ -/* ********************************************************************** */ - -/* Mail/Accounts/ * */ -static e_bconf_map_t cc_map[] = { - { "account_always_cc_%i", "always", E_BCONF_MAP_BOOL }, - { "account_always_cc_addrs_%i", "recipients", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, - { NULL }, -}; - -static e_bconf_map_t bcc_map[] = { - { "account_always_cc_%i", "always", E_BCONF_MAP_BOOL }, - { "account_always_bcc_addrs_%i", "recipients", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, - { NULL }, -}; - -static e_bconf_map_t pgp_map[] = { - { "account_pgp_encrypt_to_self_%i", "encrypt-to-self", E_BCONF_MAP_BOOL }, - { "account_pgp_always_trust_%i", "always-trust", E_BCONF_MAP_BOOL }, - { "account_pgp_always_sign_%i", "always-sign", E_BCONF_MAP_BOOL }, - { "account_pgp_no_imip_sign_%i", "no-imip-sign", E_BCONF_MAP_BOOL }, - { "account_pgp_key_%i", "key-id", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, - { NULL }, -}; - -static e_bconf_map_t smime_map[] = { - { "account_smime_encrypt_to_self_%i", "encrypt-to-self", E_BCONF_MAP_BOOL }, - { "account_smime_always_sign_%i", "always-sign", E_BCONF_MAP_BOOL }, - { "account_smime_key_%i", "key-id", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, - { NULL }, -}; - -static e_bconf_map_t identity_sig_map[] = { - { "identity_autogenerated_signature_%i", "auto", E_BCONF_MAP_BOOL }, - { "identity_def_signature_%i", "default", E_BCONF_MAP_LONG }, - { NULL }, -}; - -static e_bconf_map_t identity_map[] = { - { "identity_name_%i", "name", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, - { "identity_address_%i", "addr-spec", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, - { "identity_reply_to_%i", "reply-to", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, - { "identity_organization_%i", "organization", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, - { NULL, "signature", E_BCONF_MAP_CHILD, identity_sig_map }, - { NULL }, -}; - -static e_bconf_map_t source_map[] = { - { "source_save_passwd_%i", "save-passwd", E_BCONF_MAP_BOOL }, - { "source_keep_on_server_%i", "keep-on-server", E_BCONF_MAP_BOOL }, - { "source_auto_check_%i", "auto-check", E_BCONF_MAP_BOOL }, - { "source_auto_check_time_%i", "auto-check-timeout", E_BCONF_MAP_LONG }, - { "source_url_%i", "url", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, - { NULL }, -}; - -static e_bconf_map_t transport_map[] = { - { "transport_save_passwd_%i", "save-passwd", E_BCONF_MAP_BOOL }, - { "transport_url_%i", "url", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, - { NULL }, -}; - -static e_bconf_map_t account_map[] = { - { "account_name_%i", "name", E_BCONF_MAP_STRING }, - { "source_enabled_%i", "enabled", E_BCONF_MAP_BOOL }, - { NULL, "identity", E_BCONF_MAP_CHILD, identity_map }, - { NULL, "source", E_BCONF_MAP_CHILD, source_map }, - { NULL, "transport", E_BCONF_MAP_CHILD, transport_map }, - { "account_drafts_folder_uri_%i", "drafts-folder", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, - { "account_sent_folder_uri_%i", "sent-folder", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, - { NULL, "auto-cc", E_BCONF_MAP_CHILD, cc_map }, - { NULL, "auto-bcc", E_BCONF_MAP_CHILD, bcc_map }, - { NULL, "pgp", E_BCONF_MAP_CHILD, pgp_map }, - { NULL, "smime", E_BCONF_MAP_CHILD, smime_map }, - { NULL }, -}; - -/* /Mail/Signatures/ * */ -static e_bconf_map_t signature_format_map[] = { - { "text/plain", }, - { "text/html", }, - { NULL } -}; - -static e_bconf_map_t signature_map[] = { - { "name_%i", "name", E_BCONF_MAP_STRING }, - { "html_%i", "format", E_BCONF_MAP_ENUM, signature_format_map }, - { "filename_%i", "filename", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, - { "script_%i", "script", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, - { NULL }, -}; - -/* ********************************************************************** */ -/* Tables for bonobo conf -> gconf conversion */ -/* ********************************************************************** */ - -static e_gconf_map_t mail_accounts_map[] = { - /* /Mail/Accounts - most entries are processed via the xml blob routine */ - /* This also works because the initial uid mapping is 1:1 with the list order */ - { "default_account", "mail/default_account", E_GCONF_MAP_SIMPLESTRING }, - { 0 }, -}; - -static e_gconf_map_t mail_display_map[] = { - /* /Mail/Display */ - { "side_bar_search", "mail/display/side_bar_search", E_GCONF_MAP_BOOL }, - { "thread_list", "mail/display/thread_list", E_GCONF_MAP_BOOL }, - { "thread_subject", "mail/display/thread_subject", E_GCONF_MAP_BOOL }, - { "hide_deleted", "mail/display/show_deleted", E_GCONF_MAP_BOOLNOT }, - { "preview_pane", "mail/display/show_preview", E_GCONF_MAP_BOOL }, - { "paned_size", "mail/display/paned_size", E_GCONF_MAP_INT }, - { "seen_timeout", "mail/display/mark_seen_timeout", E_GCONF_MAP_INT }, - { "do_seen_timeout", "mail/display/mark_seen", E_GCONF_MAP_BOOL }, - { "http_images", "mail/display/load_http_images", E_GCONF_MAP_INT }, - { "citation_highlight", "mail/display/mark_citations", E_GCONF_MAP_BOOL }, - { "citation_color", "mail/display/citation_colour", E_GCONF_MAP_COLOUR }, - { 0 }, -}; - -static e_gconf_map_t mail_format_map[] = { - /* /Mail/Format */ - { "message_display_style", "mail/display/message_style", E_GCONF_MAP_INT }, - { "send_html", "mail/composer/send_html", E_GCONF_MAP_BOOL }, - { "default_reply_style", "mail/format/reply_style", E_GCONF_MAP_INT }, - { "default_forward_style", "mail/format/forward_style", E_GCONF_MAP_INT }, - { "default_charset", "mail/composer/charset", E_GCONF_MAP_STRING }, - { "confirm_unwanted_html", "mail/prompts/unwanted_html", E_GCONF_MAP_BOOL }, - { 0 }, -}; - -static e_gconf_map_t mail_trash_map[] = { - /* /Mail/Trash */ - { "empty_on_exit", "mail/trash/empty_on_exit", E_GCONF_MAP_BOOL }, - { 0 }, -}; - -static e_gconf_map_t mail_prompts_map[] = { - /* /Mail/Prompts */ - { "confirm_expunge", "mail/prompts/expunge", E_GCONF_MAP_BOOL }, - { "empty_subject", "mail/prompts/empty_subject", E_GCONF_MAP_BOOL }, - { "only_bcc", "mail/prompts/only_bcc", E_GCONF_MAP_BOOL }, - { 0 } -}; - -static e_gconf_map_t mail_filters_map[] = { - /* /Mail/Filters */ - { "log", "mail/filters/log", E_GCONF_MAP_BOOL }, - { "log_path", "mail/filters/logfile", E_GCONF_MAP_STRING }, - { 0 } -}; - -static e_gconf_map_t mail_notify_map[] = { - /* /Mail/Notify */ - { "new_mail_notification", "mail/notify/type", E_GCONF_MAP_INT }, - { "new_mail_notification_sound_file", "mail/notify/sound", E_GCONF_MAP_STRING }, - { 0 } -}; - -static e_gconf_map_t mail_filesel_map[] = { - /* /Mail/Filesel */ - { "last_filesel_dir", "mail/save_dir", E_GCONF_MAP_STRING }, - { 0 } -}; - -static e_gconf_map_t mail_composer_map[] = { - /* /Mail/Composer */ - { "ViewFrom", "mail/composer/view/From", E_GCONF_MAP_BOOL }, - { "ViewReplyTo", "mail/composer/view/ReplyTo", E_GCONF_MAP_BOOL }, - { "ViewCC", "mail/composer/view/Cc", E_GCONF_MAP_BOOL }, - { "ViewBCC", "mail/composer/view/Bcc", E_GCONF_MAP_BOOL }, - { "ViewSubject", "mail/composer/view/Subject", E_GCONF_MAP_BOOL }, - { 0 }, -}; - -/* ********************************************************************** */ - -static e_gconf_map_t importer_elm_map[] = { - /* /Importer/Elm */ - { "mail", "importer/elm/mail", E_GCONF_MAP_BOOL }, - { "mail-imported", "importer/elm/mail-imported", E_GCONF_MAP_BOOL }, - { 0 }, -}; - -static e_gconf_map_t importer_pine_map[] = { - /* /Importer/Pine */ - { "mail", "importer/elm/mail", E_GCONF_MAP_BOOL }, - { "address", "importer/elm/address", E_GCONF_MAP_BOOL }, - { 0 }, -}; - -static e_gconf_map_t importer_netscape_map[] = { - /* /Importer/Netscape */ - { "mail", "importer/netscape/mail", E_GCONF_MAP_BOOL }, - { "settings", "importer/netscape/settings", E_GCONF_MAP_BOOL }, - { "filters", "importer/netscape/filters", E_GCONF_MAP_BOOL }, - { 0 }, -}; - -/* ********************************************************************** */ - -static e_gconf_map_list_t gconf_remap_list[] = { - { "/Mail/Accounts", mail_accounts_map }, - { "/Mail/Display", mail_display_map }, - { "/Mail/Format", mail_format_map }, - { "/Mail/Trash", mail_trash_map }, - { "/Mail/Prompts", mail_prompts_map }, - { "/Mail/Filters", mail_filters_map }, - { "/Mail/Notify", mail_notify_map }, - { "/Mail/Filesel", mail_filesel_map }, - { "/Mail/Composer", mail_composer_map }, - - { "/Importer/Elm", importer_elm_map }, - { "/Importer/Pine", importer_pine_map }, - { "/Importer/Netscape", importer_netscape_map }, - - { 0 }, -}; - -static struct { - const gchar *label; - const gchar *colour; -} label_default[5] = { - { N_("Important"), "#EF2929" }, /* red */ - { N_("Work"), "#F57900" }, /* orange */ - { N_("Personal"), "#4E9A06" }, /* green */ - { N_("To Do"), "#3465A4" }, /* blue */ - { N_("Later"), "#75507B" } /* purple */ -}; - -/* remaps mail config from bconf to gconf */ -static gboolean -bconf_import(GConfClient *gconf, xmlDocPtr config_xmldb) -{ - xmlNodePtr source; - gchar labx[16], colx[16]; - gchar *val, *lab, *col; - GSList *list, *l; - gint i; - - e_bconf_import(gconf, config_xmldb, gconf_remap_list); - - /* Labels: - label string + label colour as integer - -> label string:# colour as hex */ - source = e_bconf_get_path(config_xmldb, "/Mail/Labels"); - if (source) { - list = NULL; - for (i = 0; i < 5; i++) { - sprintf(labx, "label_%d", i); - sprintf(colx, "color_%d", i); - lab = e_bconf_get_string(source, labx); - if ((col = e_bconf_get_value(source, colx))) { - sprintf(colx, "#%06x", atoi(col) & 0xffffff); - g_free(col); - } else - strcpy(colx, label_default[i].colour); - - val = g_strdup_printf("%s:%s", lab ? lab : label_default[i].label, colx); - list = g_slist_append(list, val); - g_free(lab); - } - - gconf_client_set_list(gconf, "/apps/evolution/mail/labels", GCONF_VALUE_STRING, list, NULL); - while (list) { - l = list->next; - g_free(list->data); - g_slist_free_1(list); - list = l; - } - } else { - g_warning("could not find /Mail/Labels in old config database, skipping"); - } - - /* Accounts: The flat bonobo-config structure is remapped to a list of xml blobs. Upgrades as necessary */ - e_bconf_import_xml_blob(gconf, config_xmldb, account_map, "/Mail/Accounts", - "/apps/evolution/mail/accounts", "account", "uid"); - - /* Same for signatures */ - e_bconf_import_xml_blob(gconf, config_xmldb, signature_map, "/Mail/Signatures", - "/apps/evolution/mail/signatures", "signature", NULL); - - return TRUE; -} - -static gboolean -em_migrate_1_2(const gchar *data_dir, xmlDocPtr config_xmldb, xmlDocPtr filters, xmlDocPtr vfolders, GError **error) -{ - GConfClient *gconf; - - gconf = gconf_client_get_default(); - bconf_import(gconf, config_xmldb); - g_object_unref(gconf); - - em_upgrade_xml_1_2(filters); - em_upgrade_xml_1_2(vfolders); - - return TRUE; -} - -/* 1.4 upgrade functions */ - -#define EM_MIGRATE_SESSION_TYPE (em_migrate_session_get_type ()) -#define EM_MIGRATE_SESSION(obj) (CAMEL_CHECK_CAST((obj), EM_MIGRATE_SESSION_TYPE, EMMigrateSession)) -#define EM_MIGRATE_SESSION_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), EM_MIGRATE_SESSION_TYPE, EMMigrateSessionClass)) -#define EM_MIGRATE_IS_SESSION(o) (CAMEL_CHECK_TYPE((o), EM_MIGRATE_SESSION_TYPE)) - -typedef struct _EMMigrateSession { - CamelSession parent_object; - - CamelStore *store; /* new folder tree store */ - gchar *srcdir; /* old folder tree path */ -} EMMigrateSession; - -typedef struct _EMMigrateSessionClass { - CamelSessionClass parent_class; - -} EMMigrateSessionClass; - -static CamelType em_migrate_session_get_type (void); -static CamelSession *em_migrate_session_new (const gchar *path); - -static void -class_init (EMMigrateSessionClass *klass) -{ - ; -} - -static CamelType -em_migrate_session_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register ( - camel_session_get_type (), - "EMMigrateSession", - sizeof (EMMigrateSession), - sizeof (EMMigrateSessionClass), - (CamelObjectClassInitFunc) class_init, - NULL, - NULL, - NULL); - } - - return type; -} - -static CamelSession * -em_migrate_session_new (const gchar *path) -{ - CamelSession *session; - - session = CAMEL_SESSION (camel_object_new (EM_MIGRATE_SESSION_TYPE)); - - camel_session_construct (session, path); - - return session; -} - - -#endif /* !G_OS_WIN32 */ - -static GtkWidget *window; -static GtkLabel *label; -static GtkProgressBar *progress; - -static void -em_migrate_setup_progress_dialog (const gchar *title, const gchar *desc) -{ - GtkWidget *vbox, *hbox, *w; - gchar *markup; - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title ((GtkWindow *) window, _("Migrating...")); - gtk_window_set_modal ((GtkWindow *) window, TRUE); - gtk_container_set_border_width ((GtkContainer *) window, 6); - - vbox = gtk_vbox_new (FALSE, 6); - gtk_widget_show (vbox); - gtk_container_add ((GtkContainer *) window, vbox); - - w = gtk_label_new (desc); - - gtk_label_set_line_wrap ((GtkLabel *) w, TRUE); - gtk_widget_show (w); - gtk_box_pack_start_defaults ((GtkBox *) vbox, w); - - hbox = gtk_hbox_new (FALSE, 6); - gtk_widget_show (hbox); - gtk_box_pack_start_defaults ((GtkBox *) vbox, hbox); - - label = (GtkLabel *) gtk_label_new (""); - gtk_widget_show ((GtkWidget *) label); - gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) label); - - progress = (GtkProgressBar *) gtk_progress_bar_new (); - gtk_widget_show ((GtkWidget *) progress); - gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) progress); - - /* Prepare the message */ - vbox = gtk_vbox_new (FALSE, 12); - gtk_widget_show (vbox); - gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); - - w = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.0); - markup = g_strconcat ("", title ? title : _("Migration"), "", NULL); - gtk_label_set_markup (GTK_LABEL (w), markup); - gtk_box_pack_start (GTK_BOX (vbox), w, TRUE, TRUE, 0); - g_free (markup); - - w = gtk_label_new (desc); - gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.0); - gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); - gtk_box_pack_start (GTK_BOX (vbox), w, TRUE, TRUE, 0); - - /* Progress bar */ - w = gtk_vbox_new (FALSE, 6); - gtk_box_pack_start (GTK_BOX (vbox), w, TRUE, TRUE, 0); - - label = GTK_LABEL (gtk_label_new ("")); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0); - gtk_label_set_line_wrap (label, TRUE); - gtk_widget_show (GTK_WIDGET (label)); - gtk_box_pack_start (GTK_BOX (w), GTK_WIDGET (label), TRUE, TRUE, 0); - - progress = GTK_PROGRESS_BAR (gtk_progress_bar_new ()); - gtk_widget_show (GTK_WIDGET (progress)); - gtk_box_pack_start (GTK_BOX (w), GTK_WIDGET (progress), TRUE, TRUE, 0); - - gtk_container_add (GTK_CONTAINER (window), hbox); - gtk_widget_show_all (hbox); - gtk_widget_show (window); -} - -static void -em_migrate_close_progress_dialog (void) -{ - gtk_widget_destroy ((GtkWidget *) window); -} - -static void -em_migrate_set_folder_name (const gchar *folder_name) -{ - gchar *text; - - text = g_strdup_printf (_("Migrating '%s':"), folder_name); - gtk_label_set_text (label, text); - g_free (text); - - gtk_progress_bar_set_fraction (progress, 0.0); - while (gtk_events_pending ()) - gtk_main_iteration (); -} - -static void -em_migrate_set_progress (double percent) -{ - gchar text[5]; - - snprintf (text, sizeof (text), "%d%%", (gint) (percent * 100.0f)); - - gtk_progress_bar_set_fraction (progress, percent); - gtk_progress_bar_set_text (progress, text); - - while (gtk_events_pending ()) - gtk_main_iteration (); -} - -#ifndef G_OS_WIN32 - -static gboolean -is_mail_folder (const gchar *metadata) -{ - xmlNodePtr node; - xmlDocPtr doc; - gchar *type; - - if (!(doc = xmlParseFile (metadata))) { - g_warning ("Cannot parse `%s'", metadata); - return FALSE; - } - - if (!(node = xmlDocGetRootElement (doc))) { - g_warning ("`%s' corrupt: document contains no root node", metadata); - xmlFreeDoc (doc); - return FALSE; - } - - if (!node->name || strcmp ((gchar *)node->name, "efolder") != 0) { - g_warning ("`%s' corrupt: root node is not 'efolder'", metadata); - xmlFreeDoc (doc); - return FALSE; - } - - node = node->children; - while (node != NULL) { - if (node->name && !strcmp ((gchar *)node->name, "type")) { - type = (gchar *)xmlNodeGetContent (node); - if (!strcmp ((gchar *)type, "mail")) { - xmlFreeDoc (doc); - xmlFree (type); - - return TRUE; - } - - xmlFree (type); - - break; - } - - node = node->next; - } - - xmlFreeDoc (doc); - - return FALSE; -} - -static gboolean -get_local_et_expanded (const gchar *dirname) -{ - xmlNodePtr node; - xmlDocPtr doc; - struct stat st; - gchar *buf, *p; - gint thread_list; - - buf = g_strdup_printf ("%s/evolution/config/file:%s", g_get_home_dir (), dirname); - p = buf + strlen (g_get_home_dir ()) + strlen ("/evolution/config/file:"); - e_filename_make_safe (p); - - if (stat (buf, &st) == -1) { - g_free (buf); - return FALSE; - } - - if (!(doc = xmlParseFile (buf))) { - g_free (buf); - return FALSE; - } - - g_free (buf); - - if (!(node = xmlDocGetRootElement (doc)) || strcmp ((gchar *)node->name, "expanded_state") != 0) { - xmlFreeDoc (doc); - return FALSE; - } - - if (!(buf = (gchar *)xmlGetProp (node, (const guchar *)"default"))) { - xmlFreeDoc (doc); - return FALSE; - } - - thread_list = strcmp (buf, "0") == 0 ? 0 : 1; - xmlFree (buf); - - xmlFreeDoc (doc); - - return thread_list; -} - -static gchar * -get_local_store_uri (const gchar *dirname, gchar **namep, gint *indexp) -{ - gchar *name, *protocol, *metadata, *tmp; - gint index; - struct stat st; - xmlNodePtr node; - xmlDocPtr doc; - - metadata = g_build_filename(dirname, "local-metadata.xml", NULL); - - /* in 1.4, any errors are treated as defaults, this function cannot fail */ - - /* defaults */ - name = (gchar *) "mbox"; - protocol = (gchar *) "mbox"; - index = TRUE; - - if (stat (metadata, &st) == -1 || !S_ISREG (st.st_mode)) - goto nofile; - - doc = xmlParseFile(metadata); - if (doc == NULL) - goto nofile; - - node = doc->children; - if (strcmp((gchar *)node->name, "folderinfo")) - goto dodefault; - - for (node = node->children; node; node = node->next) { - if (node->name && !strcmp ((gchar *)node->name, "folder")) { - tmp = (gchar *)xmlGetProp (node, (const guchar *)"type"); - if (tmp) { - protocol = alloca(strlen(tmp)+1); - strcpy(protocol, tmp); - xmlFree(tmp); - } - tmp = (gchar *)xmlGetProp (node, (const guchar *)"name"); - if (tmp) { - name = alloca(strlen(tmp)+1); - strcpy(name, tmp); - xmlFree(tmp); - } - tmp = (gchar *)xmlGetProp (node, (const guchar *)"index"); - if (tmp) { - index = atoi(tmp); - xmlFree(tmp); - } - } - } -dodefault: - xmlFreeDoc (doc); -nofile: - g_free(metadata); - - *namep = g_strdup(name); - *indexp = index; - - return g_strdup_printf("%s:%s", protocol, dirname); -} - -#endif /* !G_OS_WIN32 */ - -enum { - CP_UNIQUE = 0, - CP_OVERWRITE, - CP_APPEND -}; - -static gint open_flags[3] = { - O_WRONLY | O_CREAT | O_TRUNC, - O_WRONLY | O_CREAT | O_TRUNC, - O_WRONLY | O_CREAT | O_APPEND, -}; - -static gboolean -cp (const gchar *src, const gchar *dest, gboolean show_progress, gint mode) -{ - guchar readbuf[65536]; - gssize nread, nwritten; - gint errnosav, readfd, writefd; - gsize total = 0; - struct stat st; - struct utimbuf ut; - - /* if the dest file exists and has content, abort - we don't - * want to corrupt their existing data */ - if (g_stat (dest, &st) == 0 && st.st_size > 0 && mode == CP_UNIQUE) { - errno = EEXIST; - return FALSE; - } - - if (g_stat (src, &st) == -1 - || (readfd = g_open (src, O_RDONLY | O_BINARY, 0)) == -1) - return FALSE; - - if ((writefd = g_open (dest, open_flags[mode] | O_BINARY, 0666)) == -1) { - errnosav = errno; - close (readfd); - errno = errnosav; - return FALSE; - } - - do { - do { - nread = read (readfd, readbuf, sizeof (readbuf)); - } while (nread == -1 && errno == EINTR); - - if (nread == 0) - break; - else if (nread < 0) - goto exception; - - do { - nwritten = write (writefd, readbuf, nread); - } while (nwritten == -1 && errno == EINTR); - - if (nwritten < nread) - goto exception; - - total += nwritten; - if (show_progress) - em_migrate_set_progress (((double) total) / ((double) st.st_size)); - } while (total < st.st_size); - - if (fsync (writefd) == -1) - goto exception; - - close (readfd); - if (close (writefd) == -1) - goto failclose; - - ut.actime = st.st_atime; - ut.modtime = st.st_mtime; - utime (dest, &ut); - chmod (dest, st.st_mode); - - return TRUE; - - exception: - - errnosav = errno; - close (readfd); - close (writefd); - errno = errnosav; - - failclose: - - errnosav = errno; - unlink (dest); - errno = errnosav; - - return FALSE; -} - -#ifndef G_OS_WIN32 - -static gboolean -cp_r (const gchar *src, const gchar *dest, const gchar *pattern, gint mode) -{ - GString *srcpath, *destpath; - struct dirent *dent; - gsize slen, dlen; - struct stat st; - DIR *dir; - - if (g_mkdir_with_parents (dest, 0777) == -1) - return FALSE; - - if (!(dir = opendir (src))) - return FALSE; - - srcpath = g_string_new (src); - g_string_append_c (srcpath, '/'); - slen = srcpath->len; - - destpath = g_string_new (dest); - g_string_append_c (destpath, '/'); - dlen = destpath->len; - - while ((dent = readdir (dir))) { - if (!strcmp (dent->d_name, ".") || !strcmp (dent->d_name, "..")) - continue; - - g_string_truncate (srcpath, slen); - g_string_truncate (destpath, dlen); - - g_string_append (srcpath, dent->d_name); - g_string_append (destpath, dent->d_name); - - if (stat (srcpath->str, &st) == -1) - continue; - - if (S_ISDIR (st.st_mode)) { - cp_r (srcpath->str, destpath->str, pattern, mode); - } else if (!pattern || !strcmp (dent->d_name, pattern)) { - cp (srcpath->str, destpath->str, FALSE, mode); - } - } - - closedir (dir); - - g_string_free (destpath, TRUE); - g_string_free (srcpath, TRUE); - - return TRUE; -} - -static void -mbox_build_filename (GString *path, const gchar *toplevel_dir, const gchar *full_name) -{ - const gchar *start, *inptr = full_name; - gint subdirs = 0; - - while (*inptr != '\0') { - if (*inptr == '/') - subdirs++; - inptr++; - } - - g_string_assign(path, toplevel_dir); - g_string_append_c (path, '/'); - - inptr = full_name; - while (*inptr != '\0') { - start = inptr; - while (*inptr != '/' && *inptr != '\0') - inptr++; - - g_string_append_len (path, start, inptr - start); - - if (*inptr == '/') { - g_string_append (path, ".sbd/"); - inptr++; - - /* strip extranaeous '/'s */ - while (*inptr == '/') - inptr++; - } - } -} - -static gboolean -em_migrate_folder(EMMigrateSession *session, const gchar *dirname, const gchar *full_name, GError **error) -{ - CamelFolder *old_folder = NULL, *new_folder = NULL; - CamelStore *local_store = NULL; - CamelException ex; - gchar *name, *uri; - GPtrArray *uids; - struct stat st; - gboolean thread_list; - gint index, i; - GString *src, *dest; - gboolean success = FALSE; - - camel_exception_init (&ex); - - src = g_string_new(""); - - g_string_printf(src, "%s/folder-metadata.xml", dirname); - if (stat (src->str, &st) == -1 - || !S_ISREG (st.st_mode) - || !is_mail_folder(src->str)) { - /* Not an evolution mail folder */ - g_string_free(src, TRUE); - return TRUE; - } - - dest = g_string_new(""); - uri = get_local_store_uri(dirname, &name, &index); - em_migrate_set_folder_name (full_name); - thread_list = get_local_et_expanded (dirname); - - /* Manually copy local mbox files, its much faster */ - if (!strncmp (uri, "mbox:", 5)) { - static const gchar *meta_ext[] = { ".summary", ".ibex.index", ".ibex.index.data" }; - gsize slen, dlen; - FILE *fp; - gchar *p; - gint mode; - - g_string_printf (src, "%s/%s", uri + 5, name); - mbox_build_filename (dest, ((CamelService *)session->store)->url->path, full_name); - p = strrchr (dest->str, '/'); - *p = '\0'; - - slen = src->len; - dlen = dest->len; - - if (g_mkdir_with_parents (dest->str, 0777) == -1 && errno != EEXIST) { - g_set_error ( - error, E_SHELL_MIGRATE_ERROR, - E_SHELL_MIGRATE_ERROR_FAILED, - _("Unable to create new folder `%s': %s"), - dest->str, g_strerror (errno)); - goto fatal; - } - - *p = '/'; - mode = CP_UNIQUE; - retry_copy: - if (!cp (src->str, dest->str, TRUE, mode)) { - if (errno == EEXIST) { - gint save = errno; - - switch (e_error_run(NULL, "mail:ask-migrate-existing", src->str, dest->str, NULL)) { - case GTK_RESPONSE_ACCEPT: - mode = CP_OVERWRITE; - goto retry_copy; - case GTK_RESPONSE_OK: - mode = CP_APPEND; - goto retry_copy; - case GTK_RESPONSE_REJECT: - goto ignore; - } - - errno = save; - } - g_set_error ( - error, E_SHELL_MIGRATE_ERROR, - E_SHELL_MIGRATE_ERROR_FAILED, - _("Unable to copy folder `%s' to `%s': %s"), - src->str, dest->str, g_strerror (errno)); - goto fatal; - } - ignore: - - /* create a .cmeta file specifying to index and/or thread the folder */ - g_string_truncate (dest, dlen); - g_string_append (dest, ".cmeta"); - if ((fp = fopen (dest->str, "w")) != NULL) { - gint fd = fileno (fp); - - /* write the magic string */ - if (fwrite ("CLMD", 4, 1, fp) != 1) - goto cmeta_err; - - /* write the version (1) */ - if (camel_file_util_encode_uint32 (fp, 1) == -1) - goto cmeta_err; - - /* write the meta count */ - if (camel_file_util_encode_uint32 (fp, thread_list ? 1 : 0) == -1) - goto cmeta_err; - - if (!thread_list) { - if (camel_file_util_encode_string (fp, "evolution:thread_list") == -1) - goto cmeta_err; - - if (camel_file_util_encode_string (fp, !thread_list ? "1" : "0") == -1) - goto cmeta_err; - } - - /* write the prop count (only prop is the index prop) */ - if (camel_file_util_encode_uint32 (fp, 1) == -1) - goto cmeta_err; - - /* write the index prop tag (== CAMEL_FOLDER_ARG_LAST|CAMEL_ARG_BOO) */ - if (camel_file_util_encode_uint32 (fp, CAMEL_FOLDER_ARG_LAST|CAMEL_ARG_BOO) == -1) - goto cmeta_err; - - /* write the index prop value */ - if (camel_file_util_encode_uint32 (fp, 1) == -1) - goto cmeta_err; - - fflush (fp); - - if (fsync (fd) == -1) { - cmeta_err: - fclose (fp); - unlink (dest->str); - } else { - fclose (fp); - } - } - - /* copy over the metadata files */ - for (i = 0; i < sizeof(meta_ext)/sizeof(meta_ext[0]); i++) { - g_string_truncate (src, slen); - g_string_truncate (dest, dlen); - - g_string_append (src, meta_ext[i]); - g_string_append (dest, meta_ext[i]); - cp (src->str, dest->str, FALSE, CP_OVERWRITE); - } - } else { - guint32 flags = CAMEL_STORE_FOLDER_CREATE; - - if (!(local_store = camel_session_get_store ((CamelSession *) session, uri, &ex)) - || !(old_folder = camel_store_get_folder (local_store, name, 0, &ex))) - goto fatal; - - flags |= (index ? CAMEL_STORE_FOLDER_BODY_INDEX : 0); - if (!(new_folder = camel_store_get_folder (session->store, full_name, flags, &ex))) - goto fatal; - - if (!thread_list) { - camel_object_meta_set (new_folder, "evolution:thread_list", !thread_list ? "1" : "0"); - camel_object_state_write (new_folder); - } - - uids = camel_folder_get_uids (old_folder); - for (i = 0; i < uids->len; i++) { - CamelMimeMessage *message; - CamelMessageInfo *info; - - if (!(info = camel_folder_get_message_info (old_folder, uids->pdata[i]))) - continue; - - if (!(message = camel_folder_get_message (old_folder, uids->pdata[i], &ex))) { - camel_folder_free_message_info (old_folder, info); - camel_folder_free_uids (old_folder, uids); - goto fatal; - } - - camel_folder_append_message (new_folder, message, info, NULL, &ex); - camel_folder_free_message_info (old_folder, info); - camel_object_unref (message); - - if (camel_exception_is_set (&ex)) - break; - - em_migrate_set_progress (((double) i + 1) / ((double) uids->len)); - } - - camel_folder_free_uids (old_folder, uids); - - if (camel_exception_is_set (&ex)) - goto fatal; - } - success = TRUE; -fatal: - g_free (uri); - g_free (name); - g_string_free(src, TRUE); - g_string_free(dest, TRUE); - if (local_store) - camel_object_unref(local_store); - if (old_folder) - camel_object_unref(old_folder); - if (new_folder) - camel_object_unref(new_folder); - - if (camel_exception_is_set (&ex)) { - g_set_error ( - error, E_SHELL_MIGRATE_ERROR, - E_SHELL_MIGRATE_ERROR_FAILED, - "%s", camel_exception_get_description (&ex)); - camel_exception_clear (&ex); - } - - return success; -} - -static gboolean -em_migrate_dir (EMMigrateSession *session, const gchar *dirname, const gchar *full_name, GError **error) -{ - gchar *path; - DIR *dir; - struct stat st; - struct dirent *dent; - gboolean success = TRUE; - - if (!em_migrate_folder(session, dirname, full_name, error)) - return FALSE; - - /* no subfolders, not readable, don't care */ - path = g_strdup_printf ("%s/subfolders", dirname); - if (stat (path, &st) == -1 || !S_ISDIR (st.st_mode)) { - g_free (path); - return TRUE; - } - - if (!(dir = opendir (path))) { - g_free (path); - return TRUE; - } - - while (success && (dent = readdir (dir))) { - gchar *full_path; - gchar *name; - - if (dent->d_name[0] == '.') - continue; - - full_path = g_strdup_printf ("%s/%s", path, dent->d_name); - if (stat (full_path, &st) == -1 || !S_ISDIR (st.st_mode)) { - g_free (full_path); - continue; - } - - name = g_strdup_printf ("%s/%s", full_name, dent->d_name); - success = em_migrate_dir (session, full_path, name, error); - g_free (full_path); - g_free (name); - } - - closedir (dir); - - g_free (path); - - return success; -} - -static gboolean -em_migrate_local_folders_1_4 (EMMigrateSession *session, GError **error) -{ - struct dirent *dent; - struct stat st; - DIR *dir; - gboolean success = TRUE; - - if (!(dir = opendir (session->srcdir))) { - g_set_error ( - error, E_SHELL_MIGRATE_ERROR, - E_SHELL_MIGRATE_ERROR_FAILED, - _("Unable to scan for existing mailboxes at " - "`%s': %s"), session->srcdir, g_strerror (errno)); - return FALSE; - } - - em_migrate_setup_progress_dialog ( - _("Migrating Folders"), - _("The location and hierarchy of the Evolution mailbox " - "folders has changed since Evolution 1.x.\n\nPlease be " - "patient while Evolution migrates your folders...")); - - while (success && (dent = readdir (dir))) { - gchar *full_path; - - if (dent->d_name[0] == '.') - continue; - - full_path = g_strdup_printf ("%s/%s", session->srcdir, dent->d_name); - if (stat (full_path, &st) == -1 || !S_ISDIR (st.st_mode)) { - g_free (full_path); - continue; - } - - success = em_migrate_dir (session, full_path, dent->d_name, error); - g_free (full_path); - } - - closedir (dir); - - em_migrate_close_progress_dialog (); - - return success; -} - -static gchar * -upgrade_xml_uris_1_4 (const gchar *uri) -{ - gchar *path, *prefix, *p; - CamelURL *url; - - if (!strncmp (uri, "file:", 5)) { - url = camel_url_new (uri, NULL); - camel_url_set_protocol (url, "email"); - camel_url_set_user (url, "local"); - camel_url_set_host (url, "local"); - - prefix = g_build_filename (g_get_home_dir (), "evolution", "local", NULL); - if (strncmp (url->path, prefix, strlen (prefix)) != 0) { - /* uri is busticated - user probably copied from another user's home directory */ - camel_url_free (url); - g_free (prefix); - - return g_strdup (uri); - } - path = g_strdup (url->path + strlen (prefix)); - g_free (prefix); - - /* modify the path in-place */ - p = path + strlen (path) - 12; - while (p > path) { - if (!strncmp (p, "/subfolders/", 12)) - memmove (p, p + 11, strlen (p + 11) + 1); - - p--; - } - - camel_url_set_path (url, path); - g_free (path); - - path = camel_url_to_string (url, 0); - camel_url_free (url); - - return path; - } else { - return em_uri_from_camel (uri); - } -} - -static void -upgrade_vfolder_sources_1_4 (xmlDocPtr doc) -{ - xmlNodePtr root, node; - - if (!doc || !(root = xmlDocGetRootElement (doc))) - return; - - if (!root->name || strcmp ((gchar *)root->name, "filteroptions") != 0) { - /* root node is not , nothing to upgrade */ - return; - } - - if (!(node = xml_find_node (root, "ruleset"))) { - /* no ruleset node, nothing to upgrade */ - return; - } - - node = node->children; - while (node != NULL) { - if (node->name && !strcmp ((gchar *)node->name, "rule")) { - xmlNodePtr sources; - gchar *src; - - if (!(src = (gchar *)xmlGetProp (node, (const guchar *)"source"))) - src = (gchar *)xmlStrdup ((const guchar *)"local"); /* default to all local folders? */ - - xmlSetProp (node, (const guchar *)"source", (const guchar *)"incoming"); - - if (!(sources = xml_find_node (node, "sources"))) - sources = xmlNewChild (node, NULL, (const guchar *)"sources", NULL); - - xmlSetProp (sources, (const guchar *)"with", (guchar *)src); - xmlFree (src); - } - - node = node->next; - } -} - -static gchar * -get_nth_sig (gint id) -{ - ESignatureList *list; - ESignature *sig; - EIterator *iter; - gchar *uid = NULL; - gint i = 0; - - list = e_get_signature_list (); - iter = e_list_get_iterator ((EList *) list); - - while (e_iterator_is_valid (iter) && i < id) { - e_iterator_next (iter); - i++; - } - - if (i == id && e_iterator_is_valid (iter)) { - sig = (ESignature *) e_iterator_get (iter); - uid = g_strdup (sig->uid); - } - - g_object_unref (iter); - - return uid; -} - -static void -em_upgrade_accounts_1_4 (void) -{ - EAccountList *accounts; - EIterator *iter; - - if (!(accounts = e_get_account_list ())) - return; - - iter = e_list_get_iterator ((EList *) accounts); - while (e_iterator_is_valid (iter)) { - EAccount *account = (EAccount *) e_iterator_get (iter); - gchar *url; - - if (account->drafts_folder_uri) { - url = upgrade_xml_uris_1_4 (account->drafts_folder_uri); - g_free (account->drafts_folder_uri); - account->drafts_folder_uri = url; - } - - if (account->sent_folder_uri) { - url = upgrade_xml_uris_1_4 (account->sent_folder_uri); - g_free (account->sent_folder_uri); - account->sent_folder_uri = url; - } - - if (account->id->sig_uid && !strncmp (account->id->sig_uid, "::", 2)) { - gint sig_id; - - sig_id = strtol (account->id->sig_uid + 2, NULL, 10); - g_free (account->id->sig_uid); - account->id->sig_uid = get_nth_sig (sig_id); - } - - e_iterator_next (iter); - } - - g_object_unref (iter); - - e_account_list_save (accounts); -} - -static gboolean -em_migrate_pop_uid_caches_1_4 (const gchar *data_dir, GError **error) -{ - GString *oldpath, *newpath; - struct dirent *dent; - gsize olen, nlen; - gchar *cache_dir; - DIR *dir; - gboolean success = TRUE; - - /* Sigh, too many unique strings to translate, for cases which shouldn't ever happen */ - - /* open the old cache dir */ - cache_dir = g_build_filename (g_get_home_dir (), "evolution", "mail", "pop3", NULL); - if (!(dir = opendir (cache_dir))) { - if (errno == ENOENT) { - g_free(cache_dir); - return TRUE; - } - - g_set_error ( - error, E_SHELL_MIGRATE_ERROR, - E_SHELL_MIGRATE_ERROR_FAILED, - _("Unable to open old POP keep-on-server data " - "`%s': %s"), cache_dir, g_strerror (errno)); - g_free (cache_dir); - return FALSE; - } - - oldpath = g_string_new (cache_dir); - g_string_append_c (oldpath, '/'); - olen = oldpath->len; - g_free (cache_dir); - - cache_dir = g_build_filename (data_dir, "pop", NULL); - if (g_mkdir_with_parents (cache_dir, 0777) == -1) { - g_set_error ( - error, E_SHELL_MIGRATE_ERROR, - E_SHELL_MIGRATE_ERROR_FAILED, - _("Unable to create POP3 keep-on-server data " - "directory `%s': %s"), cache_dir, - g_strerror (errno)); - g_string_free (oldpath, TRUE); - g_free (cache_dir); - closedir (dir); - return FALSE; - } - - newpath = g_string_new (cache_dir); - g_string_append_c (newpath, '/'); - nlen = newpath->len; - g_free (cache_dir); - - while (success && (dent = readdir (dir))) { - if (strncmp (dent->d_name, "cache-pop:__", 12) != 0) - continue; - - g_string_truncate (oldpath, olen); - g_string_truncate (newpath, nlen); - - g_string_append (oldpath, dent->d_name); - g_string_append (newpath, dent->d_name + 12); - - /* strip the trailing '_' */ - g_string_truncate (newpath, newpath->len - 1); - - if (g_mkdir_with_parents (newpath->str, 0777) == -1 - || !cp(oldpath->str, (g_string_append(newpath, "/uid-cache"))->str, FALSE, CP_UNIQUE)) { - g_set_error ( - error, E_SHELL_MIGRATE_ERROR, - E_SHELL_MIGRATE_ERROR_FAILED, - _("Unable to copy POP3 keep-on-server data " - "`%s': %s"), oldpath->str, - g_strerror (errno)); - success = FALSE; - } - - } - - g_string_free (oldpath, TRUE); - g_string_free (newpath, TRUE); - - closedir (dir); - - return success; -} - -static gboolean -em_migrate_imap_caches_1_4 (const gchar *data_dir, GError **error) -{ - gchar *src, *dest; - struct stat st; - - src = g_build_filename (g_get_home_dir (), "evolution", "mail", "imap", NULL); - if (stat (src, &st) == -1 || !S_ISDIR (st.st_mode)) { - g_free (src); - return TRUE; - } - - dest = g_build_filename (data_dir, "imap", NULL); - - /* we don't care if this fails, it's only a cache... */ - cp_r (src, dest, "summary", CP_OVERWRITE); - - g_free (dest); - g_free (src); - - return TRUE; -} - -static gboolean -em_migrate_folder_expand_state_1_4 (const gchar *data_dir, GError **error) -{ - GString *srcpath, *destpath; - gsize slen, dlen, rlen; - gchar *evo14_mbox_root; - struct dirent *dent; - struct stat st; - DIR *dir; - - srcpath = g_string_new (g_get_home_dir ()); - g_string_append (srcpath, "/evolution/config"); - if (stat (srcpath->str, &st) == -1 || !S_ISDIR (st.st_mode)) { - g_string_free (srcpath, TRUE); - return TRUE; - } - - destpath = g_string_new (data_dir); - g_string_append (destpath, "/config"); - if (g_mkdir_with_parents (destpath->str, 0777) == -1 || !(dir = opendir (srcpath->str))) { - g_string_free (destpath, TRUE); - g_string_free (srcpath, TRUE); - return TRUE; - } - - g_string_append (srcpath, "/et-expanded-"); - slen = srcpath->len; - g_string_append (destpath, "/et-expanded-"); - dlen = destpath->len; - - evo14_mbox_root = g_build_filename (g_get_home_dir (), "evolution", "local", NULL); - e_filename_make_safe (evo14_mbox_root); - rlen = strlen (evo14_mbox_root); - evo14_mbox_root = g_realloc (evo14_mbox_root, rlen + 2); - evo14_mbox_root[rlen++] = '_'; - evo14_mbox_root[rlen] = '\0'; - - while ((dent = readdir (dir))) { - gchar *full_name, *inptr, *buf = NULL; - const gchar *filename; - GString *new; - - if (strncmp (dent->d_name, "et-expanded-", 12) != 0) - continue; - - if (!strncmp (dent->d_name + 12, "file:", 5)) { - /* need to munge the filename */ - inptr = dent->d_name + 17; - - if (!strncmp (inptr, evo14_mbox_root, rlen)) { - /* this should always be the case afaik... */ - inptr += rlen; - new = g_string_new ("mbox:"); - g_string_append_printf (new, "%s/local#", data_dir); - - full_name = g_strdup (inptr); - inptr = full_name + strlen (full_name) - 12; - while (inptr > full_name) { - if (!strncmp (inptr, "_subfolders_", 12)) - memmove (inptr, inptr + 11, strlen (inptr + 11) + 1); - - inptr--; - } - - g_string_append (new, full_name); - g_free (full_name); - - filename = buf = new->str; - g_string_free (new, FALSE); - e_filename_make_safe (buf); - } else { - /* but just in case... */ - filename = dent->d_name + 12; - } - } else { - /* no munging needed */ - filename = dent->d_name + 12; - } - - g_string_append (srcpath, dent->d_name + 12); - g_string_append (destpath, filename); - g_free (buf); - - cp (srcpath->str, destpath->str, FALSE, CP_UNIQUE); - - g_string_truncate (srcpath, slen); - g_string_truncate (destpath, dlen); - } - - closedir (dir); - - g_free (evo14_mbox_root); - g_string_free (destpath, TRUE); - g_string_free (srcpath, TRUE); - - return TRUE; -} - -static gboolean -em_migrate_folder_view_settings_1_4 (const gchar *data_dir, GError **error) -{ - GString *srcpath, *destpath; - gsize slen, dlen, rlen; - gchar *evo14_mbox_root; - struct dirent *dent; - struct stat st; - DIR *dir; - - srcpath = g_string_new (g_get_home_dir ()); - g_string_append (srcpath, "/evolution/views/mail"); - if (stat (srcpath->str, &st) == -1 || !S_ISDIR (st.st_mode)) { - g_string_free (srcpath, TRUE); - return TRUE; - } - - destpath = g_string_new (data_dir); - g_string_append (destpath, "/views"); - if (g_mkdir_with_parents (destpath->str, 0777) == -1 || !(dir = opendir (srcpath->str))) { - g_string_free (destpath, TRUE); - g_string_free (srcpath, TRUE); - return TRUE; - } - - g_string_append_c (srcpath, '/'); - slen = srcpath->len; - g_string_append_c (destpath, '/'); - dlen = destpath->len; - - evo14_mbox_root = g_build_filename (g_get_home_dir (), "evolution", "local", NULL); - e_filename_make_safe (evo14_mbox_root); - rlen = strlen (evo14_mbox_root); - evo14_mbox_root = g_realloc (evo14_mbox_root, rlen + 2); - evo14_mbox_root[rlen++] = '_'; - evo14_mbox_root[rlen] = '\0'; - - while ((dent = readdir (dir))) { - gchar *full_name, *inptr, *buf = NULL; - const gchar *filename, *ext; - gsize prelen = 0; - GString *new; - - if (dent->d_name[0] == '.') - continue; - - if (!(ext = strrchr (dent->d_name, '.'))) - continue; - - if (!strcmp (ext, ".galview") || !strcmp ((gchar *)dent->d_name, "galview.xml")) { - /* just copy the file */ - filename = dent->d_name; - goto copy; - } else if (strcmp (ext, ".xml") != 0) { - continue; - } - - if (!strncmp ((const gchar *)dent->d_name, "current_view-", 13)) { - prelen = 13; - } else if (!strncmp ((const gchar *)dent->d_name, "custom_view-", 12)) { - prelen = 12; - } else { - /* huh? wtf is this file? */ - continue; - } - - if (!strncmp (dent->d_name + prelen, "file:", 5)) { - /* need to munge the filename */ - inptr = dent->d_name + prelen + 5; - - if (!strncmp (inptr, evo14_mbox_root, rlen)) { - /* this should always be the case afaik... */ - inptr += rlen; - new = g_string_new ("mbox:"); - g_string_append_printf (new, "%s/local#", data_dir); - - full_name = g_strdup (inptr); - inptr = full_name + strlen (full_name) - 12; - while (inptr > full_name) { - if (!strncmp (inptr, "_subfolders_", 12)) - memmove (inptr, inptr + 11, strlen (inptr + 11) + 1); - - inptr--; - } - - g_string_append (new, full_name); - g_free (full_name); - - filename = buf = new->str; - g_string_free (new, FALSE); - e_filename_make_safe (buf); - } else { - /* but just in case... */ - filename = dent->d_name + prelen; - } - } else { - /* no munging needed */ - filename = dent->d_name + prelen; - } - - copy: - g_string_append (srcpath, dent->d_name); - if (prelen > 0) - g_string_append_len (destpath, dent->d_name, prelen); - g_string_append (destpath, filename); - g_free (buf); - - cp (srcpath->str, destpath->str, FALSE, CP_UNIQUE); - - g_string_truncate (srcpath, slen); - g_string_truncate (destpath, dlen); - } - - closedir (dir); - - g_free (evo14_mbox_root); - g_string_free (destpath, TRUE); - g_string_free (srcpath, TRUE); - - return TRUE; -} - -#define SUBFOLDER_DIR_NAME "subfolders" -#define SUBFOLDER_DIR_NAME_LEN 10 - -static gchar * -e_path_to_physical (const gchar *prefix, const gchar *vpath) -{ - const gchar *p, *newp; - gchar *dp; - gchar *ppath; - gint ppath_len; - gint prefix_len; - - while (*vpath == '/') - vpath++; - if (!prefix) - prefix = ""; - - /* Calculate the length of the real path. */ - ppath_len = strlen (vpath); - ppath_len++; /* For the ending zero. */ - - prefix_len = strlen (prefix); - ppath_len += prefix_len; - ppath_len++; /* For the separating slash. */ - - /* Take account of the fact that we need to translate every - * separator into `subfolders/'. - */ - p = vpath; - while (1) { - newp = strchr (p, '/'); - if (newp == NULL) - break; - - ppath_len += SUBFOLDER_DIR_NAME_LEN; - ppath_len++; /* For the separating slash. */ - - /* Skip consecutive slashes. */ - while (*newp == '/') - newp++; - - p = newp; - }; - - ppath = g_malloc (ppath_len); - dp = ppath; - - memcpy (dp, prefix, prefix_len); - dp += prefix_len; - *(dp++) = '/'; - - /* Copy the mangled path. */ - p = vpath; - while (1) { - newp = strchr (p, '/'); - if (newp == NULL) { - strcpy (dp, p); - break; - } - - memcpy (dp, p, newp - p + 1); /* `+ 1' to copy the slash too. */ - dp += newp - p + 1; - - memcpy (dp, SUBFOLDER_DIR_NAME, SUBFOLDER_DIR_NAME_LEN); - dp += SUBFOLDER_DIR_NAME_LEN; - - *(dp++) = '/'; - - /* Skip consecutive slashes. */ - while (*newp == '/') - newp++; - - p = newp; - } - - return ppath; -} - -static gboolean -em_migrate_imap_cmeta_1_4(const gchar *data_dir, GError **error) -{ - GConfClient *gconf; - GSList *paths, *p; - EAccountList *accounts; - const EAccount *account; - - if (!(accounts = e_get_account_list ())) - return TRUE; - - gconf = gconf_client_get_default(); - paths = gconf_client_get_list(gconf, "/apps/evolution/shell/offline/folder_paths", GCONF_VALUE_STRING, NULL); - for (p = paths;p;p = g_slist_next(p)) { - gchar *name, *path; - - name = p->data; - if (*name) - name++; - path = strchr(name, '/'); - if (path) { - *path++ = 0; - account = e_account_list_find(accounts, E_ACCOUNT_FIND_NAME, name); - if (account && !strncmp(account->source->url, "imap:", 5)) { - CamelURL *url = camel_url_new(account->source->url, NULL); - - if (url) { - gchar *dir, *base; - - base = g_strdup_printf("%s/imap/%s@%s/folders", - data_dir, - url->user?url->user:"", - url->host?url->host:""); - - dir = e_path_to_physical(base, path); - if (g_mkdir_with_parents(dir, 0777) == 0) { - gchar *cmeta; - FILE *fp; - - cmeta = g_build_filename(dir, "cmeta", NULL); - fp = fopen(cmeta, "w"); - if (fp) { - /* header/version */ - fwrite("CLMD", 4, 1, fp); - camel_file_util_encode_uint32(fp, 1); - /* meta count, do we have any metadata? */ - camel_file_util_encode_uint32(fp, 0); - /* prop count */ - camel_file_util_encode_uint32(fp, 1); - /* sync offline property */ - camel_file_util_encode_uint32(fp, CAMEL_DISCO_FOLDER_OFFLINE_SYNC); - camel_file_util_encode_uint32(fp, 1); - fclose(fp); - } else { - g_warning("couldn't create imap folder cmeta file '%s'", cmeta); - } - g_free(cmeta); - } else { - g_warning("couldn't create imap folder directory '%s'", dir); - } - g_free(dir); - g_free(base); - camel_url_free(url); - } - } else - g_warning("can't find offline folder '%s' '%s'", name, path); - } - g_free(p->data); - } - g_slist_free(paths); - g_object_unref(gconf); - - /* we couldn't care less if this doesn't work */ - - return TRUE; -} - -static void -remove_system_searches(xmlDocPtr searches) -{ - xmlNodePtr node; - - /* in pre 2.0, system searches were stored in the user - * searches.xml file with the source set to 'demand'. In 2.0+ - * the system searches are stored in the system - * searchtypes.xml file instead */ - - node = xmlDocGetRootElement(searches); - if (!node->name || strcmp((gchar *)node->name, "filteroptions")) - return; - - if (!(node = xml_find_node(node, "ruleset"))) - return; - - node = node->children; - while (node != NULL) { - xmlNodePtr nnode = node->next; - - if (node->name && !strcmp ((gchar *)node->name, "rule")) { - gchar *src; - - src = (gchar *)xmlGetProp(node, (guchar *)"source"); - if (src && !strcmp((gchar *)src, "demand")) { - xmlUnlinkNode(node); - xmlFreeNodeList(node); - } - xmlFree (src); - } - - node = nnode; - } -} - -static gboolean -em_migrate_1_4 (const gchar *data_dir, xmlDocPtr filters, xmlDocPtr vfolders, GError **error) -{ - EMMigrateSession *session; - CamelException lex; - struct stat st; - gchar *path; - xmlDocPtr searches; - - camel_init (data_dir, TRUE); - camel_provider_init(); - session = (EMMigrateSession *) em_migrate_session_new (data_dir); - - session->srcdir = g_build_filename (g_get_home_dir (), "evolution", "local", NULL); - - path = g_strdup_printf ("mbox:%s/.evolution/mail/local", g_get_home_dir ()); - if (stat (path + 5, &st) == -1) { - if (errno != ENOENT || g_mkdir_with_parents (path + 5, 0777) == -1) { - g_set_error ( - error, E_SHELL_MIGRATE_ERROR, - E_SHELL_MIGRATE_ERROR_FAILED, - _("Failed to create local mail storage " - "`%s': %s"), path + 5, g_strerror (errno)); - g_free (session->srcdir); - camel_object_unref (session); - g_free (path); - return FALSE; - } - } - - camel_exception_init (&lex); - if (!(session->store = camel_session_get_store ((CamelSession *) session, path, &lex))) { - g_set_error ( - error, E_SHELL_MIGRATE_ERROR, - E_SHELL_MIGRATE_ERROR_FAILED, - _("Failed to create local mail storage `%s': %s"), - path, lex.desc); - g_free (session->srcdir); - camel_object_unref (session); - camel_exception_clear (&lex); - g_free (path); - return FALSE; - } - g_free (path); - - if (!em_migrate_local_folders_1_4 (session, error)) - return FALSE; - - camel_object_unref (session->store); - g_free (session->srcdir); - - camel_object_unref (session); - - em_upgrade_accounts_1_4(); - - upgrade_xml_uris(filters, upgrade_xml_uris_1_4); - upgrade_vfolder_sources_1_4(vfolders); - upgrade_xml_uris(vfolders, upgrade_xml_uris_1_4); - - path = g_build_filename(g_get_home_dir(), "evolution", NULL); - searches = emm_load_xml(path, "searches.xml"); - g_free(path); - if (searches) { - remove_system_searches(searches); - emm_save_xml(searches, data_dir, "searches.xml"); - xmlFreeDoc(searches); - } - - if (!em_migrate_pop_uid_caches_1_4 (data_dir, error)) - return FALSE; - - /* these are non-fatal */ - em_migrate_imap_caches_1_4 (data_dir, error); - g_clear_error (error); - em_migrate_folder_expand_state_1_4 (data_dir, error); - g_clear_error (error); - em_migrate_folder_view_settings_1_4 (data_dir, error); - g_clear_error (error); - em_migrate_imap_cmeta_1_4 (data_dir, error); - g_clear_error (error); - - return TRUE; -} - -static void -em_update_accounts_2_11 (void) -{ - EAccountList *accounts; - EIterator *iter; - gboolean changed = FALSE; - - if (!(accounts = e_get_account_list ())) - return; - - iter = e_list_get_iterator ((EList *) accounts); - while (e_iterator_is_valid (iter)) { - EAccount *account = (EAccount *) e_iterator_get (iter); - - if (g_str_has_prefix (account->source->url, "spool://")) { - if (g_file_test (account->source->url + 8, G_FILE_TEST_IS_DIR)) { - gchar *str = g_strdup_printf ("spooldir://%s", account->source->url + 8); - - g_free (account->source->url); - account->source->url = str; - changed = TRUE; - } - } - - e_iterator_next (iter); - } - - g_object_unref (iter); - - if (changed) - e_account_list_save (accounts); -} - -#endif /* !G_OS_WIN32 */ - -static gboolean -emm_setup_initial(const gchar *data_dir) -{ - GDir *dir; - const gchar *d; - gchar *local = NULL, *base; - const gchar * const *language_names; - - /* special-case - this means brand new install of evolution */ - /* FIXME: create default folders and stuff... */ - - d(printf("Setting up initial mail tree\n")); - - base = g_build_filename(data_dir, "local", NULL); - if (g_mkdir_with_parents(base, 0777) == -1 && errno != EEXIST) { - g_free(base); - return FALSE; - } - - /* e.g. try en-AU then en, etc */ - language_names = g_get_language_names (); - while (*language_names != NULL) { - local = g_build_filename ( - EVOLUTION_PRIVDATADIR, "default", - *language_names, "mail", "local", NULL); - if (g_file_test (local, G_FILE_TEST_EXISTS)) - break; - g_free (local); - language_names++; - } - - /* Make sure we found one. */ - g_return_val_if_fail (*language_names != NULL, FALSE); - - dir = g_dir_open(local, 0, NULL); - if (dir) { - while ((d = g_dir_read_name(dir))) { - gchar *src, *dest; - - src = g_build_filename(local, d, NULL); - dest = g_build_filename(base, d, NULL); - - cp(src, dest, FALSE, CP_UNIQUE); - g_free(dest); - g_free(src); - } - g_dir_close(dir); - } - - g_free(local); - g_free(base); - - return TRUE; -} - -static gboolean -is_in_plugs_list (GSList *list, const gchar *value) -{ - GSList *l; - - for (l = list; l; l = l->next) { - if (l->data && !strcmp (l->data, value)) - return TRUE; - } - - return FALSE; -} - -/* - * em_update_message_notify_settings_2_21 - * DBus plugin and sound email notification was merged to mail-notification plugin, - * so move these options to new locations. - */ -static void -em_update_message_notify_settings_2_21 (void) -{ - GConfClient *client; - GConfValue *is_key; - gboolean dbus, status; - GSList *list; - gchar *str; - gint val; - - client = gconf_client_get_default (); - - is_key = gconf_client_get (client, "/apps/evolution/eplugin/mail-notification/dbus-enabled", NULL); - if (is_key) { - /* already migrated, so do not migrate again */ - gconf_value_free (is_key); - g_object_unref (client); - - return; - } - - gconf_client_set_bool (client, "/apps/evolution/eplugin/mail-notification/status-blink-icon", - gconf_client_get_bool (client, "/apps/evolution/mail/notification/blink-status-icon", NULL), NULL); - gconf_client_set_bool (client, "/apps/evolution/eplugin/mail-notification/status-notification", - gconf_client_get_bool (client, "/apps/evolution/mail/notification/notification", NULL), NULL); - - list = gconf_client_get_list (client, "/apps/evolution/eplugin/disabled", GCONF_VALUE_STRING, NULL); - dbus = !is_in_plugs_list (list, "org.gnome.evolution.new_mail_notify"); - status = !is_in_plugs_list (list, "org.gnome.evolution.mail_notification"); - - gconf_client_set_bool (client, "/apps/evolution/eplugin/mail-notification/dbus-enabled", dbus, NULL); - gconf_client_set_bool (client, "/apps/evolution/eplugin/mail-notification/status-enabled", status, NULL); - - if (!status) { - /* enable this plugin, because it holds all those other things */ - GSList *plugins, *l; - - plugins = e_plugin_list_plugins (); - - for (l = plugins; l; l = l->next) { - EPlugin *p = l->data; - - if (p && p->id && !strcmp (p->id, "org.gnome.evolution.mail_notification")) { - e_plugin_enable (p, 1); - break; - } - } - - g_slist_foreach (plugins, (GFunc)g_object_unref, NULL); - g_slist_free (plugins); - } - - g_slist_foreach (list, (GFunc) g_free, NULL); - g_slist_free (list); - - val = gconf_client_get_int (client, "/apps/evolution/mail/notify/type", NULL); - gconf_client_set_bool (client, "/apps/evolution/eplugin/mail-notification/sound-enabled", val == 1 || val == 2, NULL); - gconf_client_set_bool (client, "/apps/evolution/eplugin/mail-notification/sound-beep", val == 0 || val == 1, NULL); - - str = gconf_client_get_string (client, "/apps/evolution/mail/notify/sound", NULL); - gconf_client_set_string (client, "/apps/evolution/eplugin/mail-notification/sound-file", str ? str : "", NULL); - g_free (str); - - g_object_unref (client); -} - -/* fixing typo in SpamAssassin name */ -static void -em_update_sa_junk_setting_2_23 (void) -{ - GConfClient *client; - GConfValue *key; - - client = gconf_client_get_default (); - - key = gconf_client_get (client, "/apps/evolution/mail/junk/default_plugin", NULL); - if (key) { - const gchar *str = gconf_value_get_string (key); - - if (str && strcmp (str, "Spamassasin") == 0) - gconf_client_set_string (client, "/apps/evolution/mail/junk/default_plugin", "SpamAssassin", NULL); - - gconf_value_free (key); - g_object_unref (client); - - return; - } - - g_object_unref (client); -} - -static gboolean -update_progress_in_main_thread (double *progress) -{ - em_migrate_set_progress (*progress); - return FALSE; -} - -static void -migrate_folders(CamelStore *store, gboolean is_local, CamelFolderInfo *fi, const gchar *acc, CamelException *ex, gboolean *done, gint *nth_folder, gint total_folders) -{ - CamelFolder *folder; - - while (fi) { - double progress; - gchar *tmp; - - *nth_folder = *nth_folder + 1; - - tmp = g_strdup_printf ("%s/%s", acc, fi->full_name); - em_migrate_set_folder_name (tmp); - g_free (tmp); - - progress = (double) (*nth_folder) / total_folders; - g_idle_add ((GSourceFunc) update_progress_in_main_thread, &progress); - - if (is_local) - folder = camel_store_get_folder (store, fi->full_name, CAMEL_STORE_IS_MIGRATING, ex); - else - folder = camel_store_get_folder (store, fi->full_name, 0, ex); - - if (folder != NULL) - camel_folder_summary_migrate_infos (folder->summary); - migrate_folders(store, is_local, fi->child, acc, ex, done, nth_folder, total_folders); - fi = fi->next; - } - - if ((*nth_folder) == (total_folders - 1)) - *done = TRUE; -} - -/* This could be in CamelStore.ch */ -static void -count_folders (CamelFolderInfo *fi, gint *count) -{ - while (fi) { - *count = *count + 1; - count_folders (fi->child, count); - fi = fi->next; - } -} - -static CamelStore * -setup_local_store (EShellBackend *shell_backend, - EMMigrateSession *session) -{ - CamelURL *url; - const gchar *data_dir; - gchar *tmp; - CamelStore *store; - - url = camel_url_new("mbox:", NULL); - data_dir = e_shell_backend_get_data_dir (shell_backend); - tmp = g_build_filename (data_dir, "local", NULL); - camel_url_set_path(url, tmp); - g_free(tmp); - tmp = camel_url_to_string(url, 0); - store = (CamelStore *)camel_session_get_service(CAMEL_SESSION (session), tmp, CAMEL_PROVIDER_STORE, NULL); - g_free(tmp); - - return store; -} - -struct migrate_folders_to_db_structure { - gchar *account_name; - CamelException ex; - CamelStore *store; - CamelFolderInfo *info; - gboolean done; - gboolean is_local_store; -}; - -static void -migrate_folders_to_db_thread (struct migrate_folders_to_db_structure *migrate_dbs) -{ - gint num_of_folders = 0, nth_folder = 0; - count_folders (migrate_dbs->info, &num_of_folders); - migrate_folders (migrate_dbs->store, migrate_dbs->is_local_store, migrate_dbs->info, - migrate_dbs->account_name, &(migrate_dbs->ex), &(migrate_dbs->done), - &nth_folder, num_of_folders); -} - -static void -migrate_to_db (EShellBackend *shell_backend) -{ - EMMigrateSession *session; - EAccountList *accounts; - EIterator *iter; - gint i=0, len; - CamelStore *store = NULL; - CamelFolderInfo *info; - const gchar *data_dir; - - if (!(accounts = e_get_account_list ())) - return; - - iter = e_list_get_iterator ((EList *) accounts); - len = e_list_length ((EList *) accounts); - - data_dir = e_shell_backend_get_data_dir (shell_backend); - session = (EMMigrateSession *) em_migrate_session_new (data_dir); - camel_session_set_online ((CamelSession *) session, FALSE); - em_migrate_setup_progress_dialog ( - _("Migrating Folders"), - _("The summary format of the Evolution mailbox " - "folders has been moved to SQLite since Evolution 2.24.\n\nPlease be " - "patient while Evolution migrates your folders...")); - - em_migrate_set_progress ( (double)i/(len+1)); - store = setup_local_store (shell_backend, session); - info = camel_store_get_folder_info (store, NULL, CAMEL_STORE_FOLDER_INFO_RECURSIVE|CAMEL_STORE_FOLDER_INFO_FAST|CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, NULL); - if (info) { - GThread *thread; - struct migrate_folders_to_db_structure migrate_dbs; - - if (g_str_has_suffix (((CamelService *)store)->url->path, ".evolution/mail/local")) - migrate_dbs.is_local_store = TRUE; - else - migrate_dbs.is_local_store = FALSE; - camel_exception_init (&migrate_dbs.ex); - migrate_dbs.account_name = _("On This Computer"); - migrate_dbs.info = info; - migrate_dbs.store = store; - migrate_dbs.done = FALSE; - - thread = g_thread_create ((GThreadFunc) migrate_folders_to_db_thread, &migrate_dbs, TRUE, NULL); - while (!migrate_dbs.done) - g_main_context_iteration (NULL, TRUE); - } - i++; - em_migrate_set_progress ( (double)i/(len+1)); - - - while (e_iterator_is_valid (iter)) { - EAccount *account = (EAccount *) e_iterator_get (iter); - EAccountService *service; - const gchar *name; - - - service = account->source; - name = account->name; - em_migrate_set_progress ( (double)i/(len+1)); - if (account->enabled - && service->url != NULL - && service->url[0] - && strncmp(service->url, "mbox:", 5) != 0) { - - CamelException ex; - - camel_exception_init (&ex); - e_mail_store_add_by_uri (service->url, name); - - store = (CamelStore *) camel_session_get_service (CAMEL_SESSION (session), service->url, CAMEL_PROVIDER_STORE, &ex); - info = camel_store_get_folder_info (store, NULL, CAMEL_STORE_FOLDER_INFO_RECURSIVE|CAMEL_STORE_FOLDER_INFO_FAST|CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, &ex); - if (info) { - GThread *thread; - struct migrate_folders_to_db_structure migrate_dbs; - - migrate_dbs.ex = ex; - migrate_dbs.account_name = account->name; - migrate_dbs.info = info; - migrate_dbs.store = store; - migrate_dbs.done = FALSE; - - thread = g_thread_create ((GThreadFunc) migrate_folders_to_db_thread, &migrate_dbs, TRUE, NULL); - while (!migrate_dbs.done) - g_main_context_iteration (NULL, TRUE); - } else - printf("%s:%s: failed to get folder infos \n", G_STRLOC, G_STRFUNC); - camel_exception_clear(&ex); - - } - i++; - e_iterator_next (iter); - - } - - //camel_session_set_online ((CamelSession *) session, TRUE); - - g_object_unref (iter); - em_migrate_close_progress_dialog (); - - g_object_unref (session); -} - -gboolean -e_mail_shell_migrate (EShellBackend *shell_backend, - gint major, - gint minor, - gint micro, - GError **error) -{ - struct stat st; - const gchar *data_dir; - gchar *path; - - /* make sure ~/.evolution/mail exists */ - data_dir = e_shell_backend_get_data_dir (shell_backend); - if (g_stat (data_dir, &st) == -1) { - if (errno != ENOENT || g_mkdir_with_parents (data_dir, 0777) == -1) { - g_set_error ( - error, E_SHELL_MIGRATE_ERROR, - E_SHELL_MIGRATE_ERROR_FAILED, - _("Unable to create local mail folders at " - "`%s': %s"), data_dir, g_strerror (errno)); - return FALSE; - } - } - - if (major == 0) - return emm_setup_initial (data_dir); - - if (major == 1 && minor < 5) { -#ifndef G_OS_WIN32 - xmlDocPtr config_xmldb = NULL, filters, vfolders; - - path = g_build_filename (g_get_home_dir (), "evolution", NULL); - if (minor <= 2 && !(config_xmldb = emm_load_xml (path, "config.xmldb"))) { - g_set_error ( - error, E_SHELL_MIGRATE_ERROR, - E_SHELL_MIGRATE_ERROR_FAILED, - _("Unable to read settings from previous " - "Evolution install, `evolution/config.xmldb' " - "does not exist or is corrupt.")); - return FALSE; - } - filters = emm_load_xml (path, "filters.xml"); - vfolders = emm_load_xml (path, "vfolders.xml"); - g_free (path); - - if (minor == 0) { - if (!em_migrate_1_0 (data_dir, config_xmldb, filters, vfolders, error)) { - xmlFreeDoc (config_xmldb); - xmlFreeDoc (filters); - xmlFreeDoc (vfolders); - return FALSE; - } - } - - if (minor <= 2) { - if (!em_migrate_1_2 (data_dir, config_xmldb, filters, vfolders, error)) { - xmlFreeDoc (config_xmldb); - xmlFreeDoc (filters); - xmlFreeDoc (vfolders); - return FALSE; - } - - xmlFreeDoc (config_xmldb); - } - - if (minor <= 4) { - if (!em_migrate_1_4 (data_dir, filters, vfolders, error)) { - xmlFreeDoc (filters); - xmlFreeDoc (vfolders); - return FALSE; - } - } - - if (filters) { - emm_save_xml (filters, path, "filters.xml"); - xmlFreeDoc (filters); - } - - if (vfolders) { - emm_save_xml (vfolders, path, "vfolders.xml"); - xmlFreeDoc (vfolders); - } - - g_free (path); -#else - g_error ("Upgrading from ancient versions not supported on Windows"); -#endif - } - - if (major < 2 || (major == 2 && minor < 12)) { -#ifndef G_OS_WIN32 - em_update_accounts_2_11 (); -#else - g_error ("Upgrading from ancient versions not supported on Windows"); -#endif - } - - - if (major < 2 || (major == 2 && minor < 22)) - em_update_message_notify_settings_2_21 (); - - if (major < 2 || (major == 2 && minor < 24)) { - em_update_sa_junk_setting_2_23 (); - migrate_to_db (shell_backend); - } - - return TRUE; -} diff --git a/mail/e-mail-shell-migrate.h b/mail/e-mail-shell-migrate.h deleted file mode 100644 index 8f3057ec0d..0000000000 --- a/mail/e-mail-shell-migrate.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * e-mail-shell-migrate.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_MAIL_SHELL_BACKEND_MIGRATE_H -#define E_MAIL_SHELL_BACKEND_MIGRATE_H - -#include -#include - -G_BEGIN_DECLS - -gboolean e_mail_shell_migrate (EShellBackend *shell_backend, - gint major, - gint minor, - gint micro, - GError **error); - -G_END_DECLS - -#endif /* E_MAIL_SHELL_BACKEND_MIGRATE_H */ diff --git a/mail/e-mail-shell-settings.c b/mail/e-mail-shell-settings.c deleted file mode 100644 index 8237924e3c..0000000000 --- a/mail/e-mail-shell-settings.c +++ /dev/null @@ -1,521 +0,0 @@ -/* - * e-mail-shell-settings.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-mail-shell-settings.h" - -#include -#include - -#include "e-util/e-signature-list.h" -#include "mail/e-mail-label-list-store.h" -#include "mail/mail-session.h" - -void -e_mail_shell_settings_init (EShell *shell) -{ - EShellSettings *shell_settings; - gpointer object; - - shell_settings = e_shell_get_shell_settings (shell); - - /* XXX Default values should match the GConf schema. - * Yes it's redundant, but we're stuck with GConf. */ - - /*** Global Objects ***/ - - e_shell_settings_install_property ( - g_param_spec_object ( - "mail-label-list-store", - NULL, - NULL, - E_TYPE_MAIL_LABEL_LIST_STORE, - G_PARAM_READWRITE)); - - object = e_mail_label_list_store_new (); - e_shell_settings_set_object ( - shell_settings, "mail-label-list-store", object); - g_object_unref (object); - - e_shell_settings_install_property ( - g_param_spec_pointer ( - "mail-session", - NULL, - NULL, - G_PARAM_READWRITE)); - - camel_object_ref (session); - e_shell_settings_set_pointer ( - shell_settings, "mail-session", session); - - /*** Mail Preferences ***/ - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "mail-address-compress", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-address-compress", - "/apps/evolution/mail/display/address_compress"); - - e_shell_settings_install_property ( - g_param_spec_int ( - "mail-address-count", - NULL, - NULL, - G_MININT, - G_MAXINT, - 0, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-address-count", - "/apps/evolution/mail/display/address_count"); - - e_shell_settings_install_property ( - g_param_spec_string ( - "mail-charset-default", - NULL, - NULL, - NULL, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-charset-default", - "/apps/evolution/mail/display/charset"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "mail-check-for-junk", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-check-for-junk", - "/apps/evolution/mail/junk/check_incoming"); - - e_shell_settings_install_property ( - g_param_spec_string ( - "mail-citation-color", - NULL, - NULL, - "#737373", - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-citation-color", - "/apps/evolution/mail/display/citation_colour"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "mail-confirm-expunge", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-confirm-expunge", - "/apps/evolution/mail/prompts/expunge"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "mail-confirm-unwanted-html", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-confirm-unwanted-html", - "/apps/evolution/mail/prompts/unwanted_html"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "mail-empty-trash-on-exit", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-empty-trash-on-exit", - "/apps/evolution/mail/trash/empty_on_exit"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "mail-enable-search-folders", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-enable-search-folders", - "/apps/evolution/mail/display/enable_vfolders"); - - e_shell_settings_install_property ( - g_param_spec_string ( - "mail-font-monospace", - NULL, - NULL, - "", - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-font-monospace", - "/apps/evolution/mail/display/fonts/monospace"); - - e_shell_settings_install_property ( - g_param_spec_string ( - "mail-font-variable", - NULL, - NULL, - "", - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-font-variable", - "/apps/evolution/mail/display/fonts/variable"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "mail-force-message-limit", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-force-message-limit", - "/apps/evolution/mail/display/force_message_limit"); - - /* This value corresponds to MailConfigForwardStyle enum. */ - e_shell_settings_install_property ( - g_param_spec_int ( - "mail-forward-style", - NULL, - NULL, - 0, - G_MAXINT, - 0, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-forward-style", - "/apps/evolution/mail/format/forward_style"); - - /* This value corresponds to MailConfigHTTPMode enum. */ - e_shell_settings_install_property ( - g_param_spec_int ( - "mail-image-loading-policy", - NULL, - NULL, - 0, - G_MAXINT, - 0, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-image-loading-policy", - "/apps/evolution/mail/display/load_http_images"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "mail-magic-spacebar", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-magic-spacebar", - "/apps/evolution/mail/display/magic_spacebar"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "mail-mark-citations", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-mark-citations", - "/apps/evolution/mail/display/mark_citations"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "mail-mark-seen", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-mark-seen", - "/apps/evolution/mail/display/mark_seen"); - - e_shell_settings_install_property ( - g_param_spec_int ( - "mail-mark-seen-timeout", - NULL, - NULL, - G_MININT, - G_MAXINT, - 0, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-mark-seen-timeout", - "/apps/evolution/mail/display/mark_seen_timeout"); - - e_shell_settings_install_property ( - g_param_spec_int ( - "mail-message-text-part-limit", - NULL, - NULL, - G_MININT, - G_MAXINT, - 0, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-message-text-part-limit", - "/apps/evolution/mail/display/message_text_part_limit"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "mail-only-local-photos", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-only-local-photos", - "/apps/evolution/mail/display/photo_local"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "mail-prompt-delete-in-vfolder", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-prompt-delete-in-vfolder", - "/apps/evolution/mail/prompts/delete_in_vfolder"); - - /* This value corresponds to MailConfigReplyStyle enum, - * but the ordering of the combo box items in preferences - * has changed. We use transformation functions there. */ - e_shell_settings_install_property ( - g_param_spec_int ( - "mail-reply-style", - NULL, - NULL, - 0, - G_MAXINT, - 0, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-reply-style", - "/apps/evolution/mail/format/reply_style"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "mail-show-animated-images", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-show-animated-images", - "/apps/evolution/mail/display/animated_images"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "mail-show-sender-photo", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-show-sender-photo", - "/apps/evolution/mail/display/sender_photo"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "mail-use-custom-fonts", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "mail-use-custom-fonts", - "/apps/evolution/mail/display/fonts/use_custom"); - - - /*** Composer Preferences ***/ - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "composer-format-html", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "composer-format-html", - "/apps/evolution/mail/composer/send_html"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "composer-inline-spelling", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "composer-inline-spelling", - "/apps/evolution/mail/composer/inline_spelling"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "composer-magic-links", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "composer-magic-links", - "/apps/evolution/mail/composer/magic_links"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "composer-magic-smileys", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "composer-magic-smileys", - "/apps/evolution/mail/composer/magic_smileys"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "composer-outlook-filenames", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "composer-outlook-filenames", - "/apps/evolution/mail/composer/outlook_filenames"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "composer-prompt-only-bcc", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "composer-prompt-only-bcc", - "/apps/evolution/mail/prompts/only_bcc"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "composer-prompt-empty-subject", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "composer-prompt-empty-subject", - "/apps/evolution/mail/prompts/empty_subject"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "composer-reply-start-bottom", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "composer-reply-start-bottom", - "/apps/evolution/mail/composer/reply_start_bottom"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "composer-request-receipt", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "composer-request-receipt", - "/apps/evolution/mail/composer/request_receipt"); - - e_shell_settings_install_property ( - g_param_spec_string ( - "composer-spell-color", - NULL, - NULL, - "#ff0000", - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "composer-spell-color", - "/apps/evolution/mail/composer/spell_color"); - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "composer-top-signature", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "composer-top-signature", - "/apps/evolution/mail/composer/top_signature"); -} diff --git a/mail/e-mail-shell-settings.h b/mail/e-mail-shell-settings.h deleted file mode 100644 index 4267fd8a60..0000000000 --- a/mail/e-mail-shell-settings.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * e-mail-shell-settings.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_MAIL_SHELL_SETTINGS_H -#define E_MAIL_SHELL_SETTINGS_H - -#include - -G_BEGIN_DECLS - -void e_mail_shell_settings_init (EShell *shell); - -G_END_DECLS - -#endif /* E_MAIL_SHELL_SETTINGS_H */ diff --git a/mail/e-mail-shell-sidebar.c b/mail/e-mail-shell-sidebar.c deleted file mode 100644 index 2e5dffcb96..0000000000 --- a/mail/e-mail-shell-sidebar.c +++ /dev/null @@ -1,644 +0,0 @@ -/* - * e-mail-shell-sidebar.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-mail-shell-sidebar.h" - -#include -#include - -#include "em-utils.h" -#include "em-folder-utils.h" - -#include "e-mail-local.h" -#include "e-mail-store.h" - -#define E_MAIL_SHELL_SIDEBAR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_MAIL_SHELL_SIDEBAR, EMailShellSidebarPrivate)) - -#define STATE_KEY_EXPANDED "Expanded" - -struct _EMailShellSidebarPrivate { - GtkWidget *folder_tree; -}; - -enum { - PROP_0, - PROP_FOLDER_TREE -}; - -static gpointer parent_class; -static GType mail_shell_sidebar_type; - -static void -mail_shell_sidebar_restore_state (EMailShellSidebar *mail_shell_sidebar) -{ - EShellView *shell_view; - EShellSidebar *shell_sidebar; - EMFolderTree *folder_tree; - GtkTreeModel *tree_model; - GtkTreeView *tree_view; - GtkTreeIter iter; - GKeyFile *key_file; - gboolean valid; - gchar *selected; - gchar **groups; - gint ii; - - shell_sidebar = E_SHELL_SIDEBAR (mail_shell_sidebar); - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - key_file = e_shell_view_get_state_key_file (shell_view); - - folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); - - tree_view = GTK_TREE_VIEW (folder_tree); - tree_model = gtk_tree_view_get_model (tree_view); - - /* Restore selected folder. */ - - selected = g_key_file_get_string ( - key_file, "Folder Tree", "Selected", NULL); - if (selected != NULL) { - em_folder_tree_set_selected (folder_tree, selected, FALSE); - g_free (selected); - } - - /* Set the initial folder tree expanded state in two stages: - * - * 1) Iterate over the "Store" and "Folder" state file groups - * and apply the "Expanded" keys where possible. - * - * 2) Iterate over the top-level nodes in the folder tree - * (these are all stores) and expand those that have no - * corresponding "Expanded" key in the state file. This - * ensures that new stores are expanded by default. - */ - - /* Stage 1 */ - - groups = g_key_file_get_groups (key_file, NULL); - - for (ii = 0; groups[ii] != NULL; ii++) { - GtkTreeRowReference *reference; - GtkTreePath *path; - GtkTreeIter iter; - const gchar *group_name = groups[ii]; - const gchar *key = STATE_KEY_EXPANDED; - const gchar *uri; - gboolean expanded; - - if (g_str_has_prefix (group_name, "Store ")) { - uri = group_name + 6; - expanded = TRUE; - } else if (g_str_has_prefix (group_name, "Folder ")) { - uri = group_name + 7; - expanded = FALSE; - } else - continue; - - if (g_key_file_has_key (key_file, group_name, key, NULL)) - expanded = g_key_file_get_boolean ( - key_file, group_name, key, NULL); - - if (!expanded) - continue; - - reference = em_folder_tree_model_lookup_uri ( - EM_FOLDER_TREE_MODEL (tree_model), uri); - if (reference == NULL) - continue; - - path = gtk_tree_row_reference_get_path (reference); - gtk_tree_model_get_iter (tree_model, &iter, path); - gtk_tree_view_expand_row (tree_view, path, FALSE); - gtk_tree_path_free (path); - } - - g_strfreev (groups); - - /* Stage 2 */ - - valid = gtk_tree_model_get_iter_first (tree_model, &iter); - - while (valid) { - const gchar *key = STATE_KEY_EXPANDED; - gchar *group_name; - gchar *uri; - - gtk_tree_model_get ( - tree_model, &iter, COL_STRING_URI, &uri, -1); - - if (uri == NULL) - goto next; - - group_name = g_strdup_printf ("Store %s", uri); - - if (!g_key_file_has_key (key_file, group_name, key, NULL)) { - GtkTreePath *path; - - path = gtk_tree_model_get_path (tree_model, &iter); - gtk_tree_view_expand_row (tree_view, path, FALSE); - gtk_tree_path_free (path); - } - - g_free (group_name); - g_free (uri); - - next: - valid = gtk_tree_model_iter_next (tree_model, &iter); - } -} - -static void -mail_shell_sidebar_row_collapsed_cb (EShellSidebar *shell_sidebar, - GtkTreeIter *iter, - GtkTreePath *path, - GtkTreeView *tree_view) -{ - EShellView *shell_view; - GtkTreeModel *model; - GKeyFile *key_file; - const gchar *key; - gboolean is_folder; - gboolean is_store; - gchar *group_name; - gchar *uri; - - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - key_file = e_shell_view_get_state_key_file (shell_view); - - model = gtk_tree_view_get_model (tree_view); - - gtk_tree_model_get ( - model, iter, - COL_STRING_URI, &uri, - COL_BOOL_IS_STORE, &is_store, - COL_BOOL_IS_FOLDER, &is_folder, -1); - - g_return_if_fail (is_store || is_folder); - - key = STATE_KEY_EXPANDED; - if (is_store) - group_name = g_strdup_printf ("Store %s", uri); - else - group_name = g_strdup_printf ("Folder %s", uri); - - g_key_file_set_boolean (key_file, group_name, key, FALSE); - e_shell_view_set_state_dirty (shell_view); - - g_free (group_name); - g_free (uri); -} - -static void -mail_shell_sidebar_row_expanded_cb (EShellSidebar *shell_sidebar, - GtkTreeIter *unused, - GtkTreePath *path, - GtkTreeView *tree_view) -{ - EShellView *shell_view; - GtkTreeModel *model; - GKeyFile *key_file; - const gchar *key; - gboolean is_folder; - gboolean is_store; - gchar *group_name; - gchar *uri; - - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - key_file = e_shell_view_get_state_key_file (shell_view); - - path = gtk_tree_path_copy (path); - model = gtk_tree_view_get_model (tree_view); - - /* Expand the node and all ancestors. */ - while (gtk_tree_path_get_depth (path) > 0) { - GtkTreeIter iter; - - gtk_tree_model_get_iter (model, &iter, path); - - gtk_tree_model_get ( - model, &iter, - COL_STRING_URI, &uri, - COL_BOOL_IS_STORE, &is_store, - COL_BOOL_IS_FOLDER, &is_folder, -1); - - g_return_if_fail (is_store || is_folder); - - key = STATE_KEY_EXPANDED; - if (is_store) - group_name = g_strdup_printf ("Store %s", uri); - else - group_name = g_strdup_printf ("Folder %s", uri); - - g_key_file_set_boolean (key_file, group_name, key, TRUE); - e_shell_view_set_state_dirty (shell_view); - - g_free (group_name); - g_free (uri); - - gtk_tree_path_up (path); - } - - gtk_tree_path_free (path); -} - -static void -mail_shell_sidebar_model_loaded_row_cb (EMailShellSidebar *mail_shell_sidebar, - GtkTreePath *path, - GtkTreeIter *iter, - GtkTreeModel *model) -{ - EShellSidebar *shell_sidebar; - EShellView *shell_view; - GtkTreeView *tree_view; - GKeyFile *key_file; - gboolean is_folder; - gboolean is_store; - const gchar *key; - gchar *group_name; - gchar *uri; - gboolean expanded; - - shell_sidebar = E_SHELL_SIDEBAR (mail_shell_sidebar); - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - key_file = e_shell_view_get_state_key_file (shell_view); - - tree_view = GTK_TREE_VIEW (mail_shell_sidebar->priv->folder_tree); - - gtk_tree_model_get ( - model, iter, - COL_STRING_URI, &uri, - COL_BOOL_IS_STORE, &is_store, - COL_BOOL_IS_FOLDER, &is_folder, -1); - - g_return_if_fail (is_store || is_folder); - - key = STATE_KEY_EXPANDED; - if (is_store) { - group_name = g_strdup_printf ("Store %s", uri); - expanded = TRUE; - } else { - group_name = g_strdup_printf ("Folder %s", uri); - expanded = FALSE; - } - - if (g_key_file_has_key (key_file, group_name, key, NULL)) - expanded = g_key_file_get_boolean ( - key_file, group_name, key, NULL); - - if (expanded) - gtk_tree_view_expand_row (tree_view, path, FALSE); - - g_free (group_name); - g_free (uri); -} - -static void -mail_shell_sidebar_selection_changed_cb (EShellSidebar *shell_sidebar, - GtkTreeSelection *selection) -{ - EShellView *shell_view; - EShellViewClass *shell_view_class; - GtkTreeModel *model; - GtkTreeIter iter; - GKeyFile *key_file; - const gchar *icon_name; - gchar *display_name = NULL; - gchar *uri = NULL; - gboolean is_folder = FALSE; - guint flags = 0; - - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); - key_file = e_shell_view_get_state_key_file (shell_view); - - if (gtk_tree_selection_get_selected (selection, &model, &iter)) - gtk_tree_model_get ( - model, &iter, - COL_STRING_DISPLAY_NAME, &display_name, - COL_STRING_URI, &uri, - COL_BOOL_IS_FOLDER, &is_folder, - COL_UINT_FLAGS, &flags, -1); - - if (uri != NULL) - g_key_file_set_string ( - key_file, "Folder Tree", "Selected", uri); - else - g_key_file_remove_key ( - key_file, "Folder Tree", "Selected", NULL); - - e_shell_view_set_state_dirty (shell_view); - - if (is_folder) - icon_name = em_folder_utils_get_icon_name (flags); - else { - icon_name = shell_view_class->icon_name; - display_name = g_strdup (shell_view_class->label); - } - - e_shell_sidebar_set_icon_name (shell_sidebar, icon_name); - e_shell_sidebar_set_primary_text (shell_sidebar, display_name); - - g_free (display_name); - g_free (uri); -} - -static void -mail_shell_sidebar_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_FOLDER_TREE: - g_value_set_object ( - value, e_mail_shell_sidebar_get_folder_tree ( - E_MAIL_SHELL_SIDEBAR (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -mail_shell_sidebar_dispose (GObject *object) -{ - EMailShellSidebarPrivate *priv; - - priv = E_MAIL_SHELL_SIDEBAR_GET_PRIVATE (object); - - if (priv->folder_tree != NULL) { - g_object_unref (priv->folder_tree); - priv->folder_tree = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -mail_shell_sidebar_finalize (GObject *object) -{ - EMailShellSidebarPrivate *priv; - - priv = E_MAIL_SHELL_SIDEBAR_GET_PRIVATE (object); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -mail_shell_sidebar_constructed (GObject *object) -{ - EMailShellSidebar *mail_shell_sidebar; - EShellSidebar *shell_sidebar; - EShellView *shell_view; - GtkTreeSelection *selection; - GtkTreeView *tree_view; - GtkTreeModel *model; - GtkWidget *container; - GtkWidget *widget; - - /* Chain up to parent's constructed method. */ - G_OBJECT_CLASS (parent_class)->constructed (object); - - shell_sidebar = E_SHELL_SIDEBAR (object); - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - - mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (object); - - /* Build sidebar widgets. */ - - container = GTK_WIDGET (object); - - widget = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy ( - GTK_SCROLLED_WINDOW (widget), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type ( - GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); - gtk_container_add (GTK_CONTAINER (container), widget); - gtk_widget_show (widget); - - container = widget; - - widget = em_folder_tree_new (); - em_folder_tree_set_excluded (EM_FOLDER_TREE (widget), 0); - em_folder_tree_enable_drag_and_drop (EM_FOLDER_TREE (widget)); - gtk_container_add (GTK_CONTAINER (container), widget); - mail_shell_sidebar->priv->folder_tree = g_object_ref (widget); - gtk_widget_show (widget); - - tree_view = GTK_TREE_VIEW (mail_shell_sidebar->priv->folder_tree); - selection = gtk_tree_view_get_selection (tree_view); - model = gtk_tree_view_get_model (tree_view); - - if (em_folder_tree_model_get_selection ( - EM_FOLDER_TREE_MODEL (model)) == NULL) - mail_shell_sidebar_restore_state (mail_shell_sidebar); - - em_folder_tree_model_set_selection ( - EM_FOLDER_TREE_MODEL (model), selection); - - g_signal_connect_swapped ( - tree_view, "row-collapsed", - G_CALLBACK (mail_shell_sidebar_row_collapsed_cb), - shell_sidebar); - - g_signal_connect_swapped ( - tree_view, "row-expanded", - G_CALLBACK (mail_shell_sidebar_row_expanded_cb), - shell_sidebar); - - g_signal_connect_swapped ( - model, "loaded-row", - G_CALLBACK (mail_shell_sidebar_model_loaded_row_cb), - shell_sidebar); - - g_signal_connect_swapped ( - selection, "changed", - G_CALLBACK (mail_shell_sidebar_selection_changed_cb), - shell_sidebar); -} - -static guint32 -mail_shell_sidebar_check_state (EShellSidebar *shell_sidebar) -{ - EMailShellSidebar *mail_shell_sidebar; - EShellView *shell_view; - EMFolderTree *folder_tree; - GtkTreeSelection *selection; - GtkTreeView *tree_view; - GtkTreeModel *model; - GtkTreeIter iter; - CamelFolder *folder; - CamelStore *local_store; - CamelStore *store; - gchar *full_name; - gchar *uri; - gboolean allows_children = TRUE; - gboolean can_delete = TRUE; - gboolean is_junk = FALSE; - gboolean is_outbox = FALSE; - gboolean is_store; - gboolean is_trash = FALSE; - guint32 folder_flags = 0; - guint32 state = 0; - - shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); - - local_store = e_mail_local_get_store (); - - mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar); - folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); - tree_view = GTK_TREE_VIEW (folder_tree); - - selection = gtk_tree_view_get_selection (tree_view); - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) - return 0; - - gtk_tree_model_get ( - model, &iter, - COL_POINTER_CAMEL_STORE, &store, - COL_STRING_FULL_NAME, &full_name, - COL_BOOL_IS_STORE, &is_store, - COL_UINT_FLAGS, &folder_flags, - COL_STRING_URI, &uri, -1); - - if (!is_store) { - is_junk = (strcmp (full_name, CAMEL_VJUNK_NAME) == 0); - is_trash = (strcmp (full_name, CAMEL_VTRASH_NAME) == 0); - allows_children = !(is_junk || is_trash); - - /* Don't allow deletion of special local folders. */ - if (store == local_store) - can_delete = - (strcmp (full_name, "Drafts") != 0) && - (strcmp (full_name, "Inbox") != 0) && - (strcmp (full_name, "Outbox") != 0) && - (strcmp (full_name, "Sent") != 0) && - (strcmp (full_name, "Templates") != 0); - - folder = em_folder_tree_get_selected_folder (folder_tree); - is_outbox = em_utils_folder_is_outbox (folder, NULL); - can_delete &= !(folder_flags & CAMEL_FOLDER_SYSTEM); - } - - if (allows_children) - state |= E_MAIL_SHELL_SIDEBAR_FOLDER_ALLOWS_CHILDREN; - if (can_delete) - state |= E_MAIL_SHELL_SIDEBAR_FOLDER_CAN_DELETE; - if (is_junk) - state |= E_MAIL_SHELL_SIDEBAR_FOLDER_IS_JUNK; - if (is_outbox) - state |= E_MAIL_SHELL_SIDEBAR_FOLDER_IS_OUTBOX; - if (is_store) - state |= E_MAIL_SHELL_SIDEBAR_FOLDER_IS_STORE; - if (is_trash) - state |= E_MAIL_SHELL_SIDEBAR_FOLDER_IS_TRASH; - - return state; -} - -static void -mail_shell_sidebar_class_init (EMailShellSidebarClass *class) -{ - GObjectClass *object_class; - EShellSidebarClass *shell_sidebar_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (EMailShellSidebarPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->get_property = mail_shell_sidebar_get_property; - object_class->dispose = mail_shell_sidebar_dispose; - object_class->finalize = mail_shell_sidebar_finalize; - object_class->constructed = mail_shell_sidebar_constructed; - - shell_sidebar_class = E_SHELL_SIDEBAR_CLASS (class); - shell_sidebar_class->check_state = mail_shell_sidebar_check_state; - - g_object_class_install_property ( - object_class, - PROP_FOLDER_TREE, - g_param_spec_object ( - "folder-tree", - NULL, - NULL, - EM_TYPE_FOLDER_TREE, - G_PARAM_READABLE)); -} - -static void -mail_shell_sidebar_init (EMailShellSidebar *mail_shell_sidebar) -{ - mail_shell_sidebar->priv = - E_MAIL_SHELL_SIDEBAR_GET_PRIVATE (mail_shell_sidebar); - - /* Postpone widget construction until we have a shell view. */ -} - -GType -e_mail_shell_sidebar_get_type (void) -{ - return mail_shell_sidebar_type; -} - -void -e_mail_shell_sidebar_register_type (GTypeModule *type_module) -{ - static const GTypeInfo type_info = { - sizeof (EMailShellSidebarClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) mail_shell_sidebar_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (EMailShellSidebar), - 0, /* n_preallocs */ - (GInstanceInitFunc) mail_shell_sidebar_init, - NULL /* value_table */ - }; - - mail_shell_sidebar_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_SIDEBAR, - "EMailShellSidebar", &type_info, 0); -} - -GtkWidget * -e_mail_shell_sidebar_new (EShellView *shell_view) -{ - g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - - return g_object_new ( - E_TYPE_MAIL_SHELL_SIDEBAR, - "shell-view", shell_view, NULL); -} - -EMFolderTree * -e_mail_shell_sidebar_get_folder_tree (EMailShellSidebar *mail_shell_sidebar) -{ - g_return_val_if_fail ( - E_IS_MAIL_SHELL_SIDEBAR (mail_shell_sidebar), NULL); - - return EM_FOLDER_TREE (mail_shell_sidebar->priv->folder_tree); -} diff --git a/mail/e-mail-shell-sidebar.h b/mail/e-mail-shell-sidebar.h deleted file mode 100644 index 10a2ff6a2a..0000000000 --- a/mail/e-mail-shell-sidebar.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * e-mail-shell-sidebar.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_MAIL_SHELL_SIDEBAR_H -#define E_MAIL_SHELL_SIDEBAR_H - -#include -#include -#include - -/* Standard GObject macros */ -#define E_TYPE_MAIL_SHELL_SIDEBAR \ - (e_mail_shell_sidebar_get_type ()) -#define E_MAIL_SHELL_SIDEBAR(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_MAIL_SHELL_SIDEBAR, EMailShellSidebar)) -#define E_MAIL_SHELL_SIDEBAR_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_MAIL_SHELL_SIDEBAR, EMailShellSidebarClass)) -#define E_IS_MAIL_SHELL_SIDEBAR(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_MAIL_SHELL_SIDEBAR)) -#define E_IS_MAIL_SHELL_SIDEBAR_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_MAIL_SHELL_SIDEBAR)) -#define E_MAIL_SHELL_SIDEBAR_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_MAIL_SHELL_SIDEBAR, EMailShellSidebarClass)) - -G_BEGIN_DECLS - -typedef struct _EMailShellSidebar EMailShellSidebar; -typedef struct _EMailShellSidebarClass EMailShellSidebarClass; -typedef struct _EMailShellSidebarPrivate EMailShellSidebarPrivate; - -enum { - E_MAIL_SHELL_SIDEBAR_FOLDER_ALLOWS_CHILDREN = 1 << 0, - E_MAIL_SHELL_SIDEBAR_FOLDER_CAN_DELETE = 1 << 1, - E_MAIL_SHELL_SIDEBAR_FOLDER_IS_JUNK = 1 << 2, - E_MAIL_SHELL_SIDEBAR_FOLDER_IS_OUTBOX = 1 << 3, - E_MAIL_SHELL_SIDEBAR_FOLDER_IS_STORE = 1 << 4, - E_MAIL_SHELL_SIDEBAR_FOLDER_IS_TRASH = 1 << 5 -}; - -struct _EMailShellSidebar { - EShellSidebar parent; - EMailShellSidebarPrivate *priv; -}; - -struct _EMailShellSidebarClass { - EShellSidebarClass parent_class; -}; - -GType e_mail_shell_sidebar_get_type (void); -void e_mail_shell_sidebar_register_type - (GTypeModule *type_module); -GtkWidget * e_mail_shell_sidebar_new(EShellView *shell_view); -EMFolderTree * e_mail_shell_sidebar_get_folder_tree - (EMailShellSidebar *mail_shell_sidebar); - -G_END_DECLS - -#endif /* E_MAIL_SHELL_SIDEBAR_H */ diff --git a/mail/e-mail-shell-view-actions.c b/mail/e-mail-shell-view-actions.c deleted file mode 100644 index 25e7d80da3..0000000000 --- a/mail/e-mail-shell-view-actions.c +++ /dev/null @@ -1,1806 +0,0 @@ -/* - * e-mail-shell-view-actions.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-mail-shell-view-private.h" - -#define STATE_KEY_SEARCH_FILTER "SearchFilter" -#define STATE_KEY_SEARCH_SCOPE "SearchScope" -#define STATE_KEY_SEARCH_TEXT "SearchText" - -static void -action_gal_save_custom_view_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EMailShellContent *mail_shell_content; - EShellView *shell_view; - GalViewInstance *view_instance; - - /* All shell views repond to the activation of this action, - * which is defined by EShellWindow. But only the currently - * active shell view proceeds with saving the custom view. */ - shell_view = E_SHELL_VIEW (mail_shell_view); - if (!e_shell_view_is_active (shell_view)) - return; - - mail_shell_content = mail_shell_view->priv->mail_shell_content; - view_instance = e_mail_shell_content_get_view_instance (mail_shell_content); - gal_view_instance_save_as (view_instance); -} - -static void -action_mail_account_disable_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EMailShellSidebar *mail_shell_sidebar; - EMFolderTree *folder_tree; - EAccountList *account_list; - EAccount *account; - gchar *folder_uri; - - mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; - - folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); - folder_uri = em_folder_tree_get_selected_uri (folder_tree); - g_return_if_fail (folder_uri != NULL); - - account_list = e_get_account_list (); - account = mail_config_get_account_by_source_url (folder_uri); - g_return_if_fail (account != NULL); - - if (e_account_list_account_has_proxies (account_list, account)) - e_account_list_remove_account_proxies (account_list, account); - - account->enabled = !account->enabled; - e_account_list_change (account_list, account); - e_mail_store_remove_by_uri (folder_uri); - - if (account->parent_uid != NULL) - e_account_list_remove (account_list, account); - - e_account_list_save (account_list); - - g_free (folder_uri); -} - -static void -action_mail_create_search_folder_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - /* FIXME */ - g_print ("Action: %s\n", gtk_action_get_name (GTK_ACTION (action))); -} - -static void -action_mail_download_foreach_cb (CamelService *service) -{ - if (CAMEL_IS_DISCO_STORE (service) || CAMEL_IS_OFFLINE_STORE (service)) - mail_store_prepare_offline (CAMEL_STORE (service)); -} - -static void -action_mail_download_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - e_mail_store_foreach ((GHFunc) action_mail_download_foreach_cb, NULL); -} - -static void -action_mail_empty_trash_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EShellWindow *shell_window; - EShellView *shell_view; - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - em_utils_empty_trash (GTK_WIDGET (shell_window)); -} - -static void -action_mail_flush_outbox_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - mail_send (); -} - -static void -action_mail_folder_copy_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EMailShellSidebar *mail_shell_sidebar; - CamelFolderInfo *folder_info; - EMFolderTree *folder_tree; - - mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; - folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); - folder_info = em_folder_tree_get_selected_folder_info (folder_tree); - g_return_if_fail (folder_info != NULL); - - /* XXX Leaking folder_info? */ - em_folder_utils_copy_folder (folder_info, FALSE); -} - -static void -action_mail_folder_delete_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EMailShellSidebar *mail_shell_sidebar; - EMFolderTree *folder_tree; - CamelFolder *folder; - - mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; - folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); - folder = em_folder_tree_get_selected_folder (folder_tree); - g_return_if_fail (folder != NULL); - - em_folder_utils_delete_folder (folder); -} - -static void -action_mail_folder_expunge_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EMailReader *reader; - MessageList *message_list; - EShellWindow *shell_window; - EShellView *shell_view; - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - g_return_if_fail (message_list->folder != NULL); - - em_utils_expunge_folder ( - GTK_WIDGET (shell_window), message_list->folder); -} - -static void -action_mail_folder_mark_all_as_read_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EMailReader *reader; - MessageList *message_list; - EShellWindow *shell_window; - EShellView *shell_view; - CamelFolder *folder; - GtkWindow *parent; - GPtrArray *uids; - const gchar *key; - const gchar *prompt; - guint ii; - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - parent = GTK_WINDOW (shell_window); - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - folder = message_list->folder; - g_return_if_fail (folder != NULL); - - key = "/apps/evolution/mail/prompts/mark_all_read"; - prompt = "mail:ask-mark-all-read"; - - if (!em_utils_prompt_user (parent, key, prompt, NULL)) - return; - - uids = message_list_get_uids (message_list); - - camel_folder_freeze (folder); - for (ii = 0; ii < uids->len; ii++) - camel_folder_set_message_flags ( - folder, uids->pdata[ii], - CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); - camel_folder_thaw (folder); - - message_list_free_uids (message_list, uids); -} - -static void -action_mail_folder_move_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EMailShellSidebar *mail_shell_sidebar; - CamelFolderInfo *folder_info; - EMFolderTree *folder_tree; - - mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; - folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); - folder_info = em_folder_tree_get_selected_folder_info (folder_tree); - g_return_if_fail (folder_info != NULL); - - /* XXX Leaking folder_info? */ - em_folder_utils_copy_folder (folder_info, TRUE); -} - -static void -action_mail_folder_new_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - EMailShellSidebar *mail_shell_sidebar; - CamelFolderInfo *folder_info; - EMFolderTree *folder_tree; - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; - folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); - folder_info = em_folder_tree_get_selected_folder_info (folder_tree); - g_return_if_fail (folder_info != NULL); - - em_folder_utils_create_folder ( - folder_info, folder_tree, GTK_WINDOW (shell_window)); - camel_folder_info_free (folder_info); -} - -static void -action_mail_folder_properties_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EMailShellSidebar *mail_shell_sidebar; - EMFolderTree *folder_tree; - EShellView *shell_view; - GtkTreeSelection *selection; - GtkTreeView *tree_view; - GtkTreeModel *model; - GtkTreeIter iter; - gchar *uri; - - shell_view = E_SHELL_VIEW (mail_shell_view); - mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; - folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); - - tree_view = GTK_TREE_VIEW (folder_tree); - selection = gtk_tree_view_get_selection (tree_view); - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) - return; - - gtk_tree_model_get (model, &iter, COL_STRING_URI, &uri, -1); - em_folder_properties_show (shell_view, NULL, uri); - g_free (uri); -} - -static void -action_mail_folder_refresh_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EMailShellSidebar *mail_shell_sidebar; - EMFolderTree *folder_tree; - CamelFolder *folder; - - mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; - folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); - folder = em_folder_tree_get_selected_folder (folder_tree); - g_return_if_fail (folder != NULL); - - mail_refresh_folder (folder, NULL, NULL); -} - -static void -action_mail_folder_rename_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EMailShellSidebar *mail_shell_sidebar; - EMFolderTree *folder_tree; - CamelFolder *folder; - - mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; - folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); - folder = em_folder_tree_get_selected_folder (folder_tree); - g_return_if_fail (folder != NULL); - - em_folder_utils_rename_folder (folder); -} - -/* Helper for action_mail_folder_select_all_cb() */ -static gboolean -action_mail_folder_select_all_timeout_cb (MessageList *message_list) -{ - message_list_select_all (message_list); - gtk_widget_grab_focus (GTK_WIDGET (message_list)); - - return FALSE; -} - -static void -action_mail_folder_select_all_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EMailReader *reader; - MessageList *message_list; - EShellWindow *shell_window; - EShellView *shell_view; - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - - if (message_list->threaded) { - gtk_action_activate (ACTION (MAIL_THREADS_EXPAND_ALL)); - - /* XXX The timeout below is added so that the execution - * thread to expand all conversation threads would - * have completed. The timeout 505 is just to ensure - * that the value is a small delta more than the - * timeout value in mail_regen_list(). */ - g_timeout_add ( - 505, (GSourceFunc) - action_mail_folder_select_all_timeout_cb, - message_list); - } else - /* If there is no threading, just select all immediately. */ - action_mail_folder_select_all_timeout_cb (message_list); -} - -static void -action_mail_folder_select_thread_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - MessageList *message_list; - EMailReader *reader; - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - - message_list_select_thread (message_list); -} - -static void -action_mail_folder_select_subthread_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - MessageList *message_list; - EMailReader *reader; - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - - message_list_select_subthread (message_list); -} - -static void -action_mail_hide_deleted_cb (GtkToggleAction *action, - EMailShellView *mail_shell_view) -{ - MessageList *message_list; - EMailReader *reader; - gboolean active; - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - - active = gtk_toggle_action_get_active (action); - message_list_set_hidedeleted (message_list, active); -} - -static void -action_mail_hide_read_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - MessageList *message_list; - EMailReader *reader; - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - - message_list_hide_add ( - message_list, - "(match-all (system-flag \"seen\"))", - ML_HIDE_SAME, ML_HIDE_SAME); -} - -static void -action_mail_hide_selected_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - MessageList *message_list; - EMailReader *reader; - GPtrArray *uids; - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - - uids = message_list_get_selected (message_list); - message_list_hide_uids (message_list, uids); - message_list_free_uids (message_list, uids); -} - -static void -action_mail_label_cb (GtkToggleAction *action, - EMailShellView *mail_shell_view) -{ - EMailReader *reader; - MessageList *message_list; - CamelFolder *folder; - GPtrArray *uids; - const gchar *tag; - gint ii; - - tag = g_object_get_data (G_OBJECT (action), "tag"); - g_return_if_fail (tag != NULL); - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - folder = message_list->folder; - - uids = message_list_get_selected (message_list); - - for (ii = 0; ii < uids->len; ii++) { - if (gtk_toggle_action_get_active (action)) - camel_folder_set_message_user_flag ( - folder, uids->pdata[ii], tag, TRUE); - else { - camel_folder_set_message_user_flag ( - folder, uids->pdata[ii], tag, FALSE); - camel_folder_set_message_user_tag ( - folder, uids->pdata[ii], "label", NULL); - } - } - - message_list_free_uids (message_list, uids); -} - -static void -action_mail_label_new_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EShell *shell; - EShellSettings *shell_settings; - EShellWindow *shell_window; - EShellView *shell_view; - EMailLabelDialog *label_dialog; - EMailLabelListStore *store; - EMailReader *reader; - MessageList *message_list; - CamelFolder *folder; - GtkTreeModel *model; - GtkTreeIter iter; - GtkWidget *dialog; - GPtrArray *uids; - GdkColor label_color; - const gchar *property_name; - const gchar *label_name; - gchar *label_tag; - gint n_children; - guint ii; - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - dialog = e_mail_label_dialog_new (GTK_WINDOW (shell_window)); - - gtk_window_set_title (GTK_WINDOW (dialog), _("Add Label")); - - if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) - goto exit; - - shell = e_shell_window_get_shell (shell_window); - shell_settings = e_shell_get_shell_settings (shell); - - label_dialog = E_MAIL_LABEL_DIALOG (dialog); - label_name = e_mail_label_dialog_get_label_name (label_dialog); - e_mail_label_dialog_get_label_color (label_dialog, &label_color); - - property_name = "mail-label-list-store"; - store = e_shell_settings_get_object (shell_settings, property_name); - e_mail_label_list_store_set (store, NULL, label_name, &label_color); - g_object_unref (store); - - /* XXX This is awkward. We've added a new label to the list store - * but we don't have the new label's tag nor an iterator to use - * to fetch it. We know the label was appended to the store, - * so we have to dig it out manually. EMailLabelListStore API - * probably needs some rethinking. */ - model = GTK_TREE_MODEL (store); - n_children = gtk_tree_model_iter_n_children (model, NULL); - gtk_tree_model_iter_nth_child (model, &iter, NULL, n_children - 1); - label_tag = e_mail_label_list_store_get_tag (store, &iter); - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - folder = message_list->folder; - - uids = message_list_get_selected (message_list); - - for (ii = 0; ii < uids->len; ii++) - camel_folder_set_message_user_flag ( - folder, uids->pdata[ii], label_tag, TRUE); - - message_list_free_uids (message_list, uids); - - g_free (label_tag); - -exit: - gtk_widget_destroy (dialog); -} - -static void -action_mail_label_none_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EShell *shell; - EShellView *shell_view; - EShellSettings *shell_settings; - EShellWindow *shell_window; - EMailReader *reader; - MessageList *message_list; - GtkTreeModel *tree_model; - CamelFolder *folder; - GtkTreeIter iter; - GPtrArray *uids; - gboolean valid; - guint ii; - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell = e_shell_window_get_shell (shell_window); - shell_settings = e_shell_get_shell_settings (shell); - - tree_model = e_shell_settings_get_object ( - shell_settings, "mail-label-list-store"); - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - uids = message_list_get_selected (message_list); - folder = message_list->folder; - - valid = gtk_tree_model_get_iter_first (tree_model, &iter); - - while (valid) { - gchar *tag; - - tag = e_mail_label_list_store_get_tag ( - E_MAIL_LABEL_LIST_STORE (tree_model), &iter); - - for (ii = 0; ii < uids->len; ii++) { - camel_folder_set_message_user_flag ( - folder, uids->pdata[ii], tag, FALSE); - camel_folder_set_message_user_tag ( - folder, uids->pdata[ii], "label", NULL); - } - - g_free (tag); - - valid = gtk_tree_model_iter_next (tree_model, &iter); - } - - message_list_free_uids (message_list, uids); -} - -static void -action_mail_search_cb (GtkRadioAction *action, - GtkRadioAction *current, - EMailShellView *mail_shell_view) -{ - EShellView *shell_view; - EShellContent *shell_content; - const gchar *search_hint; - - /* XXX Figure out a way to handle this in EShellContent - * instead of every shell view having to handle it. - * The problem is EShellContent does not know what - * the search option actions are for this view. It - * would have to dig up the popup menu and retrieve - * the action for each menu item. Seems messy. */ - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - - search_hint = gtk_action_get_label (GTK_ACTION (current)); - e_shell_content_set_search_hint (shell_content, search_hint); -} - -static void -action_mail_show_hidden_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - MessageList *message_list; - EMailReader *reader; - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - - message_list_hide_clear (message_list); -} - -static void -action_mail_smart_backward_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EShell *shell; - EShellView *shell_view; - EShellWindow *shell_window; - EShellSettings *shell_settings; - EMailShellSidebar *mail_shell_sidebar; - EMFolderTree *folder_tree; - EMFormatHTMLDisplay *html_display; - EMailReader *reader; - MessageList *message_list; - GtkToggleAction *toggle_action; - GtkHTML *html; - gboolean caret_mode; - gboolean magic_spacebar; - - /* This implements the so-called "Magic Backspace". */ - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell = e_shell_window_get_shell (shell_window); - shell_settings = e_shell_get_shell_settings (shell); - - mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; - folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - html_display = e_mail_reader_get_html_display (reader); - message_list = e_mail_reader_get_message_list (reader); - - magic_spacebar = e_shell_settings_get_boolean ( - shell_settings, "mail-magic-spacebar"); - - toggle_action = GTK_TOGGLE_ACTION (ACTION (MAIL_CARET_MODE)); - caret_mode = gtk_toggle_action_get_active (toggle_action); - - html = EM_FORMAT_HTML (html_display)->html; - - if (gtk_html_command (html, "scroll-backward")) - return; - - if (caret_mode || !magic_spacebar) - return; - - /* XXX Are two separate calls really necessary? */ - - if (message_list_select ( - message_list, MESSAGE_LIST_SELECT_PREVIOUS, - 0, CAMEL_MESSAGE_SEEN)) - return; - - if (message_list_select ( - message_list, MESSAGE_LIST_SELECT_PREVIOUS | - MESSAGE_LIST_SELECT_WRAP, 0, CAMEL_MESSAGE_SEEN)) - return; - - em_folder_tree_select_prev_path (folder_tree, TRUE); - - gtk_widget_grab_focus (GTK_WIDGET (message_list)); -} - -static void -action_mail_smart_forward_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EShell *shell; - EShellView *shell_view; - EShellWindow *shell_window; - EShellSettings *shell_settings; - EMailShellSidebar *mail_shell_sidebar; - EMFolderTree *folder_tree; - EMFormatHTMLDisplay *html_display; - EMailReader *reader; - MessageList *message_list; - GtkToggleAction *toggle_action; - GtkHTML *html; - gboolean caret_mode; - gboolean magic_spacebar; - - /* This implements the so-called "Magic Spacebar". */ - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell = e_shell_window_get_shell (shell_window); - shell_settings = e_shell_get_shell_settings (shell); - - mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; - folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - html_display = e_mail_reader_get_html_display (reader); - message_list = e_mail_reader_get_message_list (reader); - - magic_spacebar = e_shell_settings_get_boolean ( - shell_settings, "mail-magic-spacebar"); - - toggle_action = GTK_TOGGLE_ACTION (ACTION (MAIL_CARET_MODE)); - caret_mode = gtk_toggle_action_get_active (toggle_action); - - html = EM_FORMAT_HTML (html_display)->html; - - if (gtk_html_command (html, "scroll-forward")) - return; - - if (caret_mode || !magic_spacebar) - return; - - /* XXX Are two separate calls really necessary? */ - - if (message_list_select ( - message_list, MESSAGE_LIST_SELECT_NEXT, - 0, CAMEL_MESSAGE_SEEN)) - return; - - if (message_list_select ( - message_list, MESSAGE_LIST_SELECT_NEXT | - MESSAGE_LIST_SELECT_WRAP, 0, CAMEL_MESSAGE_SEEN)) - return; - - em_folder_tree_select_next_path (folder_tree, TRUE); - - gtk_widget_grab_focus (GTK_WIDGET (message_list)); -} - -static void -action_mail_stop_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - mail_cancel_all (); -} - -static void -action_mail_threads_collapse_all_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - MessageList *message_list; - EMailReader *reader; - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - - message_list_set_threaded_collapse_all (message_list); -} - -static void -action_mail_threads_expand_all_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - MessageList *message_list; - EMailReader *reader; - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - - message_list_set_threaded_expand_all (message_list); -} - -static void -action_mail_threads_group_by_cb (GtkToggleAction *action, - EMailShellView *mail_shell_view) -{ - EMailShellContent *mail_shell_content; - MessageList *message_list; - EMailReader *reader; - gboolean active; - - mail_shell_content = mail_shell_view->priv->mail_shell_content; - active = gtk_toggle_action_get_active (action); - - reader = E_MAIL_READER (mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - - message_list_set_threaded (message_list, active); -} - -static void -action_mail_tools_filters_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EShellWindow *shell_window; - EShellView *shell_view; - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - em_utils_edit_filters (GTK_WIDGET (shell_window)); -} - -static void -action_mail_tools_search_folders_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - vfolder_edit (E_SHELL_VIEW (mail_shell_view)); -} - -static void -action_mail_tools_subscriptions_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EShellWindow *shell_window; - EShellView *shell_view; - GtkWidget *dialog; - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - dialog = em_subscribe_editor_new (); - gtk_window_set_transient_for ( - GTK_WINDOW (dialog), GTK_WINDOW (shell_window)); - gtk_dialog_run (GTK_DIALOG (dialog)); - /* XXX Dialog destroys itself. */ -} - -static void -action_mail_view_cb (GtkRadioAction *action, - GtkRadioAction *current, - EMailShellView *mail_shell_view) -{ - EMailShellContent *mail_shell_content; - gboolean vertical_view; - - mail_shell_content = mail_shell_view->priv->mail_shell_content; - vertical_view = (gtk_radio_action_get_current_value (action) == 1); - - e_mail_shell_content_set_vertical_view ( - mail_shell_content, vertical_view); -} - -static void -action_search_execute_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EShellView *shell_view; - EShellContent *shell_content; - EMailReader *reader; - MessageList *message_list; - GKeyFile *key_file; - const gchar *folder_uri; - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - key_file = e_shell_view_get_state_key_file (shell_view); - - /* All shell views respond to the activation of this action, - * which is defined by EShellWindow. But only the currently - * active shell view proceeds with executing the search. */ - if (!e_shell_view_is_active (shell_view)) - return; - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - folder_uri = message_list->folder_uri; - - if (folder_uri != NULL) { - const gchar *key; - const gchar *string; - gchar *group_name; - - key = STATE_KEY_SEARCH_TEXT; - string = e_shell_content_get_search_text (shell_content); - group_name = g_strdup_printf ("Folder %s", folder_uri); - - if (string != NULL && *string != '\0') - g_key_file_set_string ( - key_file, group_name, key, string); - else - g_key_file_remove_key ( - key_file, group_name, key, NULL); - e_shell_view_set_state_dirty (shell_view); - - g_free (group_name); - } - - e_mail_shell_view_execute_search (mail_shell_view); -} - -static void -action_search_filter_cb (GtkRadioAction *action, - GtkRadioAction *current, - EMailShellView *mail_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - EMailReader *reader; - MessageList *message_list; - GKeyFile *key_file; - const gchar *folder_uri; - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - key_file = e_shell_view_get_state_key_file (shell_view); - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - folder_uri = message_list->folder_uri; - - if (folder_uri != NULL) { - const gchar *key; - const gchar *string; - gchar *group_name; - - key = STATE_KEY_SEARCH_FILTER; - string = gtk_action_get_name (GTK_ACTION (current)); - group_name = g_strdup_printf ("Folder %s", folder_uri); - - g_key_file_set_string (key_file, group_name, key, string); - e_shell_view_set_state_dirty (shell_view); - - g_free (group_name); - } - - gtk_action_activate (ACTION (SEARCH_EXECUTE)); -} - -static void -action_search_scope_cb (GtkRadioAction *action, - GtkRadioAction *current, - EMailShellView *mail_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - EMailReader *reader; - MessageList *message_list; - GKeyFile *key_file; - const gchar *folder_uri; - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - key_file = e_shell_view_get_state_key_file (shell_view); - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - folder_uri = message_list->folder_uri; - - if (folder_uri != NULL) { - const gchar *key; - const gchar *string; - gchar *group_name; - - key = STATE_KEY_SEARCH_SCOPE; - string = gtk_action_get_name (GTK_ACTION (current)); - group_name = g_strdup_printf ("Folder %s", folder_uri); - - g_key_file_set_string (key_file, group_name, key, string); - e_shell_view_set_state_dirty (shell_view); - - g_free (group_name); - } - - gtk_action_activate (ACTION (SEARCH_EXECUTE)); -} - -static GtkActionEntry mail_entries[] = { - - { "mail-account-disable", - NULL, - N_("_Disable Account"), - NULL, - N_("Disable this account"), - G_CALLBACK (action_mail_account_disable_cb) }, - - { "mail-create-search-folder", - NULL, - N_("C_reate Search Folder From Search..."), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_mail_create_search_folder_cb) }, - - { "mail-download", - NULL, - N_("_Download Messages for Offline Usage"), - NULL, - N_("Download messages of accounts and folders marked for offline"), - G_CALLBACK (action_mail_download_cb) }, - - { "mail-empty-trash", - NULL, - N_("Empty _Trash"), - NULL, - N_("Permanently remove all the deleted messages from all folders"), - G_CALLBACK (action_mail_empty_trash_cb) }, - - { "mail-flush-outbox", - "mail-send", - N_("Fl_ush Outbox"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_mail_flush_outbox_cb) }, - - { "mail-folder-copy", - "folder-copy", - N_("_Copy Folder To..."), - NULL, - N_("Copy the selected folder into another folder"), - G_CALLBACK (action_mail_folder_copy_cb) }, - - { "mail-folder-delete", - GTK_STOCK_DELETE, - NULL, - NULL, - N_("Permanently remove this folder"), - G_CALLBACK (action_mail_folder_delete_cb) }, - - { "mail-folder-expunge", - NULL, - N_("E_xpunge"), - "e", - N_("Permanently remove all deleted messages from this folder"), - G_CALLBACK (action_mail_folder_expunge_cb) }, - - { "mail-folder-mark-all-as-read", - "mail-read", - N_("Mar_k All Messages as Read"), - NULL, - N_("Mark all messages in the folder as read"), - G_CALLBACK (action_mail_folder_mark_all_as_read_cb) }, - - { "mail-folder-move", - "folder-move", - N_("_Move Folder To..."), - NULL, - N_("Move the selected folder into another folder"), - G_CALLBACK (action_mail_folder_move_cb) }, - - { "mail-folder-new", - "folder-new", - N_("_New..."), - NULL, - N_("Create a new folder for storing mail"), - G_CALLBACK (action_mail_folder_new_cb) }, - - { "mail-folder-properties", - GTK_STOCK_PROPERTIES, - NULL, - NULL, - N_("Change the properties of this folder"), - G_CALLBACK (action_mail_folder_properties_cb) }, - - { "mail-folder-refresh", - GTK_STOCK_REFRESH, - NULL, - "F5", - N_("Refresh the folder"), - G_CALLBACK (action_mail_folder_refresh_cb) }, - - { "mail-folder-rename", - NULL, - N_("_Rename..."), - "F2", - N_("Change the name of this folder"), - G_CALLBACK (action_mail_folder_rename_cb) }, - - { "mail-folder-select-all", - NULL, - N_("Select _All Messages"), - "a", - N_("Select all visible messages"), - G_CALLBACK (action_mail_folder_select_all_cb) }, - - { "mail-folder-select-thread", - NULL, - N_("Select Message _Thread"), - "h", - N_("Select all messages in the same thread as the selected message"), - G_CALLBACK (action_mail_folder_select_thread_cb) }, - - { "mail-folder-select-subthread", - NULL, - N_("Select Message S_ubthread"), - "h", - N_("Select all replies to the currently selected message"), - G_CALLBACK (action_mail_folder_select_subthread_cb) }, - - { "mail-label-new", - NULL, - N_("_New Label"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_mail_label_new_cb) }, - - { "mail-label-none", - NULL, - N_("N_one"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_mail_label_none_cb) }, - - { "mail-hide-read", - NULL, - N_("Hide _Read Messages"), - NULL, - N_("Temporarily hide all messages that have already been read"), - G_CALLBACK (action_mail_hide_read_cb) }, - - { "mail-hide-selected", - NULL, - N_("Hide S_elected Messages"), - NULL, - N_("Temporarily hide the selected messages"), - G_CALLBACK (action_mail_hide_selected_cb) }, - - { "mail-show-hidden", - NULL, - N_("Show Hidde_n Messages"), - NULL, - N_("Show messages that have been temporarily hidden"), - G_CALLBACK (action_mail_show_hidden_cb) }, - - { "mail-smart-backward", - NULL, - NULL, /* No menu item; key press only */ - NULL, - NULL, - G_CALLBACK (action_mail_smart_backward_cb) }, - - { "mail-smart-forward", - NULL, - NULL, /* No menu item; key press only */ - NULL, - NULL, - G_CALLBACK (action_mail_smart_forward_cb) }, - - { "mail-stop", - GTK_STOCK_STOP, - N_("Cancel"), - NULL, - N_("Cancel the current mail operation"), - G_CALLBACK (action_mail_stop_cb) }, - - { "mail-threads-collapse-all", - NULL, - N_("Collapse All _Threads"), - "b", - N_("Collapse all message threads"), - G_CALLBACK (action_mail_threads_collapse_all_cb) }, - - { "mail-threads-expand-all", - NULL, - N_("E_xpand All Threads"), - NULL, - N_("Expand all message threads"), - G_CALLBACK (action_mail_threads_expand_all_cb) }, - - { "mail-tools-filters", - NULL, - N_("_Message Filters"), - NULL, - N_("Create or edit rules for filtering new mail"), - G_CALLBACK (action_mail_tools_filters_cb) }, - - { "mail-tools-search-folders", - NULL, - N_("Search F_olders"), - NULL, - N_("Create or edit search folder definitions"), - G_CALLBACK (action_mail_tools_search_folders_cb) }, - - { "mail-tools-subscriptions", - NULL, - N_("_Subscriptions..."), - NULL, - N_("Subscribe or unsubscribe to folders on remote servers"), - G_CALLBACK (action_mail_tools_subscriptions_cb) }, - - /*** Menus ***/ - - { "mail-folder-menu", - NULL, - N_("F_older"), - NULL, - NULL, - NULL }, - - { "mail-label-menu", - NULL, - N_("_Label"), - NULL, - NULL, - NULL }, - - { "mail-preview-menu", - NULL, - N_("_Preview"), - NULL, - NULL, - NULL } -}; - -static EPopupActionEntry mail_popup_entries[] = { - - { "mail-popup-account-disable", - NULL, - "mail-account-disable" }, - - { "mail-popup-empty-trash", - NULL, - "mail-empty-trash" }, - - { "mail-popup-flush-outbox", - NULL, - "mail-flush-outbox" }, - - { "mail-popup-folder-copy", - NULL, - "mail-folder-copy" }, - - { "mail-popup-folder-delete", - NULL, - "mail-folder-delete" }, - - { "mail-popup-folder-move", - NULL, - "mail-folder-move" }, - - { "mail-popup-folder-new", - N_("_New Folder..."), - "mail-folder-new" }, - - { "mail-popup-folder-properties", - NULL, - "mail-folder-properties" }, - - { "mail-popup-folder-refresh", - NULL, - "mail-folder-refresh" }, - - { "mail-popup-folder-rename", - NULL, - "mail-folder-rename" } -}; - -static GtkToggleActionEntry mail_toggle_entries[] = { - - { "mail-hide-deleted", - NULL, - N_("Hide _Deleted Messages"), - NULL, - N_("Hide deleted messages rather than displaying " - "them with a line through them"), - G_CALLBACK (action_mail_hide_deleted_cb), - TRUE }, - - { "mail-preview", - NULL, - N_("Show Message _Preview"), - "m", - N_("Show message preview pane"), - NULL, /* Handled by property bindings */ - TRUE }, - - { "mail-threads-group-by", - NULL, - N_("_Group By Threads"), - "t", - N_("Threaded message list"), - G_CALLBACK (action_mail_threads_group_by_cb), - FALSE } -}; - -static GtkRadioActionEntry mail_view_entries[] = { - - /* This action represents the initial active mail view. - * It should not be visible in the UI, nor should it be - * possible to switch to it from another shell view. */ - { "mail-view-internal", - NULL, - NULL, - NULL, - NULL, - -1 }, - - { "mail-view-classic", - NULL, - N_("_Classic View"), - NULL, - N_("Show message preview below the message list"), - 0 }, - - { "mail-view-vertical", - NULL, - N_("_Vertical View"), - NULL, - N_("Show message preview alongside the message list"), - 1 } -}; - -static GtkRadioActionEntry mail_filter_entries[] = { - - { "mail-filter-all-messages", - NULL, - N_("All Messages"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_ALL_MESSAGES }, - - { "mail-filter-important-messages", - "emblem-important", - N_("Important Messages"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_IMPORTANT_MESSAGES }, - - { "mail-filter-last-5-days-messages", - NULL, - N_("Last 5 Days' Messages"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_LAST_5_DAYS_MESSAGES }, - - { "mail-filter-messages-not-junk", - "mail-mark-notjunk", - N_("Messages Not Junk"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_MESSAGES_NOT_JUNK }, - - { "mail-filter-messages-with-attachments", - "mail-attachment", - N_("Messages with Attachments"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS }, - - { "mail-filter-no-label", - NULL, - N_("No Label"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_NO_LABEL }, - - { "mail-filter-read-messages", - "mail-read", - N_("Read Messages"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_READ_MESSAGES }, - - { "mail-filter-recent-messages", - NULL, - N_("Recent Messages"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_RECENT_MESSAGES }, - - { "mail-filter-unread-messages", - "mail-unread", - N_("Unread Messages"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_UNREAD_MESSAGES } -}; - -static GtkRadioActionEntry mail_search_entries[] = { - - { "mail-search-body-contains", - NULL, - N_("Body contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SEARCH_BODY_CONTAINS }, - - { "mail-search-message-contains", - NULL, - N_("Message contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SEARCH_MESSAGE_CONTAINS }, - - { "mail-search-recipients-contain", - NULL, - N_("Recipients contain"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SEARCH_RECIPIENTS_CONTAIN }, - - { "mail-search-sender-contains", - NULL, - N_("Sender contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SEARCH_SENDER_CONTAINS }, - - { "mail-search-subject-contains", - NULL, - N_("Subject contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SEARCH_SUBJECT_CONTAINS }, - - { "mail-search-subject-or-recipients-contains", - NULL, - N_("Subject or Recipients contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SEARCH_SUBJECT_OR_RECIPIENTS_CONTAINS }, - - { "mail-search-subject-or-sender-contains", - NULL, - N_("Subject or Sender contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SEARCH_SUBJECT_OR_SENDER_CONTAINS } -}; - -static GtkRadioActionEntry mail_scope_entries[] = { - - { "mail-scope-all-accounts", - NULL, - N_("All Accounts"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SCOPE_ALL_ACCOUNTS }, - - { "mail-scope-current-account", - NULL, - N_("Current Account"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SCOPE_CURRENT_ACCOUNT }, - - { "mail-scope-current-folder", - NULL, - N_("Current Folder"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SCOPE_CURRENT_FOLDER } -}; - -void -e_mail_shell_view_actions_init (EMailShellView *mail_shell_view) -{ - EShellView *shell_view; - EShellWindow *shell_window; - EShellContent *shell_content; - GtkActionGroup *action_group; - GtkRadioAction *radio_action; - GConfBridge *bridge; - GObject *object; - GObject *src_object; - GObject *dst_object; - const gchar *key; - - g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - - /* Mail Actions */ - action_group = ACTION_GROUP (MAIL); - gtk_action_group_add_actions ( - action_group, mail_entries, - G_N_ELEMENTS (mail_entries), mail_shell_view); - e_action_group_add_popup_actions ( - action_group, mail_popup_entries, - G_N_ELEMENTS (mail_popup_entries)); - gtk_action_group_add_toggle_actions ( - action_group, mail_toggle_entries, - G_N_ELEMENTS (mail_toggle_entries), mail_shell_view); - gtk_action_group_add_radio_actions ( - action_group, mail_view_entries, - G_N_ELEMENTS (mail_view_entries), -1, - G_CALLBACK (action_mail_view_cb), mail_shell_view); - gtk_action_group_add_radio_actions ( - action_group, mail_search_entries, - G_N_ELEMENTS (mail_search_entries), - MAIL_SEARCH_SUBJECT_OR_SENDER_CONTAINS, - G_CALLBACK (action_mail_search_cb), mail_shell_view); - gtk_action_group_add_radio_actions ( - action_group, mail_scope_entries, - G_N_ELEMENTS (mail_scope_entries), - MAIL_SCOPE_CURRENT_FOLDER, - G_CALLBACK (action_search_scope_cb), mail_shell_view); - - radio_action = GTK_RADIO_ACTION (ACTION (MAIL_SCOPE_ALL_ACCOUNTS)); - e_shell_content_set_scope_action (shell_content, radio_action); - e_shell_content_set_scope_visible (shell_content, TRUE); - - /* Bind GObject properties for GConf keys. */ - - bridge = gconf_bridge_get (); - - object = G_OBJECT (ACTION (MAIL_PREVIEW)); - key = "/apps/evolution/mail/display/show_preview"; - gconf_bridge_bind_property (bridge, key, object, "active"); - - object = G_OBJECT (ACTION (MAIL_THREADS_GROUP_BY)); - key = "/apps/evolution/mail/display/thread_list"; - gconf_bridge_bind_property (bridge, key, object, "active"); - - object = G_OBJECT (ACTION (MAIL_VIEW_VERTICAL)); - key = "/apps/evolution/mail/display/layout"; - gconf_bridge_bind_property (bridge, key, object, "current-value"); - - /* Fine tuning. */ - - src_object = G_OBJECT (ACTION (MAIL_THREADS_GROUP_BY)); - - dst_object = G_OBJECT (ACTION (MAIL_FOLDER_SELECT_THREAD)); - e_binding_new (src_object, "active", dst_object, "sensitive"); - - dst_object = G_OBJECT (ACTION (MAIL_FOLDER_SELECT_SUBTHREAD)); - e_binding_new (src_object, "active", dst_object, "sensitive"); - - dst_object = G_OBJECT (ACTION (MAIL_THREADS_COLLAPSE_ALL)); - e_binding_new (src_object, "active", dst_object, "sensitive"); - - dst_object = G_OBJECT (ACTION (MAIL_THREADS_EXPAND_ALL)); - e_binding_new (src_object, "active", dst_object, "sensitive"); - - e_mutual_binding_new ( - G_OBJECT (ACTION (MAIL_PREVIEW)), "active", - G_OBJECT (shell_content), "preview-visible"); - - /* XXX The boolean sense of the GConf key is the inverse of - * the menu item, so we have to maintain two properties. */ - e_mutual_binding_new_with_negation ( - G_OBJECT (shell_content), "show-deleted", - G_OBJECT (ACTION (MAIL_HIDE_DELETED)), "active"); - - g_signal_connect ( - ACTION (GAL_SAVE_CUSTOM_VIEW), "activate", - G_CALLBACK (action_gal_save_custom_view_cb), mail_shell_view); - - g_signal_connect ( - ACTION (SEARCH_EXECUTE), "activate", - G_CALLBACK (action_search_execute_cb), mail_shell_view); -} - -/* Helper for e_mail_shell_view_update_popup_labels() */ -static void -mail_shell_view_update_label_action (GtkToggleAction *action, - MessageList *message_list, - GPtrArray *uids, - const gchar *label_tag) -{ - CamelFolder *folder; - gboolean exists = FALSE; - gboolean not_exists = FALSE; - gboolean sensitive; - guint ii; - - folder = message_list->folder; - - /* Figure out the proper label action state for the selected - * messages. If all the selected messages have the given label, - * make the toggle action active. If all the selected message - * DO NOT have the given label, make the toggle action inactive. - * If some do and some don't, make the action insensitive. */ - - for (ii = 0; ii < uids->len && (!exists || !not_exists); ii++) { - const gchar *old_label; - gchar *new_label; - - /* Check for new-style labels. */ - if (camel_folder_get_message_user_flag ( - folder, uids->pdata[ii], label_tag)) { - exists = TRUE; - continue; - } - - /* Check for old-style labels. */ - old_label = camel_folder_get_message_user_tag ( - folder, uids->pdata[ii], "label"); - if (old_label == NULL) { - not_exists = TRUE; - continue; - } - - /* Convert old-style labels ("") to "$Label". */ - new_label = g_alloca (strlen (old_label) + 10); - g_stpcpy (g_stpcpy (new_label, "$Label"), old_label); - - if (strcmp (new_label, label_tag) == 0) - exists = TRUE; - else - not_exists = TRUE; - } - - sensitive = !(exists && not_exists); - gtk_toggle_action_set_active (action, exists); - gtk_action_set_sensitive (GTK_ACTION (action), sensitive); -} - -void -e_mail_shell_view_update_popup_labels (EMailShellView *mail_shell_view) -{ - EShell *shell; - EShellSettings *shell_settings; - EShellWindow *shell_window; - EShellView *shell_view; - EMailReader *reader; - MessageList *message_list; - GtkUIManager *ui_manager; - GtkActionGroup *action_group; - GtkTreeModel *tree_model; - GtkTreeIter iter; - GPtrArray *uids; - const gchar *path; - gboolean valid; - guint merge_id; - gint ii = 0; - - g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - ui_manager = e_shell_window_get_ui_manager (shell_window); - - shell = e_shell_window_get_shell (shell_window); - shell_settings = e_shell_get_shell_settings (shell); - - tree_model = e_shell_settings_get_object ( - shell_settings, "mail-label-list-store"); - - action_group = ACTION_GROUP (MAIL_LABEL); - merge_id = mail_shell_view->priv->label_merge_id; - path = "/mail-message-popup/mail-label-menu/mail-label-actions"; - - /* Unmerge the previous menu items. */ - gtk_ui_manager_remove_ui (ui_manager, merge_id); - e_action_group_remove_all_actions (action_group); - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - uids = message_list_get_selected (message_list); - - valid = gtk_tree_model_get_iter_first (tree_model, &iter); - - while (valid) { - GtkToggleAction *toggle_action; - GtkAction *action; - gchar *action_name; - gchar *stock_id; - gchar *label; - gchar *tag; - - label = e_mail_label_list_store_get_name ( - E_MAIL_LABEL_LIST_STORE (tree_model), &iter); - stock_id = e_mail_label_list_store_get_stock_id ( - E_MAIL_LABEL_LIST_STORE (tree_model), &iter); - tag = e_mail_label_list_store_get_tag ( - E_MAIL_LABEL_LIST_STORE (tree_model), &iter); - action_name = g_strdup_printf ("mail-label-%d", ii); - - /* XXX Add a tooltip! */ - toggle_action = gtk_toggle_action_new ( - action_name, label, NULL, stock_id); - - g_object_set_data_full ( - G_OBJECT (toggle_action), "tag", - tag, (GDestroyNotify) g_free); - - /* Configure the action before we connect to signals. */ - mail_shell_view_update_label_action ( - toggle_action, message_list, uids, tag); - - g_signal_connect ( - toggle_action, "toggled", - G_CALLBACK (action_mail_label_cb), mail_shell_view); - - /* The action group takes ownership of the action. */ - action = GTK_ACTION (toggle_action); - gtk_action_group_add_action (action_group, action); - g_object_unref (toggle_action); - - gtk_ui_manager_add_ui ( - ui_manager, merge_id, path, action_name, - action_name, GTK_UI_MANAGER_AUTO, FALSE); - - g_free (label); - g_free (stock_id); - g_free (action_name); - - valid = gtk_tree_model_iter_next (tree_model, &iter); - ii++; - } - - message_list_free_uids (message_list, uids); - - g_object_unref (tree_model); -} - -void -e_mail_shell_view_update_search_filter (EMailShellView *mail_shell_view) -{ - EShell *shell; - EShellContent *shell_content; - EShellSettings *shell_settings; - EShellWindow *shell_window; - EShellView *shell_view; - GtkActionGroup *action_group; - GtkRadioAction *radio_action; - GtkTreeModel *tree_model; - GtkTreeIter iter; - GList *list; - GSList *group; - gboolean valid; - gint ii = 0; - - g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - shell = e_shell_window_get_shell (shell_window); - shell_settings = e_shell_get_shell_settings (shell); - - tree_model = e_shell_settings_get_object ( - shell_settings, "mail-label-list-store"); - - action_group = ACTION_GROUP (MAIL_FILTER); - e_action_group_remove_all_actions (action_group); - - /* Add the standard filter actions. */ - gtk_action_group_add_radio_actions ( - action_group, mail_filter_entries, - G_N_ELEMENTS (mail_filter_entries), - MAIL_FILTER_ALL_MESSAGES, - G_CALLBACK (action_search_filter_cb), - mail_shell_view); - - /* Retrieve the radio group from an action we just added. */ - list = gtk_action_group_list_actions (action_group); - radio_action = GTK_RADIO_ACTION (list->data); - group = gtk_radio_action_get_group (radio_action); - g_list_free (list); - - valid = gtk_tree_model_get_iter_first (tree_model, &iter); - - while (valid) { - GtkAction *action; - gchar *action_name; - gchar *stock_id; - gchar *label; - - label = e_mail_label_list_store_get_name ( - E_MAIL_LABEL_LIST_STORE (tree_model), &iter); - stock_id = e_mail_label_list_store_get_stock_id ( - E_MAIL_LABEL_LIST_STORE (tree_model), &iter); - - action_name = g_strdup_printf ("mail-filter-label-%d", ii); - radio_action = gtk_radio_action_new ( - action_name, label, NULL, stock_id, ii); - g_free (action_name); - - gtk_radio_action_set_group (radio_action, group); - group = gtk_radio_action_get_group (radio_action); - - /* The action group takes ownership of the action. */ - action = GTK_ACTION (radio_action); - gtk_action_group_add_action (action_group, action); - g_object_unref (radio_action); - - g_free (label); - g_free (stock_id); - - valid = gtk_tree_model_iter_next (tree_model, &iter); - ii++; - } - - /* Use any action in the group; doesn't matter which. */ - e_shell_content_set_filter_action (shell_content, radio_action); - - ii = MAIL_FILTER_UNREAD_MESSAGES; - e_shell_content_add_filter_separator_after (shell_content, ii); - - ii = MAIL_FILTER_READ_MESSAGES; - e_shell_content_add_filter_separator_before (shell_content, ii); - - g_object_unref (tree_model); -} diff --git a/mail/e-mail-shell-view-actions.h b/mail/e-mail-shell-view-actions.h deleted file mode 100644 index 2a05582df8..0000000000 --- a/mail/e-mail-shell-view-actions.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * e-mail-shell-view-actions.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_MAIL_SHELL_VIEW_ACTIONS_H -#define E_MAIL_SHELL_VIEW_ACTIONS_H - -#include - -/* Mail Actions */ -#define E_SHELL_WINDOW_ACTION_MAIL_ACCOUNT_DISABLE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-account-disable") -#define E_SHELL_WINDOW_ACTION_MAIL_ADD_SENDER(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-add-sender") -#define E_SHELL_WINDOW_ACTION_MAIL_CARET_MODE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-caret-mode") -#define E_SHELL_WINDOW_ACTION_MAIL_CHECK_FOR_JUNK(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-check-for-junk") -#define E_SHELL_WINDOW_ACTION_MAIL_CLIPBOARD_COPY(window) \ - E_SHELL_WINDOw_ACTION ((window), "mail-clipboard-copy") -#define E_SHELL_WINDOW_ACTION_MAIL_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-copy") -#define E_SHELL_WINDOW_ACTION_MAIL_CREATE_SEARCH_FOLDER(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-create-search-folder") -#define E_SHELL_WINDOW_ACTION_MAIL_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-delete") -#define E_SHELL_WINDOW_ACTION_MAIL_DOWNLOAD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-download") -#define E_SHELL_WINDOW_ACTION_MAIL_EMPTY_TRASH(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-empty-trash") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_ON_MAILING_LIST(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-on-mailing-list") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_ON_RECIPIENTS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-on-recipients") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_ON_SENDER(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-on-sender") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_ON_SUBJECT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-on-subject") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTERS_APPLY(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filters-apply") -#define E_SHELL_WINDOW_ACTION_MAIL_FIND(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-find") -#define E_SHELL_WINDOW_ACTION_MAIL_FLAG_CLEAR(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-flag-clear") -#define E_SHELL_WINDOW_ACTION_MAIL_FLAG_COMPLETED(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-flag-completed") -#define E_SHELL_WINDOW_ACTION_MAIL_FLAG_FOR_FOLLOWUP(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-flag-for-followup") -#define E_SHELL_WINDOW_ACTION_MAIL_FLUSH_OUTBOX(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-flush-outbox") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-copy") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-delete") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_EXPUNGE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-expunge") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_MARK_ALL_READ(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-mark-all-read") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_MOVE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-move") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-new") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_PROPERTIES(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-properties") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_REFRESH(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-refresh") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_RENAME(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-rename") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_SELECT_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-select-all") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_SELECT_THREAD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-select-thread") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_SELECT_SUBTHREAD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-select-subthread") -#define E_SHELL_WINDOW_ACTION_MAIL_FORWARD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-forward") -#define E_SHELL_WINDOW_ACTION_MAIL_FORWARD_ATTACHED(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-forward-attached") -#define E_SHELL_WINDOW_ACTION_MAIL_FORWARD_INLINE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-forward-inline") -#define E_SHELL_WINDOW_ACTION_MAIL_FORWARD_QUOTED(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-forward-quoted") -#define E_SHELL_WINDOW_ACTION_MAIL_HIDE_DELETED(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-hide-deleted") -#define E_SHELL_WINDOW_ACTION_MAIL_HIDE_READ(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-hide-read") -#define E_SHELL_WINDOW_ACTION_MAIL_HIDE_SELECTED(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-hide-selected") -#define E_SHELL_WINDOW_ACTION_MAIL_LABEL_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-label-new") -#define E_SHELL_WINDOW_ACTION_MAIL_LABEL_NONE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-label-none") -#define E_SHELL_WINDOW_ACTION_MAIL_LOAD_IMAGES(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-load-images") -#define E_SHELL_WINDOW_ACTION_MAIL_MARK_IMPORTANT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-mark-important") -#define E_SHELL_WINDOW_ACTION_MAIL_MARK_JUNK(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-mark-junk") -#define E_SHELL_WINDOW_ACTION_MAIL_MARK_NOTJUNK(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-mark-notjunk") -#define E_SHELL_WINDOW_ACTION_MAIL_MARK_READ(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-mark-read") -#define E_SHELL_WINDOW_ACTION_MAIL_MARK_UNIMPORTANT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-mark-unimportant") -#define E_SHELL_WINDOW_ACTION_MAIL_MARK_UNREAD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-mark-unread") -#define E_SHELL_WINDOW_ACTION_MAIL_MESSAGE_EDIT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-message-edit") -#define E_SHELL_WINDOW_ACTION_MAIL_MESSAGE_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-message-new") -#define E_SHELL_WINDOW_ACTION_MAIL_MESSAGE_OPEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-message-open") -#define E_SHELL_WINDOW_ACTION_MAIL_MOVE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-move") -#define E_SHELL_WINDOW_ACTION_MAIL_NEXT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-next") -#define E_SHELL_WINDOW_ACTION_MAIL_NEXT_IMPORTANT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-next-important") -#define E_SHELL_WINDOW_ACTION_MAIL_NEXT_THREAD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-next-thread") -#define E_SHELL_WINDOW_ACTION_MAIL_NEXT_UNREAD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-next-unread") -#define E_SHELL_WINDOW_ACTION_MAIL_PREVIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-preview") -#define E_SHELL_WINDOW_ACTION_MAIL_PREVIOUS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-previous") -#define E_SHELL_WINDOW_ACTION_MAIL_PREVIOUS_IMPORTANT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-previous-important") -#define E_SHELL_WINDOW_ACTION_MAIL_PREVIOUS_UNREAD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-previous-unread") -#define E_SHELL_WINDOW_ACTION_MAIL_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-print") -#define E_SHELL_WINDOW_ACTION_MAIL_PRINT_PREVIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-print-preview") -#define E_SHELL_WINDOW_ACTION_MAIL_REDIRECT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-redirect") -#define E_SHELL_WINDOW_ACTION_MAIL_REPLY_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-reply-all") -#define E_SHELL_WINDOW_ACTION_MAIL_REPLY_LIST(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-reply-list") -#define E_SHELL_WINDOW_ACTION_MAIL_REPLY_SENDER(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-reply-sender") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FOLDER_FROM_MAILING_LIST(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-folder-from-mailing-list") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FOLDER_FROM_RECIPIENTS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-folder-from-recipients") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FOLDER_FROM_SENDER(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-folder-from-sender") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FOLDER_FROM_SUBJECT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-folder-from-subject") -#define E_SHELL_WINDOW_ACTION_MAIL_SELECT_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-select-all") -#define E_SHELL_WINDOW_ACTION_MAIL_SHOW_ALL_HEADERS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-show-all-headers") -#define E_SHELL_WINDOW_ACTION_MAIL_SHOW_HIDDEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-show-hidden") -#define E_SHELL_WINDOW_ACTION_MAIL_SHOW_SOURCE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-show-source") -#define E_SHELL_WINDOW_ACTION_MAIL_SMART_BACKWARD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-smart-backward") -#define E_SHELL_WINDOW_ACTION_MAIL_SMART_FORWARD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-smart-forward") -#define E_SHELL_WINDOW_ACTION_MAIL_STOP(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-stop") -#define E_SHELL_WINDOW_ACTION_MAIL_THREADS_COLLAPSE_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-threads-collapse-all") -#define E_SHELL_WINDOW_ACTION_MAIL_THREADS_EXPAND_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-threads-expand-all") -#define E_SHELL_WINDOW_ACTION_MAIL_THREADS_GROUP_BY(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-threads-group-by") -#define E_SHELL_WINDOW_ACTION_MAIL_TOOLS_FILTERS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-tools-filters") -#define E_SHELL_WINDOW_ACTION_MAIL_TOOLS_SEARCH_FOLDERS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-tools-search-folders") -#define E_SHELL_WINDOW_ACTION_MAIL_TOOLS_SUBSCRIPTIONS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-tools-subscriptions") -#define E_SHELL_WINDOW_ACTION_MAIL_UNDELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-undelete") -#define E_SHELL_WINDOW_ACTION_MAIL_VIEW_CLASSIC(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-view-classic") -#define E_SHELL_WINDOW_ACTION_MAIL_VIEW_VERTICAL(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-view-vertical") -#define E_SHELL_WINDOW_ACTION_MAIL_ZOOM_100(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-zoom-100") -#define E_SHELL_WINDOW_ACTION_MAIL_ZOOM_IN(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-zoom-in") -#define E_SHELL_WINDOW_ACTION_MAIL_ZOOM_OUT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-zoom-out") - -/* Mail Query Actions */ -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_ALL_MESSAGES(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-all-messages") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_IMPORTANT_MESSAGES(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-important-messages") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_LAST_5_DAYS_MESSAGES(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-last-5-days-messages") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_MESSAGES_NOT_JUNK(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-messages-not-junk") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-messages-with-attachments") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_NO_LABEL(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-no-label") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_READ_MESSAGES(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-read-messages") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_RECENT_MESSAGES(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-recent-messages") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_UNREAD_MESSAGES(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-unread-messages") -#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_ALL_ACCOUNTS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-scope-all-accounts") -#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_CURRENT_ACCOUNT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-scope-current-account") -#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_CURRENT_FOLDER(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-scope-current-folder") -#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_CURRENT_MESSAGE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-scope-current-message") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_BODY_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-body-contains") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_MESSAGE_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-message-contains") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_RECIPIENTS_CONTAIN(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-recipients-contain") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_SENDER_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-sender-contains") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_SUBJECT_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-subject-contains") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_SUBJECT_OR_RECIPIENTS_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-subject-or-recipients-contains") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_SUBJECT_OR_SENDER_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-subject-or-sender-contains") - -/* Action Groups */ -#define E_SHELL_WINDOW_ACTION_GROUP_MAIL(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "mail") -#define E_SHELL_WINDOW_ACTION_GROUP_MAIL_FILTER(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "mail-filter") -#define E_SHELL_WINDOW_ACTION_GROUP_MAIL_LABEL(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "mail-label") - -#endif /* E_MAIL_SHELL_VIEW_ACTIONS_H */ diff --git a/mail/e-mail-shell-view-private.c b/mail/e-mail-shell-view-private.c deleted file mode 100644 index f3b3b5a513..0000000000 --- a/mail/e-mail-shell-view-private.c +++ /dev/null @@ -1,905 +0,0 @@ -/* - * e-mail-shell-view-private.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-mail-shell-view-private.h" - -#include "widgets/menus/gal-view-factory-etable.h" - -static void -mail_shell_view_folder_tree_selected_cb (EMailShellView *mail_shell_view, - const gchar *full_name, - const gchar *uri, - guint32 flags, - EMFolderTree *folder_tree) -{ - EShellView *shell_view; - EMailReader *reader; - gboolean folder_selected; - - shell_view = E_SHELL_VIEW (mail_shell_view); - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - - folder_selected = - !(flags & CAMEL_FOLDER_NOSELECT) && - full_name != NULL; - - if (folder_selected) - e_mail_reader_set_folder_uri (reader, uri); - else - e_mail_reader_set_folder (reader, NULL, NULL); - - e_shell_view_update_actions (shell_view); -} - -static void -mail_shell_view_folder_tree_popup_event_cb (EShellView *shell_view, - GdkEventButton *event) -{ - const gchar *widget_path; - - widget_path = "/mail-folder-popup"; - e_shell_view_show_popup_menu (shell_view, widget_path, event); -} - -static gboolean -mail_shell_view_key_press_event_cb (EMailShellView *mail_shell_view, - GdkEventKey *event) -{ - EShellView *shell_view; - EShellWindow *shell_window; - GtkAction *action; - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - if ((event->state & GDK_CONTROL_MASK) != 0) - return FALSE; - - switch (event->keyval) { - case GDK_space: - action = ACTION (MAIL_SMART_FORWARD); - break; - - case GDK_BackSpace: - action = ACTION (MAIL_SMART_BACKWARD); - break; - - default: - return FALSE; - } - - gtk_action_activate (action); - - return TRUE; -} - -static gint -mail_shell_view_message_list_key_press_cb (EMailShellView *mail_shell_view, - gint row, - ETreePath path, - gint col, - GdkEvent *event) -{ - return mail_shell_view_key_press_event_cb ( - mail_shell_view, &event->key); -} - -static gboolean -mail_shell_view_message_list_right_click_cb (EShellView *shell_view, - gint row, - ETreePath path, - gint col, - GdkEventButton *event) -{ - const gchar *widget_path; - - widget_path = "/mail-message-popup"; - e_shell_view_show_popup_menu (shell_view, widget_path, event); - - return TRUE; -} - -static void -mail_shell_view_reader_changed_cb (EMailShellView *mail_shell_view, - EMailReader *reader) -{ - EMailShellContent *mail_shell_content; - - mail_shell_content = mail_shell_view->priv->mail_shell_content; - e_mail_shell_content_update_view_instance (mail_shell_content); - e_mail_shell_view_update_sidebar (mail_shell_view); -} - -static void -mail_shell_view_reader_status_message_cb (EMailShellView *mail_shell_view, - const gchar *status_message) -{ - EShellView *shell_view; - EShellTaskbar *shell_taskbar; - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_taskbar = e_shell_view_get_shell_taskbar (shell_view); - - e_shell_taskbar_set_message (shell_taskbar, status_message); -} - -static void -mail_shell_view_load_view_collection (EShellViewClass *shell_view_class) -{ - GalViewCollection *collection; - GalViewFactory *factory; - ETableSpecification *spec; - const gchar *base_dir; - gchar *filename; - - collection = shell_view_class->view_collection; - - base_dir = EVOLUTION_ETSPECDIR; - spec = e_table_specification_new (); - filename = g_build_filename (base_dir, ETSPEC_FILENAME, NULL); - if (!e_table_specification_load_from_file (spec, filename)) - g_critical ("Unable to load ETable specification file " - "for mail"); - g_free (filename); - - factory = gal_view_factory_etable_new (spec); - gal_view_collection_add_factory (collection, factory); - g_object_unref (factory); - g_object_unref (spec); - - gal_view_collection_load (collection); -} - -static void -mail_shell_view_notify_view_id_cb (EMailShellView *mail_shell_view) -{ - EMailShellContent *mail_shell_content; - GalViewInstance *view_instance; - const gchar *view_id; - - mail_shell_content = mail_shell_view->priv->mail_shell_content; - view_instance = NULL; /* FIXME */ - view_id = e_shell_view_get_view_id (E_SHELL_VIEW (mail_shell_view)); - - /* A NULL view ID implies we're in a custom view. But you can - * only get to a custom view via the "Define Views" dialog, which - * would have already modified the view instance appropriately. - * Furthermore, there's no way to refer to a custom view by ID - * anyway, since custom views have no IDs. */ - if (view_id == NULL) - return; - - gal_view_instance_set_current_view_id (view_instance, view_id); -} - -void -e_mail_shell_view_private_init (EMailShellView *mail_shell_view, - EShellViewClass *shell_view_class) -{ - if (!gal_view_collection_loaded (shell_view_class->view_collection)) - mail_shell_view_load_view_collection (shell_view_class); - - g_signal_connect ( - mail_shell_view, "notify::view-id", - G_CALLBACK (mail_shell_view_notify_view_id_cb), NULL); -} - -void -e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view) -{ - EMailShellViewPrivate *priv = mail_shell_view->priv; - EMailShellSidebar *mail_shell_sidebar; - EShell *shell; - EShellView *shell_view; - EShellBackend *shell_backend; - EShellContent *shell_content; - EShellSettings *shell_settings; - EShellSidebar *shell_sidebar; - EShellWindow *shell_window; - EMFormatHTMLDisplay *html_display; - EMFolderTree *folder_tree; - RuleContext *context; - FilterRule *rule = NULL; - GtkTreeModel *tree_model; - GtkUIManager *ui_manager; - MessageList *message_list; - EMailReader *reader; - GtkHTML *html; - const gchar *source; - guint merge_id; - gint ii = 0; - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_backend = e_shell_view_get_shell_backend (shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - ui_manager = e_shell_window_get_ui_manager (shell_window); - - shell = e_shell_window_get_shell (shell_window); - shell_settings = e_shell_get_shell_settings (shell); - - tree_model = e_shell_settings_get_object ( - shell_settings, "mail-label-list-store"); - - e_shell_window_add_action_group (shell_window, "mail"); - e_shell_window_add_action_group (shell_window, "mail-filter"); - e_shell_window_add_action_group (shell_window, "mail-label"); - - merge_id = gtk_ui_manager_new_merge_id (ui_manager); - priv->label_merge_id = merge_id; - - /* Cache these to avoid lots of awkward casting. */ - priv->mail_shell_backend = g_object_ref (shell_backend); - priv->mail_shell_content = g_object_ref (shell_content); - priv->mail_shell_sidebar = g_object_ref (shell_sidebar); - - reader = E_MAIL_READER (shell_content); - html_display = e_mail_reader_get_html_display (reader); - message_list = e_mail_reader_get_message_list (reader); - - mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar); - folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); - - html = EM_FORMAT_HTML (html_display)->html; - - g_signal_connect_swapped ( - folder_tree, "folder-selected", - G_CALLBACK (mail_shell_view_folder_tree_selected_cb), - mail_shell_view); - - g_signal_connect_swapped ( - folder_tree, "popup-event", - G_CALLBACK (mail_shell_view_folder_tree_popup_event_cb), - mail_shell_view); - - g_signal_connect_swapped ( - message_list->tree, "key-press", - G_CALLBACK (mail_shell_view_message_list_key_press_cb), - mail_shell_view); - - g_signal_connect_swapped ( - message_list->tree, "right-click", - G_CALLBACK (mail_shell_view_message_list_right_click_cb), - mail_shell_view); - - g_signal_connect_swapped ( - reader, "changed", - G_CALLBACK (mail_shell_view_reader_changed_cb), - mail_shell_view); - - /* Use the same callback as "changed". */ - g_signal_connect_swapped ( - reader, "folder-loaded", - G_CALLBACK (mail_shell_view_reader_changed_cb), - mail_shell_view); - - g_signal_connect_swapped ( - reader, "folder-loaded", - G_CALLBACK (e_mail_shell_view_restore_state), - mail_shell_view); - - g_signal_connect_swapped ( - tree_model, "row-changed", - G_CALLBACK (e_mail_shell_view_update_search_filter), - mail_shell_view); - - g_signal_connect_swapped ( - tree_model, "row-deleted", - G_CALLBACK (e_mail_shell_view_update_search_filter), - mail_shell_view); - - g_signal_connect_swapped ( - tree_model, "row-inserted", - G_CALLBACK (e_mail_shell_view_update_search_filter), - mail_shell_view); - - g_signal_connect_swapped ( - html, "key-press-event", - G_CALLBACK (mail_shell_view_key_press_event_cb), - mail_shell_view); - - g_signal_connect_swapped ( - html, "status-message", - G_CALLBACK (mail_shell_view_reader_status_message_cb), - mail_shell_view); - - e_mail_shell_view_actions_init (mail_shell_view); - e_mail_shell_view_update_search_filter (mail_shell_view); - e_mail_reader_init (reader); - - /* Populate built-in rules for search entry popup menu. - * Keep the assertions, please. If the conditions aren't - * met we're going to crash anyway, just more mysteriously. */ - context = e_shell_content_get_search_context (shell_content); - source = FILTER_SOURCE_DEMAND; - while ((rule = rule_context_next_rule (context, rule, source))) { - g_assert (ii < MAIL_NUM_SEARCH_RULES); - priv->search_rules[ii++] = g_object_ref (rule); - } - g_assert (ii == MAIL_NUM_SEARCH_RULES); -} - -void -e_mail_shell_view_private_dispose (EMailShellView *mail_shell_view) -{ - EMailShellViewPrivate *priv = mail_shell_view->priv; - gint ii; - - DISPOSE (priv->mail_shell_backend); - DISPOSE (priv->mail_shell_content); - DISPOSE (priv->mail_shell_sidebar); - - for (ii = 0; ii < MAIL_NUM_SEARCH_RULES; ii++) - DISPOSE (priv->search_rules[ii]); -} - -void -e_mail_shell_view_private_finalize (EMailShellView *mail_shell_view) -{ - /* XXX Nothing to do? */ -} - -void -e_mail_shell_view_restore_state (EMailShellView *mail_shell_view) -{ - EShellView *shell_view; - EShellContent *shell_content; - EMailReader *reader; - MessageList *message_list; - const gchar *folder_uri; - gchar *group_name; - - /* XXX Move this to EMailShellContent. */ - - g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - - reader = E_MAIL_READER (shell_content); - message_list = e_mail_reader_get_message_list (reader); - folder_uri = message_list->folder_uri; - g_return_if_fail (folder_uri != NULL); - - group_name = g_strdup_printf ("Folder %s", folder_uri); - e_shell_content_restore_state (shell_content, group_name); - g_free (group_name); -} - -void -e_mail_shell_view_execute_search (EMailShellView *mail_shell_view) -{ - EShell *shell; - EShellView *shell_view; - EShellWindow *shell_window; - EShellContent *shell_content; - EShellSettings *shell_settings; - EMFormatHTMLDisplay *html_display; - EMailShellContent *mail_shell_content; - MessageList *message_list; - FilterRule *rule; - EMailReader *reader; - CamelFolder *folder; - GtkAction *action; - GtkTreeModel *model; - GtkTreePath *path; - GtkTreeIter tree_iter; - GString *string; - GList *iter; - GSList *search_strings = NULL; - const gchar *folder_uri; - const gchar *text; - gboolean valid; - gchar *query; - gchar *temp; - gchar *tag; - gint value; - - g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - - shell = e_shell_window_get_shell (shell_window); - shell_settings = e_shell_get_shell_settings (shell); - - mail_shell_content = mail_shell_view->priv->mail_shell_content; - - reader = E_MAIL_READER (shell_content); - html_display = e_mail_reader_get_html_display (reader); - message_list = e_mail_reader_get_message_list (reader); - - folder_uri = message_list->folder_uri; - folder = message_list->folder; - - /* This returns a new object reference. */ - model = e_shell_settings_get_object ( - shell_settings, "mail-label-list-store"); - - text = e_shell_content_get_search_text (shell_content); - if (text == NULL || *text == '\0') { - query = g_strdup (""); - goto filter; - } - - /* Replace variables in the selected rule with the - * current search text and extract a query string. */ - - action = ACTION (MAIL_SEARCH_SUBJECT_OR_SENDER_CONTAINS); - value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); - g_return_if_fail (value >= 0 && value < MAIL_NUM_SEARCH_RULES); - rule = mail_shell_view->priv->search_rules[value]; - - for (iter = rule->parts; iter != NULL; iter = iter->next) { - FilterPart *part = iter->data; - FilterElement *element = NULL; - - if (strcmp (part->name, "subject") == 0) - element = filter_part_find_element (part, "subject"); - else if (strcmp (part->name, "body") == 0) - element = filter_part_find_element (part, "word"); - else if (strcmp (part->name, "sender") == 0) - element = filter_part_find_element (part, "sender"); - else if (strcmp (part->name, "to") == 0) - element = filter_part_find_element (part, "recipient"); - - if (strcmp (part->name, "body") == 0) { - struct _camel_search_words *words; - gint ii; - - words = camel_search_words_split ((guchar *) text); - for (ii = 0; ii < words->len; ii++) - search_strings = g_slist_prepend ( - search_strings, g_strdup ( - words->words[ii]->word)); - camel_search_words_free (words); - } - - if (element != NULL) { - FilterInput *input = FILTER_INPUT (element); - filter_input_set_value (input, text); - } - } - - string = g_string_sized_new (1024); - filter_rule_build_code (rule, string); - query = g_string_free (string, FALSE); - -filter: - - /* Apply selected filter. */ - - value = e_shell_content_get_filter_value (shell_content); - switch (value) { - case MAIL_FILTER_ALL_MESSAGES: - break; - - case MAIL_FILTER_UNREAD_MESSAGES: - temp = g_strdup_printf ( - "(and %s (match-all (not " - "(system-flag \"Seen\"))))", query); - g_free (query); - query = temp; - break; - - case MAIL_FILTER_NO_LABEL: - string = g_string_sized_new (1024); - g_string_append_printf ( - string, "(and %s (and ", query); - valid = gtk_tree_model_get_iter_first ( - model, &tree_iter); - while (valid) { - tag = e_mail_label_list_store_get_tag ( - E_MAIL_LABEL_LIST_STORE (model), - &tree_iter); - g_string_append_printf ( - string, " (match-all (not (or " - "(= (user-tag \"label\") \"%s\") " - "(user-flag \"$Label%s\") " - "(user-flag \"%s\"))))", - tag, tag, tag); - g_free (tag); - - valid = gtk_tree_model_iter_next ( - model, &tree_iter); - } - g_string_append_len (string, "))", 2); - g_free (query); - query = g_string_free (string, FALSE); - break; - - case MAIL_FILTER_READ_MESSAGES: - temp = g_strdup_printf ( - "(and %s (match-all " - "(system-flag \"Seen\")))", query); - g_free (query); - query = temp; - break; - - case MAIL_FILTER_RECENT_MESSAGES: - if (em_utils_folder_is_sent (folder, folder_uri)) - temp = g_strdup_printf ( - "(and %s (match-all " - "(> (get-sent-date) " - "(- (get-current-date) 86400))))", - query); - else - temp = g_strdup_printf ( - "(and %s (match-all " - "(> (get-received-date) " - "(- (get-current-date) 86400))))", - query); - g_free (query); - query = temp; - break; - - case MAIL_FILTER_LAST_5_DAYS_MESSAGES: - if (em_utils_folder_is_sent (folder, folder_uri)) - temp = g_strdup_printf ( - "(and %s (match-all " - "(> (get-sent-date) " - "(- (get-current-date) 432000))))", - query); - else - temp = g_strdup_printf ( - "(and %s (match-all " - "(> (get-received-date) " - "(- (get-current-date) 432000))))", - query); - g_free (query); - query = temp; - break; - - case MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS: - temp = g_strdup_printf ( - "(and %s (match-all " - "(system-flag \"Attachments\")))", query); - g_free (query); - query = temp; - break; - - case MAIL_FILTER_IMPORTANT_MESSAGES: - temp = g_strdup_printf ( - "(and %s (match-all " - "(system-flag \"Flagged\")))", query); - g_free (query); - query = temp; - break; - - case MAIL_FILTER_MESSAGES_NOT_JUNK: - temp = g_strdup_printf ( - "(and %s (match-all (not " - "(system-flag \"junk\"))))", query); - g_free (query); - query = temp; - break; - - default: - /* The action value also serves as a path for - * the label list store. That's why we number - * the label actions from zero. */ - path = gtk_tree_path_new_from_indices (value, -1); - gtk_tree_model_get_iter (model, &tree_iter, path); - gtk_tree_path_free (path); - - tag = e_mail_label_list_store_get_tag ( - E_MAIL_LABEL_LIST_STORE (model), &tree_iter); - temp = g_strdup_printf ( - "(and %s (match-all (or " - "(= (user-tag \"label\") \"%s\") " - "(user-flag \"$Label%s\") " - "(user-flag \"%s\"))))", - query, tag, tag, tag); - g_free (tag); - - g_free (query); - query = temp; - break; - } - - message_list_set_search (message_list, query); - - e_mail_shell_content_set_search_strings ( - mail_shell_content, search_strings); - - g_slist_foreach (search_strings, (GFunc) g_free, NULL); - g_slist_free (search_strings); - - g_object_unref (model); - g_free (query); -} - -/* Helper for e_mail_shell_view_create_filter_from_selected() */ -static void -mail_shell_view_create_filter_cb (CamelFolder *folder, - const gchar *uid, - CamelMimeMessage *message, - gpointer user_data) -{ - struct { - const gchar *source; - gint type; - } *filter_data = user_data; - - if (message != NULL) - filter_gui_add_from_message ( - message, filter_data->source, filter_data->type); - - g_free (filter_data); -} - -void -e_mail_shell_view_create_filter_from_selected (EMailShellView *mail_shell_view, - gint filter_type) -{ - EMailReader *reader; - MessageList *message_list; - CamelFolder *folder; - const gchar *filter_source; - const gchar *folder_uri; - GPtrArray *uids; - - struct { - const gchar *source; - gint type; - } *filter_data; - - g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - folder_uri = message_list->folder_uri; - folder = message_list->folder; - - if (em_utils_folder_is_sent (folder, folder_uri)) - filter_source = FILTER_SOURCE_OUTGOING; - else if (em_utils_folder_is_outbox (folder, folder_uri)) - filter_source = FILTER_SOURCE_OUTGOING; - else - filter_source = FILTER_SOURCE_INCOMING; - - uids = message_list_get_selected (message_list); - - if (uids->len == 1) { - filter_data = g_malloc (sizeof (*filter_data)); - filter_data->source = filter_source; - filter_data->type = filter_type; - - mail_get_message ( - folder, uids->pdata[0], - mail_shell_view_create_filter_cb, - filter_data, mail_msg_unordered_push); - } - - em_utils_uids_free (uids); -} - -/* Helper for e_mail_shell_view_create_vfolder_from_selected() */ -static void -mail_shell_view_create_vfolder_cb (CamelFolder *folder, - const gchar *uid, - CamelMimeMessage *message, - gpointer user_data) -{ - struct { - gchar *uri; - gint type; - } *vfolder_data = user_data; - - if (message != NULL) - vfolder_gui_add_from_message ( - message, vfolder_data->type, vfolder_data->uri); - - g_free (vfolder_data->uri); - g_free (vfolder_data); -} - -void -e_mail_shell_view_create_vfolder_from_selected (EMailShellView *mail_shell_view, - gint vfolder_type) -{ - EMailReader *reader; - MessageList *message_list; - CamelFolder *folder; - const gchar *folder_uri; - GPtrArray *uids; - - struct { - gchar *uri; - gint type; - } *vfolder_data; - - g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - folder_uri = message_list->folder_uri; - folder = message_list->folder; - - uids = message_list_get_selected (message_list); - - if (uids->len == 1) { - vfolder_data = g_malloc (sizeof (*vfolder_data)); - vfolder_data->uri = g_strdup (folder_uri); - vfolder_data->type = vfolder_type; - - mail_get_message ( - folder, uids->pdata[0], - mail_shell_view_create_vfolder_cb, - vfolder_data, mail_msg_unordered_push); - } - - em_utils_uids_free (uids); -} - -void -e_mail_shell_view_update_sidebar (EMailShellView *mail_shell_view) -{ - EMailShellContent *mail_shell_content; - EShellSidebar *shell_sidebar; - EShellView *shell_view; - EMailReader *reader; - MessageList *message_list; - CamelStore *local_store; - CamelFolder *folder; - GPtrArray *selected; - GString *buffer; - const gchar *display_name; - const gchar *folder_uri; - gchar *folder_name; - gchar *title; - guint32 num_deleted; - guint32 num_junked; - guint32 num_junked_not_deleted; - guint32 num_unread; - guint32 num_visible; - - g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); - - mail_shell_content = mail_shell_view->priv->mail_shell_content; - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - - reader = E_MAIL_READER (mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - folder_uri = message_list->folder_uri; - folder = message_list->folder; - - local_store = e_mail_local_get_store (); - - /* If no folder is selected, reset the sidebar banners - * to their default values and stop. */ - if (folder == NULL) { - GtkAction *action; - gchar *label; - - action = e_shell_view_get_action (shell_view); - - g_object_get (action, "label", &label, NULL); - e_shell_sidebar_set_secondary_text (shell_sidebar, NULL); - e_shell_view_set_title (shell_view, label); - g_free (label); - - return; - } - - camel_object_get ( - folder, NULL, - CAMEL_FOLDER_NAME, &folder_name, - CAMEL_FOLDER_DELETED, &num_deleted, - CAMEL_FOLDER_JUNKED, &num_junked, - CAMEL_FOLDER_JUNKED_NOT_DELETED, &num_junked_not_deleted, - CAMEL_FOLDER_UNREAD, &num_unread, - CAMEL_FOLDER_VISIBLE, &num_visible, - NULL); - - buffer = g_string_sized_new (256); - selected = message_list_get_selected (message_list); - - if (selected->len > 1) - g_string_append_printf ( - buffer, ngettext ("%d selected, ", "%d selected, ", - selected->len), selected->len); - - if (CAMEL_IS_VTRASH_FOLDER (folder)) { - CamelVTrashFolder *trash_folder; - - trash_folder = (CamelVTrashFolder *) folder; - - /* "Trash" folder */ - if (trash_folder->type == CAMEL_VTRASH_FOLDER_TRASH) - g_string_append_printf ( - buffer, ngettext ("%d deleted", - "%d deleted", num_deleted), num_deleted); - - /* "Junk" folder (hide deleted messages) */ - else if (e_mail_reader_get_hide_deleted (reader)) - g_string_append_printf ( - buffer, ngettext ("%d junk", - "%d junk", num_junked_not_deleted), - num_junked_not_deleted); - - /* "Junk" folder (show deleted messages) */ - else - g_string_append_printf ( - buffer, ngettext ("%d junk", "%d junk", - num_junked), num_junked); - - /* "Drafts" folder */ - } else if (em_utils_folder_is_drafts (folder, folder_uri)) { - g_string_append_printf ( - buffer, ngettext ("%d draft", "%d drafts", - num_visible), num_visible); - - /* "Outbox" folder */ - } else if (em_utils_folder_is_outbox (folder, folder_uri)) { - g_string_append_printf ( - buffer, ngettext ("%d unsent", "%d unsent", - num_visible), num_visible); - - /* "Sent" folder */ - } else if (em_utils_folder_is_sent (folder, folder_uri)) { - g_string_append_printf ( - buffer, ngettext ("%d sent", "%d sent", - num_visible), num_visible); - - /* Normal folder */ - } else { - if (!e_mail_reader_get_hide_deleted (reader)) - num_visible += - num_deleted - num_junked + - num_junked_not_deleted; - - if (num_unread > 0 && selected->len <= 1) - g_string_append_printf ( - buffer, ngettext ("%d unread, ", - "%d unread, ", num_unread), num_unread); - g_string_append_printf ( - buffer, ngettext ("%d total", "%d total", - num_visible), num_visible); - } - - message_list_free_uids (message_list, selected); - - /* Choose a suitable folder name for displaying. */ - if (folder->parent_store == local_store && ( - strcmp (folder_name, "Drafts") == 0 || - strcmp (folder_name, "Inbox") == 0 || - strcmp (folder_name, "Outbox") == 0 || - strcmp (folder_name, "Sent") == 0 || - strcmp (folder_name, "Templates") == 0)) - display_name = _(folder_name); - else if (strcmp (folder_name, "INBOX") == 0) - display_name = _("Inbox"); - else - display_name = folder_name; - - title = g_strdup_printf ("%s (%s)", display_name, buffer->str); - e_shell_sidebar_set_secondary_text (shell_sidebar, buffer->str); - e_shell_view_set_title (shell_view, title); - g_free (title); - - camel_object_free (folder, CAMEL_FOLDER_NAME, folder_name); - g_string_free (buffer, TRUE); -} diff --git a/mail/e-mail-shell-view-private.h b/mail/e-mail-shell-view-private.h deleted file mode 100644 index 988d494219..0000000000 --- a/mail/e-mail-shell-view-private.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * e-mail-shell-view-private.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_MAIL_SHELL_VIEW_PRIVATE_H -#define E_MAIL_SHELL_VIEW_PRIVATE_H - -#include "e-mail-shell-view.h" - -#include -#include -#include -#include -#include -#include /* for camel_search_word */ - -#include "e-util/e-util.h" -#include "e-util/e-binding.h" -#include "e-util/gconf-bridge.h" -#include "e-util/e-account-utils.h" -#include "filter/filter-part.h" -#include "widgets/misc/e-popup-action.h" -#include "widgets/menus/gal-view-instance.h" - -#include "e-mail-label-dialog.h" -#include "e-mail-label-list-store.h" -#include "e-mail-local.h" -#include "e-mail-reader.h" -#include "e-mail-store.h" -#include "em-composer-utils.h" -#include "em-folder-properties.h" -#include "em-folder-selector.h" -#include "em-folder-utils.h" -#include "em-subscribe-editor.h" -#include "em-utils.h" -#include "mail-autofilter.h" -#include "mail-config.h" -#include "mail-ops.h" -#include "mail-send-recv.h" -#include "mail-vfolder.h" - -#include "e-mail-shell-backend.h" -#include "e-mail-shell-content.h" -#include "e-mail-shell-sidebar.h" -#include "e-mail-shell-view-actions.h" - -#define E_MAIL_SHELL_VIEW_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_MAIL_SHELL_VIEW, EMailShellViewPrivate)) - -/* Shorthand, requires a variable named "shell_window". */ -#define ACTION(name) \ - (E_SHELL_WINDOW_ACTION_##name (shell_window)) -#define ACTION_GROUP(name) \ - (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) - -/* For use in dispose() methods. */ -#define DISPOSE(obj) \ - G_STMT_START { \ - if ((obj) != NULL) { g_object_unref (obj); (obj) = NULL; } \ - } G_STMT_END - -/* ETable Specifications */ -#define ETSPEC_FILENAME "message-list.etspec" - -G_BEGIN_DECLS - -/* Filter items are displayed in ascending order. - * Labels are numbered from zero, so subsequent items must have - * sufficiently large values. Unfortunately this introduces an - * arbitrary upper bound on labels. */ -enum { - MAIL_FILTER_ALL_MESSAGES = -3, - MAIL_FILTER_UNREAD_MESSAGES = -2, - MAIL_FILTER_NO_LABEL = -1, - /* Labels go here */ - MAIL_FILTER_READ_MESSAGES = 5000, - MAIL_FILTER_RECENT_MESSAGES = 5001, - MAIL_FILTER_LAST_5_DAYS_MESSAGES = 5002, - MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS = 5003, - MAIL_FILTER_IMPORTANT_MESSAGES = 5004, - MAIL_FILTER_MESSAGES_NOT_JUNK = 5005 -}; - -/* Search items are displayed in ascending order. */ -enum { - MAIL_SEARCH_SUBJECT_OR_SENDER_CONTAINS, - MAIL_SEARCH_SUBJECT_OR_RECIPIENTS_CONTAINS, - MAIL_SEARCH_RECIPIENTS_CONTAIN, - MAIL_SEARCH_MESSAGE_CONTAINS, - MAIL_SEARCH_SUBJECT_CONTAINS, - MAIL_SEARCH_SENDER_CONTAINS, - MAIL_SEARCH_BODY_CONTAINS, - MAIL_NUM_SEARCH_RULES -}; - -/* Scope items are displayed in ascending order. */ -enum { - MAIL_SCOPE_CURRENT_FOLDER, - MAIL_SCOPE_CURRENT_ACCOUNT, - MAIL_SCOPE_ALL_ACCOUNTS -}; - -struct _EMailShellViewPrivate { - - /*** Other Stuff ***/ - - /* These are just for convenience. */ - EMailShellBackend *mail_shell_backend; - EMailShellContent *mail_shell_content; - EMailShellSidebar *mail_shell_sidebar; - - /* For UI merging and unmerging. */ - guint merge_id; - guint label_merge_id; - - /* Filter rules correspond to the search entry menu. */ - FilterRule *search_rules[MAIL_NUM_SEARCH_RULES]; - - guint show_deleted : 1; -}; - -void e_mail_shell_view_private_init - (EMailShellView *mail_shell_view, - EShellViewClass *shell_view_class); -void e_mail_shell_view_private_constructed - (EMailShellView *mail_shell_view); -void e_mail_shell_view_private_dispose - (EMailShellView *mail_shell_view); -void e_mail_shell_view_private_finalize - (EMailShellView *mail_shell_view); - -/* Private Utilities */ - -void e_mail_shell_view_actions_init - (EMailShellView *mail_shell_view); -void e_mail_shell_view_restore_state - (EMailShellView *mail_shell_view); -void e_mail_shell_view_execute_search - (EMailShellView *mail_shell_view); -void e_mail_shell_view_create_filter_from_selected - (EMailShellView *mail_shell_view, - gint filter_type); -void e_mail_shell_view_create_vfolder_from_selected - (EMailShellView *mail_shell_view, - gint vfolder_type); -void e_mail_shell_view_update_popup_labels - (EMailShellView *mail_shell_view); -void e_mail_shell_view_update_search_filter - (EMailShellView *mail_shell_view); -void e_mail_shell_view_update_sidebar - (EMailShellView *mail_shell_view); - -G_END_DECLS - -#endif /* E_MAIL_SHELL_VIEW_PRIVATE_H */ diff --git a/mail/e-mail-shell-view.c b/mail/e-mail-shell-view.c deleted file mode 100644 index 8d8b4aa2b3..0000000000 --- a/mail/e-mail-shell-view.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * e-mail-shell-view.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-mail-shell-view-private.h" - -static gpointer parent_class; -static GType mail_shell_view_type; - -static void -mail_shell_view_dispose (GObject *object) -{ - e_mail_shell_view_private_dispose (E_MAIL_SHELL_VIEW (object)); - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -mail_shell_view_finalize (GObject *object) -{ - e_mail_shell_view_private_finalize (E_MAIL_SHELL_VIEW (object)); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -mail_shell_view_constructed (GObject *object) -{ - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (parent_class)->constructed (object); - - e_mail_shell_view_private_constructed (E_MAIL_SHELL_VIEW (object)); -} - -static void -mail_shell_view_toggled (EShellView *shell_view) -{ - EMailShellViewPrivate *priv; - EShellWindow *shell_window; - GtkUIManager *ui_manager; - const gchar *basename; - gboolean view_is_active; - - /* Chain up to parent's toggled() method. */ - E_SHELL_VIEW_CLASS (parent_class)->toggled (shell_view); - - priv = E_MAIL_SHELL_VIEW_GET_PRIVATE (shell_view); - - shell_window = e_shell_view_get_shell_window (shell_view); - ui_manager = e_shell_window_get_ui_manager (shell_window); - view_is_active = e_shell_view_is_active (shell_view); - basename = E_MAIL_READER_UI_DEFINITION; - - if (view_is_active && priv->merge_id == 0) { - priv->merge_id = e_load_ui_definition (ui_manager, basename); - e_mail_reader_create_charset_menu ( - E_MAIL_READER (priv->mail_shell_content), - ui_manager, priv->merge_id); - } else if (!view_is_active && priv->merge_id != 0) { - gtk_ui_manager_remove_ui (ui_manager, priv->merge_id); - priv->merge_id = 0; - } - - gtk_ui_manager_ensure_update (ui_manager); -} - -static void -mail_shell_view_update_actions (EShellView *shell_view) -{ - EMailShellView *mail_shell_view; - EMailShellSidebar *mail_shell_sidebar; - EShellContent *shell_content; - EShellSidebar *shell_sidebar; - EShellWindow *shell_window; - EMFolderTree *folder_tree; - EAccount *account = NULL; - GtkAction *action; - const gchar *label; - gchar *uri; - gboolean sensitive; - guint32 state; - - /* Be descriptive. */ - gboolean account_is_groupwise; - gboolean folder_allows_children; - gboolean folder_can_be_deleted; - gboolean folder_is_junk; - gboolean folder_is_outbox; - gboolean folder_is_store; - gboolean folder_is_trash; - - mail_shell_view = E_MAIL_SHELL_VIEW (shell_view); - - shell_window = e_shell_view_get_shell_window (shell_view); - - shell_content = e_shell_view_get_shell_content (shell_view); - e_mail_reader_update_actions (E_MAIL_READER (shell_content)); - - mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; - folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); - - shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - state = e_shell_sidebar_check_state (shell_sidebar); - - folder_allows_children = - (state & E_MAIL_SHELL_SIDEBAR_FOLDER_ALLOWS_CHILDREN); - folder_can_be_deleted = - (state & E_MAIL_SHELL_SIDEBAR_FOLDER_CAN_DELETE); - folder_is_junk = - (state & E_MAIL_SHELL_SIDEBAR_FOLDER_IS_JUNK); - folder_is_outbox = - (state & E_MAIL_SHELL_SIDEBAR_FOLDER_IS_OUTBOX); - folder_is_store = - (state & E_MAIL_SHELL_SIDEBAR_FOLDER_IS_STORE); - folder_is_trash = - (state & E_MAIL_SHELL_SIDEBAR_FOLDER_IS_TRASH); - - uri = em_folder_tree_get_selected_uri (folder_tree); - if (uri != NULL) { - account = mail_config_get_account_by_source_url (uri); - - /* FIXME This belongs in a GroupWise plugin. */ - account_is_groupwise = - (g_strrstr (uri, "groupwise://") != NULL) && - account != NULL && account->parent_uid != NULL; - - g_free (uri); - } - - action = ACTION (MAIL_ACCOUNT_DISABLE); - sensitive = (account != NULL) && folder_is_store; - if (account_is_groupwise) - label = _("Proxy _Logout"); - else - label = _("_Disable Account"); - gtk_action_set_sensitive (action, sensitive); - g_object_set (action, "label", label, NULL); - - action = ACTION (MAIL_EMPTY_TRASH); - sensitive = folder_is_trash; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MAIL_FLUSH_OUTBOX); - sensitive = folder_is_outbox; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MAIL_FOLDER_COPY); - sensitive = !folder_is_store; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MAIL_FOLDER_DELETE); - sensitive = !folder_is_store && folder_can_be_deleted; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MAIL_FOLDER_MOVE); - sensitive = !folder_is_store && folder_can_be_deleted; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MAIL_FOLDER_NEW); - sensitive = folder_allows_children; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MAIL_FOLDER_PROPERTIES); - sensitive = !folder_is_store; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MAIL_FOLDER_REFRESH); - sensitive = !folder_is_store; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MAIL_FOLDER_RENAME); - sensitive = !folder_is_store && folder_can_be_deleted; - gtk_action_set_sensitive (action, sensitive); - - e_mail_shell_view_update_popup_labels (mail_shell_view); -} - -static void -mail_shell_view_class_init (EMailShellViewClass *class, - GTypeModule *type_module) -{ - GObjectClass *object_class; - EShellViewClass *shell_view_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (EMailShellViewPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->dispose = mail_shell_view_dispose; - object_class->finalize = mail_shell_view_finalize; - object_class->constructed = mail_shell_view_constructed; - - shell_view_class = E_SHELL_VIEW_CLASS (class); - shell_view_class->label = _("Mail"); - shell_view_class->icon_name = "evolution-mail"; - shell_view_class->ui_definition = "evolution-mail.ui"; - shell_view_class->ui_manager_id = "org.gnome.evolution.mail"; - shell_view_class->search_options = "/mail-search-options"; - shell_view_class->search_rules = "searchtypes.xml"; - shell_view_class->new_shell_content = e_mail_shell_content_new; - shell_view_class->new_shell_sidebar = e_mail_shell_sidebar_new; - shell_view_class->toggled = mail_shell_view_toggled; - shell_view_class->update_actions = mail_shell_view_update_actions; -} - -static void -mail_shell_view_init (EMailShellView *mail_shell_view, - EShellViewClass *shell_view_class) -{ - mail_shell_view->priv = - E_MAIL_SHELL_VIEW_GET_PRIVATE (mail_shell_view); - - e_mail_shell_view_private_init (mail_shell_view, shell_view_class); -} - -GType -e_mail_shell_view_get_type (void) -{ - return mail_shell_view_type; -} - -void -e_mail_shell_view_register_type (GTypeModule *type_module) -{ - const GTypeInfo type_info = { - sizeof (EMailShellViewClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) mail_shell_view_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (EMailShellView), - 0, /* n_preallocs */ - (GInstanceInitFunc) mail_shell_view_init, - NULL /* value_table */ - }; - - mail_shell_view_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_VIEW, - "EMailShellView", &type_info, 0); -} diff --git a/mail/e-mail-shell-view.h b/mail/e-mail-shell-view.h deleted file mode 100644 index d20bde74a6..0000000000 --- a/mail/e-mail-shell-view.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * e-mail-shell-view.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_MAIL_SHELL_VIEW_H -#define E_MAIL_SHELL_VIEW_H - -#include - -/* Standard GObject macros */ -#define E_TYPE_MAIL_SHELL_VIEW \ - (e_mail_shell_view_get_type ()) -#define E_MAIL_SHELL_VIEW(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_MAIL_SHELL_VIEW, EMailShellView)) -#define E_MAIL_SHELL_VIEW_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_MAIL_SHELL_VIEW, EMailShellViewClass)) -#define E_IS_MAIL_SHELL_VIEW(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_MAIL_SHELL_VIEW)) -#define E_IS_MAIL_SHELL_VIEW_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_MAIL_SHELL_VIEW)) -#define E_MAIL_SHELL_VIEW_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_MAIL_SHELL_VIEW, EMailShellViewClass)) - -G_BEGIN_DECLS - -typedef struct _EMailShellView EMailShellView; -typedef struct _EMailShellViewClass EMailShellViewClass; -typedef struct _EMailShellViewPrivate EMailShellViewPrivate; - -struct _EMailShellView { - EShellView parent; - EMailShellViewPrivate *priv; -}; - -struct _EMailShellViewClass { - EShellViewClass parent_class; -}; - -GType e_mail_shell_view_get_type (void); -void e_mail_shell_view_register_type - (GTypeModule *type_module); -gboolean e_mail_shell_view_get_show_deleted - (EMailShellView *mail_shell_view); -void e_mail_shell_view_set_show_deleted - (EMailShellView *mail_shell_view, - gboolean show_deleted); - -G_END_DECLS - -#endif /* E_MAIL_SHELL_VIEW_H */ diff --git a/mail/em-account-editor.c b/mail/em-account-editor.c deleted file mode 100644 index 4ae929513e..0000000000 --- a/mail/em-account-editor.c +++ /dev/null @@ -1,3114 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Dan Winship - * Jeffrey Stedfast - * Michael Zucchi - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -/* - work before merge can occur: - - verify behaviour. - work out what to do with the startup druid. - - also need to work out: - how to remove unecessary items from a service url once - configured (removing settings from other types). - -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include -#include - -#include - -#include - -#include -#include - -#include - -#include "e-util/e-error.h" -#include "e-util/e-account-utils.h" -#include "e-util/e-signature-utils.h" -#include "e-util/e-util-private.h" - -#include "e-mail-local.h" -#include "em-config.h" -#include "em-folder-selection-button.h" -#include "em-account-editor.h" -#include "mail-session.h" -#include "mail-send-recv.h" -#include "e-signature-editor.h" -#include "em-utils.h" -#include "em-composer-prefs.h" -#include "mail-config.h" -#include "mail-ops.h" -#include "mail-mt.h" - -#if defined (HAVE_NSS) -#include "smime/gui/e-cert-selector.h" -#endif - -#define d(x) - -/* econfig item for the extra config hings */ -struct _receive_options_item { - EMConfigItem item; - - /* Only CAMEL_PROVIDER_CONF_ENTRYs GtkEntrys are stored here. - The auto-detect camel provider code will probably be removed */ - GHashTable *extra_table; -}; - -typedef struct _EMAccountEditorService { - EMAccountEditor *emae; /* parent pointer, for callbacks */ - - /* NOTE: keep all widgets together, first frame last check_dialog */ - GtkWidget *frame; - GtkWidget *container; - - GtkComboBox *providers; - - GtkLabel *description; - GtkLabel *hostlabel; - GtkEntry *hostname; - GtkLabel *userlabel; - GtkEntry *username; - GtkEntry *path; - GtkLabel *pathlabel; - GtkWidget *pathentry; - - GtkWidget *ssl_frame; - GtkComboBox *use_ssl; - GtkWidget *ssl_hbox; - GtkWidget *no_ssl; - - GtkWidget *auth_frame; - GtkComboBox *authtype; - - GtkWidget *authitem; - GtkToggleButton *remember; - GtkButton *check_supported; - GtkToggleButton *needs_auth; - - GtkWidget *check_dialog; - gint check_id; - - GList *authtypes; /* if "Check supported" */ - CamelProvider *provider; - CamelProviderType type; - - gint auth_changed_id; -} EMAccountEditorService; - -struct _EMAccountEditorPrivate { - struct _EMConfig *config; - GList *providers; - - /* signatures */ - GtkComboBox *signatures_dropdown; - guint sig_added_id; - guint sig_removed_id; - guint sig_changed_id; - const gchar *sig_uid; - - /* incoming mail */ - EMAccountEditorService source; - - /* extra incoming config */ - CamelProvider *extra_provider; - GSList *extra_items; /* this is freed by the econfig automatically */ - - /* outgoing mail */ - EMAccountEditorService transport; - - /* account management */ - GtkEntry *identity_entries[5]; - GtkToggleButton *default_account; - GtkWidget *management_frame; - - /* special folders */ - GtkButton *drafts_folder_button; - GtkButton *sent_folder_button; - GtkButton *restore_folders_button; - - /* Security */ - GtkEntry *pgp_key; - GtkToggleButton *pgp_encrypt_to_self; - GtkToggleButton *pgp_always_sign; - GtkToggleButton *pgp_no_imip_sign; - GtkToggleButton *pgp_always_trust; - - GtkToggleButton *smime_sign_default; - GtkEntry *smime_sign_key; - GtkButton *smime_sign_key_select; - GtkButton *smime_sign_key_clear; - GtkButton *smime_sign_select; - GtkToggleButton *smime_encrypt_default; - GtkToggleButton *smime_encrypt_to_self; - GtkEntry *smime_encrypt_key; - GtkButton *smime_encrypt_key_select; - GtkButton *smime_encrypt_key_clear; - - /* for e-config callbacks, each page sets up its widgets, then they are dealed out by the get_widget callback in order*/ - GtkWidget *widgets[5]; - const gchar *widgets_name[5]; - gint widgets_index; - - /* for druid page preparation */ - guint identity_set:1; - guint receive_set:1; - guint management_set:1; -}; - -static void emae_refresh_authtype(EMAccountEditor *emae, EMAccountEditorService *service); -static void em_account_editor_construct(EMAccountEditor *emae, EAccount *account, em_account_editor_t type, const gchar *id); -static void emae_account_folder_changed(EMFolderSelectionButton *folder, EMAccountEditor *emae); -static GtkVBoxClass *emae_parent; - -static void -emae_init(GObject *o) -{ - EMAccountEditor *emae = (EMAccountEditor *)o; - - emae->priv = g_malloc0(sizeof(*emae->priv)); - - emae->priv->source.emae = emae; - emae->priv->transport.emae = emae; -} - -static void -emae_finalise(GObject *o) -{ - EMAccountEditor *emae = (EMAccountEditor *)o; - EMAccountEditorPrivate *p = emae->priv; - - if (p->sig_added_id) { - ESignatureList *signatures = e_get_signature_list (); - - g_signal_handler_disconnect(signatures, p->sig_added_id); - g_signal_handler_disconnect(signatures, p->sig_removed_id); - g_signal_handler_disconnect(signatures, p->sig_changed_id); - } - - g_list_free(p->source.authtypes); - g_list_free(p->transport.authtypes); - - g_list_free(p->providers); - g_free(p); - - g_object_unref(emae->account); - if (emae->original) - g_object_unref(emae->original); - - ((GObjectClass *)emae_parent)->finalize(o); -} - -static void -emae_class_init(GObjectClass *klass) -{ - klass->finalize = emae_finalise; -} - -GType -em_account_editor_get_type(void) -{ - static GType type = 0; - - if (type == 0) { - static const GTypeInfo info = { - sizeof(EMAccountEditorClass), - NULL, NULL, - (GClassInitFunc)emae_class_init, - NULL, NULL, - sizeof(EMAccountEditor), 0, - (GInstanceInitFunc)emae_init - }; - emae_parent = g_type_class_ref(G_TYPE_OBJECT); - type = g_type_register_static(G_TYPE_OBJECT, "EMAccountEditor", &info, 0); - } - - return type; -} - -/** - * em_account_editor_new: - * @account: - * @type: - * - * Create a new account editor. If @account is NULL then this is to - * create a new account, else @account is copied to a working - * structure and is for editing an existing account. - * - * Return value: - **/ -EMAccountEditor *em_account_editor_new(EAccount *account, em_account_editor_t type, const gchar *id) -{ - EMAccountEditor *emae = g_object_new(em_account_editor_get_type(), NULL); - - em_account_editor_construct(emae, account, type, id); - - return emae; -} - -/** - * em_account_editor_new_for_pages: - * @account: - * @type: - * - * Create a new account editor. If @account is NULL then this is to - * create a new account, else @account is copied to a working - * structure and is for editing an existing account. - * - * Return value: - **/ -EMAccountEditor *em_account_editor_new_for_pages(EAccount *account, em_account_editor_t type, gchar *id, GtkWidget **pages) -{ - EMAccountEditor *emae = g_object_new(em_account_editor_get_type(), NULL); - emae->pages = pages; - em_account_editor_construct(emae, account, type, id); - - return emae; -} - -/* ********************************************************************** */ - -static struct { - const gchar *label; - const gchar *value; -} ssl_options[] = { - /* Translators: This string is a "Use secure connection" option for - the Mailer. It will not use an encrypted connection. */ - { N_("No encryption"), "never" }, - /* Translators: This string is a "Use secure connection" option for - the Mailer. TLS (Transport Layer Security) is commonly known by - this abbreviation. */ - { N_("TLS encryption"), "when-possible" }, - /* Translators: This string is a "Use secure connection" option for - the Mailer. SSL (Secure Sockets Layer) is commonly known by this - abbreviation. */ - { N_("SSL encryption"), "always" } -}; - -#define num_ssl_options (sizeof (ssl_options) / sizeof (ssl_options[0])) - -static gboolean -is_email (const gchar *address) -{ - /* This is supposed to check if the address's domain could be - an FQDN but alas, it's not worth the pain and suffering. */ - const gchar *at; - - at = strchr (address, '@'); - /* make sure we have an '@' and that it's not the first or last gchar */ - if (!at || at == address || *(at + 1) == '\0') - return FALSE; - - return TRUE; -} - -static CamelURL * -emae_account_url(EMAccountEditor *emae, gint urlid) -{ - CamelURL *url = NULL; - const gchar *uri; - - uri = e_account_get_string(emae->account, urlid); - - if (uri && uri[0]) - url = camel_url_new(uri, NULL); - - if (url == NULL) { - url = camel_url_new("dummy:", NULL); - camel_url_set_protocol(url, NULL); - } - - return url; -} - -/* ********************************************************************** */ -static void -emae_license_state(GtkToggleButton *button, GtkDialog *dialog) -{ - gtk_dialog_set_response_sensitive(dialog, GTK_RESPONSE_ACCEPT, - gtk_toggle_button_get_active(button)); -} - -static gboolean -emae_load_text(GtkTextView *view, const gchar *filename) -{ - FILE *fd; - gchar filebuf[1024]; - GtkTextIter iter; - GtkTextBuffer *buffer; - gint count; - - g_return_val_if_fail (filename != NULL , FALSE); - - fd = g_fopen (filename, "r"); - if (fd) { - buffer = gtk_text_buffer_new (NULL); - gtk_text_buffer_get_start_iter (buffer, &iter); - while (!feof (fd) && !ferror (fd)) { - count = fread (filebuf, 1, sizeof (filebuf), fd); - gtk_text_buffer_insert (buffer, &iter, filebuf, count); - } - - gtk_text_view_set_buffer(GTK_TEXT_VIEW (view), GTK_TEXT_BUFFER(buffer)); - fclose (fd); - } - - return fd != NULL; -} - -static gboolean -emae_display_license(EMAccountEditor *emae, CamelProvider *prov) -{ - GladeXML *xml; - GtkWidget *w, *dialog; - gchar *tmp; - GtkResponseType response = GTK_RESPONSE_NONE; - gchar *gladefile; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - "mail-dialogs.glade", - NULL); - xml = glade_xml_new (gladefile, "license_dialog", NULL); - g_free (gladefile); - - dialog = glade_xml_get_widget(xml, "license_dialog"); - gtk_dialog_set_response_sensitive((GtkDialog *)dialog, GTK_RESPONSE_ACCEPT, FALSE); - tmp = g_strdup_printf(_("%s License Agreement"), prov->license); - gtk_window_set_title((GtkWindow *)dialog, tmp); - g_free(tmp); - - g_signal_connect(glade_xml_get_widget(xml, "license_checkbutton"), - "toggled", G_CALLBACK(emae_license_state), dialog); - - tmp = g_strdup_printf(_("\nPlease read carefully the license agreement\n" - "for %s displayed below\n" - "and tick the check box for accepting it\n"), prov->license); - gtk_label_set_text((GtkLabel *)glade_xml_get_widget(xml, "license_top_label"), tmp); - g_free(tmp); - - w = glade_xml_get_widget(xml, "license_textview"); - if (emae_load_text((GtkTextView *)w, prov->license_file)) { - gtk_text_view_set_editable((GtkTextView *)w, FALSE); - response = gtk_dialog_run((GtkDialog *)dialog); - } else { - e_error_run(emae->editor ? (GtkWindow *)gtk_widget_get_toplevel(emae->editor) : NULL, - "mail:no-load-license", prov->license_file, NULL); - } - - gtk_widget_destroy(dialog); - g_object_unref(xml); - - return (response == GTK_RESPONSE_ACCEPT); -} - -static gboolean -emae_check_license(EMAccountEditor *emae, CamelProvider *prov) -{ - gboolean accepted = TRUE; - - if (prov->flags & CAMEL_PROVIDER_HAS_LICENSE) { - GConfClient *gconf = mail_config_get_gconf_client(); - GSList *providers_list, *l; - - providers_list = gconf_client_get_list (gconf, "/apps/evolution/mail/licenses", GCONF_VALUE_STRING, NULL); - - for (l = providers_list, accepted = FALSE; l && !accepted; l = g_slist_next(l)) - accepted = (strcmp((gchar *)l->data, prov->protocol) == 0); - - if (!accepted - && (accepted = emae_display_license(emae, prov)) == TRUE) { - providers_list = g_slist_append(providers_list, g_strdup(prov->protocol)); - gconf_client_set_list(gconf, - "/apps/evolution/mail/licenses", - GCONF_VALUE_STRING, - providers_list, NULL); - } - - g_slist_foreach(providers_list, (GFunc)g_free, NULL); - g_slist_free(providers_list); - } - - return accepted; -} - -static void -default_folders_clicked (GtkButton *button, gpointer user_data) -{ - EMAccountEditor *emae = user_data; - const gchar *uri; - - uri = e_mail_local_get_folder_uri (E_MAIL_FOLDER_DRAFTS); - em_folder_selection_button_set_selection((EMFolderSelectionButton *)emae->priv->drafts_folder_button, uri); - emae_account_folder_changed((EMFolderSelectionButton *)emae->priv->drafts_folder_button, emae); - - uri = e_mail_local_get_folder_uri (E_MAIL_FOLDER_SENT); - em_folder_selection_button_set_selection((EMFolderSelectionButton *)emae->priv->sent_folder_button, uri); - emae_account_folder_changed((EMFolderSelectionButton *)emae->priv->sent_folder_button, emae); -} - -/* custom widget factories */ -GtkWidget *em_account_editor_folder_selector_button_new (gchar *widget_name, gchar *string1, gchar *string2, gint int1, gint int2); - -GtkWidget * -em_account_editor_folder_selector_button_new (gchar *widget_name, gchar *string1, gchar *string2, gint int1, gint int2) -{ - return (GtkWidget *)em_folder_selection_button_new ( - string1 ? string1 : _("Select Folder"), NULL); -} - -GtkWidget *em_account_editor_dropdown_new(gchar *widget_name, gchar *string1, gchar *string2, gint int1, gint int2); - -GtkWidget * -em_account_editor_dropdown_new(gchar *widget_name, gchar *string1, gchar *string2, gint int1, gint int2) -{ - return gtk_combo_box_new (); -} - -GtkWidget *em_account_editor_ssl_selector_new(gchar *widget_name, gchar *string1, gchar *string2, gint int1, gint int2); - -GtkWidget * -em_account_editor_ssl_selector_new(gchar *widget_name, gchar *string1, gchar *string2, gint int1, gint int2) -{ - GtkComboBox *dropdown = (GtkComboBox *)gtk_combo_box_new(); - GtkCellRenderer *cell = gtk_cell_renderer_text_new(); - GtkListStore *store; - gint i; - GtkTreeIter iter; - - gtk_widget_show((GtkWidget *)dropdown); - - store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); - - for (i=0;ipriv; - EMAccountEditorService *service = &gui->source; - GHashTable *auto_detected; - GSList *l; - CamelProviderConfEntry *entries; - gchar *value; - gint i; - CamelURL *url; - - if (service->provider == NULL - || (entries = service->provider->extra_conf) == NULL) - return; - - d(printf("Running auto-detect\n")); - - url = emae_account_url(emae, E_ACCOUNT_SOURCE_URL); - camel_provider_auto_detect(service->provider, url, &auto_detected, NULL); - camel_url_free(url); - if (auto_detected == NULL) { - d(printf(" no values detected\n")); - return; - } - - for (i = 0; entries[i].type != CAMEL_PROVIDER_CONF_END; i++) { - struct _receive_options_item *item; - GtkWidget *w; - - if (entries[i].name == NULL - || (value = g_hash_table_lookup (auto_detected, entries[i].name)) == NULL) - continue; - - /* only 2 providers use this, and they only do it for 3 entries only */ - g_return_if_fail (entries[i].type == CAMEL_PROVIDER_CONF_ENTRY); - - w = NULL; - for (l = emae->priv->extra_items;l;l=g_slist_next(l)) { - item = l->data; - if (item->extra_table && (w = g_hash_table_lookup(item->extra_table, entries[i].name))) - break; - } - - gtk_entry_set_text((GtkEntry *)w, value?value:""); - } - - g_hash_table_foreach(auto_detected, emae_auto_detect_free, NULL); - g_hash_table_destroy(auto_detected); -} - -static gint -provider_compare (const CamelProvider *p1, const CamelProvider *p2) -{ - /* sort providers based on "location" (ie. local or remote) */ - if (p1->flags & CAMEL_PROVIDER_IS_REMOTE) { - if (p2->flags & CAMEL_PROVIDER_IS_REMOTE) - return 0; - return -1; - } else { - if (p2->flags & CAMEL_PROVIDER_IS_REMOTE) - return 1; - return 0; - } -} - -static void -emae_signature_added(ESignatureList *signatures, ESignature *sig, EMAccountEditor *emae) -{ - GtkTreeModel *model; - GtkTreeIter iter; - - model = gtk_combo_box_get_model(emae->priv->signatures_dropdown); - - gtk_list_store_append((GtkListStore *)model, &iter); - gtk_list_store_set((GtkListStore *)model, &iter, 0, sig->autogen?_("Autogenerated"):sig->name, 1, sig->uid, -1); - - gtk_combo_box_set_active(emae->priv->signatures_dropdown, gtk_tree_model_iter_n_children(model, NULL)-1); -} - -static gint -emae_signature_get_iter(EMAccountEditor *emae, ESignature *sig, GtkTreeModel **modelp, GtkTreeIter *iter) -{ - GtkTreeModel *model; - gint found = 0; - - model = gtk_combo_box_get_model(emae->priv->signatures_dropdown); - *modelp = model; - if (!gtk_tree_model_get_iter_first(model, iter)) - return FALSE; - - do { - gchar *uid; - - gtk_tree_model_get(model, iter, 1, &uid, -1); - if (uid && !strcmp(uid, sig->uid)) - found = TRUE; - g_free(uid); - } while (!found && gtk_tree_model_iter_next(model, iter)); - - return found; -} - -static void -emae_signature_removed(ESignatureList *signatures, ESignature *sig, EMAccountEditor *emae) -{ - GtkTreeIter iter; - GtkTreeModel *model; - - if (emae_signature_get_iter(emae, sig, &model, &iter)) - gtk_list_store_remove((GtkListStore *)model, &iter); -} - -static void -emae_signature_changed(ESignatureList *signatures, ESignature *sig, EMAccountEditor *emae) -{ - GtkTreeIter iter; - GtkTreeModel *model; - - if (emae_signature_get_iter(emae, sig, &model, &iter)) - gtk_list_store_set((GtkListStore *)model, &iter, 0, sig->autogen?_("Autogenerated"):sig->name, -1); -} - -static void -emae_signaturetype_changed(GtkComboBox *dropdown, EMAccountEditor *emae) -{ - gint id = gtk_combo_box_get_active(dropdown); - GtkTreeModel *model; - GtkTreeIter iter; - gchar *uid = NULL; - - if (id != -1) { - model = gtk_combo_box_get_model(dropdown); - if (gtk_tree_model_iter_nth_child(model, &iter, NULL, id)) - gtk_tree_model_get(model, &iter, 1, &uid, -1); - } - - e_account_set_string(emae->account, E_ACCOUNT_ID_SIGNATURE, uid); - g_free(uid); -} - -static void -emae_signature_new(GtkWidget *w, EMAccountEditor *emae) -{ - EShell *shell; - EShellSettings *shell_settings; - GtkWidget *parent; - gboolean html_mode; - - shell = e_shell_get_default (); - shell_settings = e_shell_get_shell_settings (shell); - parent = gtk_widget_get_toplevel (w); - - html_mode = e_shell_settings_get_boolean ( - shell_settings, "composer-format-html"); - - em_composer_prefs_new_signature (GTK_WINDOW (parent), html_mode); -} - -static GtkWidget * -emae_setup_signatures(EMAccountEditor *emae, GladeXML *xml) -{ - EMAccountEditorPrivate *p = emae->priv; - GtkComboBox *dropdown = (GtkComboBox *)glade_xml_get_widget(xml, "signature_dropdown"); - GtkCellRenderer *cell = gtk_cell_renderer_text_new(); - GtkListStore *store; - gint i, active=0; - GtkTreeIter iter; - ESignatureList *signatures; - EIterator *it; - const gchar *current = e_account_get_string(emae->account, E_ACCOUNT_ID_SIGNATURE); - GtkWidget *button; - - emae->priv->signatures_dropdown = dropdown; - gtk_widget_show((GtkWidget *)dropdown); - - store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); - - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, _("None"), 1, NULL, -1); - - signatures = e_get_signature_list (); - - if (p->sig_added_id == 0) { - p->sig_added_id = g_signal_connect(signatures, "signature-added", G_CALLBACK(emae_signature_added), emae); - p->sig_removed_id = g_signal_connect(signatures, "signature-removed", G_CALLBACK(emae_signature_removed), emae); - p->sig_changed_id = g_signal_connect(signatures, "signature-changed", G_CALLBACK(emae_signature_changed), emae); - } - - /* we need to count the 'none' entry before using the index */ - i = 1; - it = e_list_get_iterator ((EList *) signatures); - while (e_iterator_is_valid (it)) { - ESignature *sig = (ESignature *)e_iterator_get(it); - - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, sig->autogen?_("Autogenerated"):sig->name, 1, sig->uid, -1); - - if (current && !strcmp(current, sig->uid)) - active = i; - - e_iterator_next(it); - i++; - } - g_object_unref (it); - - gtk_cell_layout_pack_start((GtkCellLayout *)dropdown, cell, TRUE); - gtk_cell_layout_set_attributes((GtkCellLayout *)dropdown, cell, "text", 0, NULL); - - gtk_combo_box_set_model(dropdown, (GtkTreeModel *)store); - gtk_combo_box_set_active(dropdown, active); - - g_signal_connect(dropdown, "changed", G_CALLBACK(emae_signaturetype_changed), emae); - gtk_widget_set_sensitive((GtkWidget *)dropdown, e_account_writable(emae->account, E_ACCOUNT_ID_SIGNATURE)); - - button = glade_xml_get_widget(xml, "sigAddNew"); - g_signal_connect(button, "clicked", G_CALLBACK(emae_signature_new), emae); - gtk_widget_set_sensitive(button, - gconf_client_key_is_writable(mail_config_get_gconf_client(), - "/apps/evolution/mail/signatures", NULL)); - - return (GtkWidget *)dropdown; -} - -static void -emae_receipt_policy_changed(GtkComboBox *dropdown, EMAccountEditor *emae) -{ - gint id = gtk_combo_box_get_active(dropdown); - GtkTreeModel *model; - GtkTreeIter iter; - EAccountReceiptPolicy policy; - - if (id != -1) { - model = gtk_combo_box_get_model(dropdown); - if (gtk_tree_model_iter_nth_child(model, &iter, NULL, id)) { - gtk_tree_model_get(model, &iter, 1, &policy, -1); - e_account_set_int (emae->account, E_ACCOUNT_RECEIPT_POLICY, policy); - } - } - -} - -static GtkWidget * -emae_setup_receipt_policy (EMAccountEditor *emae, GladeXML *xml) -{ - GtkComboBox *dropdown = (GtkComboBox *)glade_xml_get_widget(xml, "receipt_policy_dropdown"); - GtkListStore *store; - gint i = 0, active = 0; - GtkTreeIter iter; - EAccountReceiptPolicy current = emae->account->receipt_policy; - static struct { - EAccountReceiptPolicy policy; - const gchar *label; - } receipt_policies[] = { - { E_ACCOUNT_RECEIPT_NEVER, N_("Never") }, - { E_ACCOUNT_RECEIPT_ALWAYS, N_("Always") }, - { E_ACCOUNT_RECEIPT_ASK, N_("Ask for each message") } - }; - - gtk_widget_show((GtkWidget *)dropdown); - - store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT); - - for (i = 0; i < 3; ++i) { - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, - 0, _(receipt_policies[i].label), - 1, receipt_policies[i].policy, - -1); - if (current == receipt_policies[i].policy) - active = i; - } - - gtk_combo_box_set_model(dropdown, (GtkTreeModel *)store); - gtk_combo_box_set_active(dropdown, active); - - g_signal_connect(dropdown, "changed", G_CALLBACK(emae_receipt_policy_changed), emae); - gtk_widget_set_sensitive((GtkWidget *)dropdown, e_account_writable(emae->account, E_ACCOUNT_RECEIPT_POLICY)); - - return (GtkWidget *)dropdown; -} - -static void -emae_account_entry_changed(GtkEntry *entry, EMAccountEditor *emae) -{ - gint item = GPOINTER_TO_INT(g_object_get_data((GObject *)entry, "account-item")); - - e_account_set_string(emae->account, item, gtk_entry_get_text(entry)); -} - -static GtkEntry * -emae_account_entry(EMAccountEditor *emae, const gchar *name, gint item, GladeXML *xml) -{ - GtkEntry *entry; - const gchar *text; - - entry = (GtkEntry *)glade_xml_get_widget(xml, name); - text = e_account_get_string(emae->account, item); - if (text) - gtk_entry_set_text(entry, text); - g_object_set_data((GObject *)entry, "account-item", GINT_TO_POINTER(item)); - g_signal_connect(entry, "changed", G_CALLBACK(emae_account_entry_changed), emae); - gtk_widget_set_sensitive((GtkWidget *)entry, e_account_writable(emae->account, item)); - - return entry; -} - -static void -emae_account_toggle_changed(GtkToggleButton *toggle, EMAccountEditor *emae) -{ - gint item = GPOINTER_TO_INT(g_object_get_data((GObject *)toggle, "account-item")); - - e_account_set_bool(emae->account, item, gtk_toggle_button_get_active(toggle)); -} - -static void -emae_account_toggle_widget(EMAccountEditor *emae, GtkToggleButton *toggle, gint item) -{ - gtk_toggle_button_set_active(toggle, e_account_get_bool(emae->account, item)); - g_object_set_data((GObject *)toggle, "account-item", GINT_TO_POINTER(item)); - g_signal_connect(toggle, "toggled", G_CALLBACK(emae_account_toggle_changed), emae); - gtk_widget_set_sensitive((GtkWidget *)toggle, e_account_writable(emae->account, item)); -} - -static GtkToggleButton * -emae_account_toggle(EMAccountEditor *emae, const gchar *name, gint item, GladeXML *xml) -{ - GtkToggleButton *toggle; - - toggle = (GtkToggleButton *)glade_xml_get_widget(xml, name); - emae_account_toggle_widget(emae, toggle, item); - - return toggle; -} - -static void -emae_account_spinint_changed(GtkSpinButton *spin, EMAccountEditor *emae) -{ - gint item = GPOINTER_TO_INT(g_object_get_data((GObject *)spin, "account-item")); - - e_account_set_int(emae->account, item, gtk_spin_button_get_value(spin)); -} - -static void -emae_account_spinint_widget(EMAccountEditor *emae, GtkSpinButton *spin, gint item) -{ - gtk_spin_button_set_value(spin, e_account_get_int(emae->account, item)); - g_object_set_data((GObject *)spin, "account-item", GINT_TO_POINTER(item)); - g_signal_connect(spin, "value_changed", G_CALLBACK(emae_account_spinint_changed), emae); - gtk_widget_set_sensitive((GtkWidget *)spin, e_account_writable(emae->account, item)); -} - -#if 0 -static GtkSpinButton * -emae_account_spinint(EMAccountEditor *emae, const gchar *name, gint item) -{ - GtkSpinButton *spin; - - spin = (GtkSpinButton *)glade_xml_get_widget(emae->priv->xml, name); - emae_account_spinint_widget(emae, spin, item); - - return spin; -} -#endif - -static void -emae_account_folder_changed(EMFolderSelectionButton *folder, EMAccountEditor *emae) -{ - gint item = GPOINTER_TO_INT(g_object_get_data((GObject *)folder, "account-item")); - - e_account_set_string(emae->account, item, em_folder_selection_button_get_selection(folder)); -} - -static EMFolderSelectionButton * -emae_account_folder(EMAccountEditor *emae, const gchar *name, gint item, gint deffolder, GladeXML *xml) -{ - EMFolderSelectionButton *folder; - const gchar *uri; - - folder = (EMFolderSelectionButton *)glade_xml_get_widget(xml, name); - uri = e_account_get_string(emae->account, item); - if (uri) { - gchar *tmp = em_uri_to_camel(uri); - - em_folder_selection_button_set_selection(folder, tmp); - g_free(tmp); - } else { - const gchar *uri; - - uri = e_mail_local_get_folder_uri (deffolder); - em_folder_selection_button_set_selection(folder, uri); - } - - g_object_set_data((GObject *)folder, "account-item", GINT_TO_POINTER(item)); - g_object_set_data((GObject *)folder, "folder-default", GINT_TO_POINTER(deffolder)); - g_signal_connect(folder, "selected", G_CALLBACK(emae_account_folder_changed), emae); - gtk_widget_show((GtkWidget *)folder); - - gtk_widget_set_sensitive((GtkWidget *)folder, e_account_writable(emae->account, item)); - - return folder; -} - -#if defined (HAVE_NSS) -static void -smime_changed(EMAccountEditor *emae) -{ - EMAccountEditorPrivate *gui = emae->priv; - gint act; - const gchar *tmp; - - tmp = gtk_entry_get_text(gui->smime_sign_key); - act = tmp && tmp[0]; - gtk_widget_set_sensitive((GtkWidget *)gui->smime_sign_key_clear, act); - gtk_widget_set_sensitive((GtkWidget *)gui->smime_sign_default, act); - if (!act) - gtk_toggle_button_set_active(gui->smime_sign_default, FALSE); - - tmp = gtk_entry_get_text(gui->smime_encrypt_key); - act = tmp && tmp[0]; - gtk_widget_set_sensitive((GtkWidget *)gui->smime_encrypt_key_clear, act); - gtk_widget_set_sensitive((GtkWidget *)gui->smime_encrypt_default, act); - gtk_widget_set_sensitive((GtkWidget *)gui->smime_encrypt_to_self, act); - if (!act) { - gtk_toggle_button_set_active(gui->smime_encrypt_default, FALSE); - gtk_toggle_button_set_active(gui->smime_encrypt_to_self, FALSE); - } -} - -static void -smime_sign_key_selected(GtkWidget *dialog, const gchar *key, EMAccountEditor *emae) -{ - EMAccountEditorPrivate *gui = emae->priv; - - if (key != NULL) { - gtk_entry_set_text(gui->smime_sign_key, key); - smime_changed(emae); - } - - gtk_widget_destroy(dialog); -} - -static void -smime_sign_key_select(GtkWidget *button, EMAccountEditor *emae) -{ - EMAccountEditorPrivate *gui = emae->priv; - GtkWidget *w; - - w = e_cert_selector_new(E_CERT_SELECTOR_SIGNER, gtk_entry_get_text(gui->smime_sign_key)); - gtk_window_set_modal((GtkWindow *)w, TRUE); - gtk_window_set_transient_for((GtkWindow *)w, (GtkWindow *)gtk_widget_get_toplevel(button)); - g_signal_connect(w, "selected", G_CALLBACK(smime_sign_key_selected), emae); - gtk_widget_show(w); -} - -static void -smime_sign_key_clear(GtkWidget *w, EMAccountEditor *emae) -{ - EMAccountEditorPrivate *gui = emae->priv; - - gtk_entry_set_text(gui->smime_sign_key, ""); - smime_changed(emae); -} - -static void -smime_encrypt_key_selected(GtkWidget *dialog, const gchar *key, EMAccountEditor *emae) -{ - EMAccountEditorPrivate *gui = emae->priv; - - if (key != NULL) { - gtk_entry_set_text(gui->smime_encrypt_key, key); - smime_changed(emae); - } - - gtk_widget_destroy(dialog); -} - -static void -smime_encrypt_key_select(GtkWidget *button, EMAccountEditor *emae) -{ - EMAccountEditorPrivate *gui = emae->priv; - GtkWidget *w; - - w = e_cert_selector_new(E_CERT_SELECTOR_SIGNER, gtk_entry_get_text(gui->smime_encrypt_key)); - gtk_window_set_modal((GtkWindow *)w, TRUE); - gtk_window_set_transient_for((GtkWindow *)w, (GtkWindow *)gtk_widget_get_toplevel(button)); - g_signal_connect(w, "selected", G_CALLBACK(smime_encrypt_key_selected), emae); - gtk_widget_show(w); -} - -static void -smime_encrypt_key_clear(GtkWidget *w, EMAccountEditor *emae) -{ - EMAccountEditorPrivate *gui = emae->priv; - - gtk_entry_set_text(gui->smime_encrypt_key, ""); - smime_changed(emae); -} -#endif - -static void -emae_url_set_hostport(CamelURL *url, const gchar *txt) -{ - const gchar *port; - gchar *host; - - /* FIXME: what if this was a raw IPv6 address? */ - if (txt && (port = strchr(txt, ':'))) { - camel_url_set_port(url, atoi(port+1)); - host = g_strdup(txt); - host[port-txt] = 0; - } else { - /* "" is converted to NULL, but if we set NULL on the url, - camel_url_to_string strips lots of details */ - host = g_strdup((txt?txt:"")); - camel_url_set_port (url, 0); - } - - g_strstrip(host); - if (txt && *txt) - camel_url_set_host(url, host); - - g_free(host); -} - -/* This is used to map a funciton which will set on the url a string value. - if widgets[0] is set, it is the entry which will be called against setval() - We need our own function for host:port decoding, as above */ -struct _provider_host_info { - guint32 flag; - void (*setval)(CamelURL *, const gchar *); - glong widgets[3]; -}; - -static struct _provider_host_info emae_source_host_info[] = { - { CAMEL_URL_PART_HOST, emae_url_set_hostport, { G_STRUCT_OFFSET(EMAccountEditorService, hostname), G_STRUCT_OFFSET(EMAccountEditorService, hostlabel), }, }, - { CAMEL_URL_PART_USER, camel_url_set_user, { G_STRUCT_OFFSET(EMAccountEditorService, username), G_STRUCT_OFFSET(EMAccountEditorService, userlabel), } }, - { CAMEL_URL_PART_PATH, camel_url_set_path, { G_STRUCT_OFFSET(EMAccountEditorService, path), G_STRUCT_OFFSET(EMAccountEditorService, pathlabel), G_STRUCT_OFFSET(EMAccountEditorService, pathentry) }, }, - { CAMEL_URL_PART_AUTH, NULL, { 0, G_STRUCT_OFFSET(EMAccountEditorService, auth_frame), }, }, - { 0 }, -}; - -static struct _provider_host_info emae_transport_host_info[] = { - { CAMEL_URL_PART_HOST, emae_url_set_hostport, { G_STRUCT_OFFSET(EMAccountEditorService, hostname), G_STRUCT_OFFSET(EMAccountEditorService, hostlabel), }, }, - { CAMEL_URL_PART_USER, camel_url_set_user, { G_STRUCT_OFFSET(EMAccountEditorService, username), G_STRUCT_OFFSET(EMAccountEditorService, userlabel), } }, - { CAMEL_URL_PART_AUTH, NULL, { 0, G_STRUCT_OFFSET(EMAccountEditorService, auth_frame), }, }, - { 0 }, -}; - -/* This is used to map each of the two services in a typical account to the widgets that represent each service. - i.e. the receiving (source) service, and the sending (transport) service. - It is used throughout the following code to drive each page */ -static struct _service_info { - gint account_uri_key; - gint save_passwd_key; - - const gchar *frame; - const gchar *type_dropdown; - - const gchar *container; - const gchar *description; - const gchar *hostname; - const gchar *hostlabel; - const gchar *username; - const gchar *userlabel; - const gchar *path; - const gchar *pathlabel; - const gchar *pathentry; - - const gchar *security_frame; - const gchar *ssl_hbox; - const gchar *use_ssl; - const gchar *ssl_disabled; - - const gchar *needs_auth; - const gchar *auth_frame; - - const gchar *authtype; - const gchar *authtype_check; - - const gchar *remember_password; - - struct _provider_host_info *host_info; -} emae_service_info[CAMEL_NUM_PROVIDER_TYPES] = { - { E_ACCOUNT_SOURCE_URL, E_ACCOUNT_SOURCE_SAVE_PASSWD, - "source_frame", "source_type_dropdown", - "source_vbox", "source_description", "source_host", "source_host_label", "source_user", "source_user_label", "source_path", "source_path_label", "source_path_entry", - "source_security_frame", "source_ssl_hbox", "source_use_ssl", "source_ssl_disabled", - NULL, "source_auth_frame", - "source_auth_dropdown", "source_check_supported", - "source_remember_password", - emae_source_host_info, - }, - { E_ACCOUNT_TRANSPORT_URL, E_ACCOUNT_TRANSPORT_SAVE_PASSWD, - "transport_frame", "transport_type_dropdown", - "transport_vbox", "transport_description", "transport_host", "transport_host_label", "transport_user", "transport_user_label", NULL, NULL, NULL, - "transport_security_frame", "transport_ssl_hbox", "transport_use_ssl", "transport_ssl_disabled", - "transport_needs_auth", "transport_auth_frame", - "transport_auth_dropdown", "transport_check_supported", - "transport_remember_password", - emae_transport_host_info, - }, -}; - -static void -emae_uri_changed(EMAccountEditorService *service, CamelURL *url) -{ - gchar *uri; - - uri = camel_url_to_string(url, 0); - - e_account_set_string(service->emae->account, emae_service_info[service->type].account_uri_key, uri); - - /* small hack for providers which are store and transport - copy settings across */ - if (service->type == CAMEL_PROVIDER_STORE - && service->provider - && CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT(service->provider)) - e_account_set_string(service->emae->account, E_ACCOUNT_TRANSPORT_URL, uri); - - g_free(uri); -} - -static void -emae_service_url_changed(EMAccountEditorService *service, void (*setval)(CamelURL *, const gchar *), GtkEntry *entry) -{ - GtkComboBox *dropdown; - gint id; - GtkTreeModel *model; - GtkTreeIter iter; - CamelServiceAuthType *authtype; - - CamelURL *url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); - const gchar *text = gtk_entry_get_text(entry); - - setval(url, (text && text[0])?text:NULL); - - if (text && text[0] && setval == camel_url_set_user) { - dropdown = service->authtype; - if(dropdown) { - id = gtk_combo_box_get_active (dropdown); - if (id != -1) { - model = gtk_combo_box_get_model (dropdown); - if (gtk_tree_model_iter_nth_child (model, &iter, NULL, id)) { - gtk_tree_model_get (model, &iter, 1, &authtype, -1); - if (authtype) - camel_url_set_authmech (url, authtype->authproto); - } - } - } - } - - emae_uri_changed(service, url); - camel_url_free(url); -} - -static void -emae_service_url_path_changed(EMAccountEditorService *service, void (*setval)(CamelURL *, const gchar *), GtkWidget *widget) -{ - GtkComboBox *dropdown; - gint id; - GtkTreeModel *model; - GtkTreeIter iter; - CamelServiceAuthType *authtype; - - CamelURL *url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); - const gchar *text = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget)); - - setval(url, (text && text[0])?text:NULL); - - if (text && text[0] && setval == camel_url_set_user) { - dropdown = service->authtype; - if(dropdown) { - id = gtk_combo_box_get_active (dropdown); - if (id != -1) { - model = gtk_combo_box_get_model (dropdown); - if (gtk_tree_model_iter_nth_child (model, &iter, NULL, id)) { - gtk_tree_model_get (model, &iter, 1, &authtype, -1); - if (authtype) - camel_url_set_authmech (url, authtype->authproto); - } - } - } - } - - emae_uri_changed(service, url); - camel_url_free(url); -} - -static void -emae_hostname_changed(GtkEntry *entry, EMAccountEditorService *service) -{ - emae_service_url_changed(service, emae_url_set_hostport, entry); -} - -static void -emae_username_changed(GtkEntry *entry, EMAccountEditorService *service) -{ - emae_service_url_changed(service, camel_url_set_user, entry); -} - -static void -emae_path_changed(GtkWidget *widget, EMAccountEditorService *service) -{ - emae_service_url_path_changed(service, camel_url_set_path, widget); -} - -static gint -emae_ssl_update(EMAccountEditorService *service, CamelURL *url) -{ - gint id = gtk_combo_box_get_active(service->use_ssl); - GtkTreeModel *model; - GtkTreeIter iter; - gchar *ssl; - - if (id == -1) - return 0; - - model = gtk_combo_box_get_model(service->use_ssl); - if (gtk_tree_model_iter_nth_child(model, &iter, NULL, id)) { - gtk_tree_model_get(model, &iter, 1, &ssl, -1); - if (!strcmp(ssl, "none")) - ssl = NULL; - camel_url_set_param(url, "use_ssl", ssl); - return 1; - } - - return 0; -} - -static void -emae_ssl_changed(GtkComboBox *dropdown, EMAccountEditorService *service) -{ - CamelURL *url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); - - if (emae_ssl_update(service, url)) - emae_uri_changed(service, url); - camel_url_free(url); -} - -static void -emae_service_provider_changed(EMAccountEditorService *service) -{ - gint i, j; - void (*show)(GtkWidget *); - CamelURL *url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); - - if (service->provider) { - gint enable; - GtkWidget *dwidget = NULL; - - camel_url_set_protocol(url, service->provider->protocol); - gtk_label_set_text(service->description, service->provider->description); - if (!emae_check_license(service->emae, service->provider)) - gtk_widget_hide(service->frame); - else - gtk_widget_show(service->frame); - - enable = e_account_writable_option(service->emae->account, service->provider->protocol, "auth"); - gtk_widget_set_sensitive((GtkWidget *)service->authtype, enable); - gtk_widget_set_sensitive((GtkWidget *)service->check_supported, enable); - - enable = e_account_writable_option(service->emae->account, service->provider->protocol, "use_ssl"); - gtk_widget_set_sensitive((GtkWidget *)service->use_ssl, enable); - - enable = e_account_writable(service->emae->account, emae_service_info[service->type].save_passwd_key); - gtk_widget_set_sensitive((GtkWidget *)service->remember, enable); - - for (i=0;emae_service_info[service->type].host_info[i].flag;i++) { - GtkWidget *w; - gint hide; - struct _provider_host_info *info = &emae_service_info[service->type].host_info[i]; - - enable = CAMEL_PROVIDER_ALLOWS(service->provider, info->flag); - hide = CAMEL_PROVIDER_HIDDEN(service->provider, info->flag); - show = (enable && !hide)?gtk_widget_show:gtk_widget_hide; - - for (j=0; j < sizeof(info->widgets)/sizeof(info->widgets[0]); j++) { - if (info->widgets[j] && (w = G_STRUCT_MEMBER(GtkWidget *, service, info->widgets[j]))) { - show(w); - if (j == 0) { - if (dwidget == NULL && enable) - dwidget = w; - - if (info->setval && !hide) - info->setval(url, enable?gtk_entry_get_text((GtkEntry *)w):NULL); - } - } - } - } - - if (dwidget) - gtk_widget_grab_focus(dwidget); - - if (CAMEL_PROVIDER_ALLOWS(service->provider, CAMEL_URL_PART_AUTH)) { - GList *ll; - - /* try to keep the authmech from the current url, or clear it */ - if (url->authmech) { - if (service->provider->authtypes) { - for (ll = service->provider->authtypes;ll;ll = g_list_next(ll)) - if (!strcmp(url->authmech, ((CamelServiceAuthType *)ll->data)->authproto)) - break; - if (ll == NULL) - camel_url_set_authmech(url, NULL); - } else { - camel_url_set_authmech(url, NULL); - } - } - - emae_refresh_authtype(service->emae, service); - if (service->needs_auth && !CAMEL_PROVIDER_NEEDS(service->provider, CAMEL_URL_PART_AUTH)) - gtk_widget_show((GtkWidget *)service->needs_auth); - } else { - if (service->needs_auth) - gtk_widget_hide((GtkWidget *)service->needs_auth); - } -#ifdef HAVE_SSL - gtk_widget_hide(service->no_ssl); - if (service->provider->flags & CAMEL_PROVIDER_SUPPORTS_SSL) { - emae_ssl_update(service, url); - show = gtk_widget_show; - } else { - camel_url_set_param(url, "use_ssl", NULL); - show = gtk_widget_hide; - } - show(service->ssl_frame); - show(service->ssl_hbox); -#else - gtk_widget_hide(service->ssl_hbox); - gtk_widget_show(service->no_ssl); - camel_url_set_param(url, "use_ssl", NULL); -#endif - } else { - camel_url_set_protocol(url, NULL); - gtk_label_set_text(service->description, ""); - gtk_widget_hide(service->frame); - gtk_widget_hide(service->auth_frame); - gtk_widget_hide(service->ssl_frame); - } - - /* FIXME: linked services? */ - /* FIXME: permissions setup */ - - emae_uri_changed(service, url); - camel_url_free(url); -} - -static void -emae_provider_changed(GtkComboBox *dropdown, EMAccountEditorService *service) -{ - gint id = gtk_combo_box_get_active(dropdown); - GtkTreeModel *model; - GtkTreeIter iter; - - if (id == -1) - return; - - model = gtk_combo_box_get_model(dropdown); - if (!gtk_tree_model_iter_nth_child(model, &iter, NULL, id)) - return; - - gtk_tree_model_get(model, &iter, 1, &service->provider, -1); - - g_list_free(service->authtypes); - service->authtypes = NULL; - - emae_service_provider_changed(service); - - e_config_target_changed((EConfig *)service->emae->priv->config, E_CONFIG_TARGET_CHANGED_REBUILD); -} - -static void -emae_refresh_providers(EMAccountEditor *emae, EMAccountEditorService *service) -{ - EAccount *account = emae->account; - GtkListStore *store; - GtkTreeIter iter; - GList *l; - GtkCellRenderer *cell = gtk_cell_renderer_text_new(); - GtkComboBox *dropdown; - gint active = 0, i; - struct _service_info *info = &emae_service_info[service->type]; - const gchar *uri = e_account_get_string(account, info->account_uri_key); - gchar *current = NULL; - const gchar *tmp; - CamelURL *url; - - dropdown = service->providers; - gtk_widget_show((GtkWidget *)dropdown); - - if (uri) { - const gchar *colon = strchr(uri, ':'); - gint len; - - if (colon) { - len = colon-uri; - current = g_alloca(len+1); - memcpy(current, uri, len); - current[len] = 0; - } - } else { - current = (gchar *) "imap"; - } - - store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); - - i = 0; - - /* We just special case each type here, its just easier */ - if (service->type == CAMEL_PROVIDER_STORE) { - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, _("None"), 1, NULL, -1); - i++; - } - - for (l=emae->priv->providers; l; l=l->next) { - CamelProvider *provider = l->data; - - if (!((strcmp(provider->domain, "mail") == 0 - || strcmp (provider->domain, "news") == 0) - && provider->object_types[service->type] - && (service->type != CAMEL_PROVIDER_STORE || (provider->flags & CAMEL_PROVIDER_IS_SOURCE) != 0)) - /* hardcode not showing providers who's transport is done in the store */ - || (service->type == CAMEL_PROVIDER_TRANSPORT - && CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider))) - continue; - - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, provider->name, 1, provider, -1); - - /* find the displayed and set default */ - if (i == 0 || (current && strcmp(provider->protocol, current) == 0)) { - service->provider = provider; - active = i; - - /* we need to set this value on the uri too */ - if (current == NULL) { - CamelURL *url = emae_account_url(emae, info->account_uri_key); - - camel_url_set_protocol(url, provider->protocol); - emae_uri_changed(service, url); - camel_url_free(url); - } - } - i++; - } - - - gtk_cell_layout_clear((GtkCellLayout *)dropdown); - gtk_combo_box_set_model(dropdown, (GtkTreeModel *)store); - gtk_cell_layout_pack_start((GtkCellLayout *)dropdown, cell, TRUE); - gtk_cell_layout_set_attributes((GtkCellLayout *)dropdown, cell, "text", 0, NULL); - - g_signal_handlers_disconnect_by_func(dropdown, emae_provider_changed, service); - gtk_combo_box_set_active(dropdown, -1); /* needed for gtkcombo bug(?) */ - gtk_combo_box_set_active(dropdown, active); - g_signal_connect(dropdown, "changed", G_CALLBACK(emae_provider_changed), service); - - if (!uri || (url = camel_url_new(uri, NULL)) == NULL) { - return; - } - - tmp = camel_url_get_param(url, "use_ssl"); - if (tmp == NULL) - tmp = "never"; - for (i=0;iuse_ssl, i); - break; - } - } -} - -static void -emae_authtype_changed(GtkComboBox *dropdown, EMAccountEditorService *service) -{ - gint id = gtk_combo_box_get_active(dropdown); - GtkTreeModel *model; - GtkTreeIter iter; - CamelServiceAuthType *authtype; - CamelURL *url; - - if (id == -1) - return; - - url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); - model = gtk_combo_box_get_model(dropdown); - if (gtk_tree_model_iter_nth_child(model, &iter, NULL, id)) { - gtk_tree_model_get(model, &iter, 1, &authtype, -1); - if (authtype) - camel_url_set_authmech(url, authtype->authproto); - else - camel_url_set_authmech(url, NULL); - emae_uri_changed(service, url); - } - camel_url_free(url); - - gtk_widget_set_sensitive((GtkWidget *)service->remember, - authtype - ?(authtype->need_password && e_account_writable(service->emae->account, emae_service_info[service->type].save_passwd_key)) - :FALSE); -} - -static void -emae_needs_auth(GtkToggleButton *toggle, EMAccountEditorService *service) -{ - gint need = gtk_toggle_button_get_active(toggle); - - gtk_widget_set_sensitive(service->auth_frame, need); - - if (need) - emae_authtype_changed(service->authtype, service); - else { - CamelURL *url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); - - camel_url_set_authmech(url, NULL); - emae_uri_changed(service, url); - camel_url_free(url); - } -} - -static void emae_check_authtype(GtkWidget *w, EMAccountEditorService *service); - -static void -emae_refresh_authtype (EMAccountEditor *emae, EMAccountEditorService *service) -{ - EAccount *account = emae->account; - GtkListStore *store; - GtkTreeIter iter; - GtkComboBox *dropdown; - gint active = 0; - gint i; - struct _service_info *info = &emae_service_info[service->type]; - const gchar *uri = e_account_get_string(account, info->account_uri_key); - GList *l, *ll; - CamelURL *url = NULL; - - dropdown = service->authtype; - gtk_widget_show((GtkWidget *)dropdown); - - store = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN); - - if (uri) - url = camel_url_new(uri, NULL); - - if (service->provider) { - for (i=0, l=service->provider->authtypes; l; l=l->next, i++) { - CamelServiceAuthType *authtype = l->data; - gint avail; - - /* if we have some already shown */ - if (service->authtypes) { - for (ll = service->authtypes;ll;ll = g_list_next(ll)) - if (!strcmp(authtype->authproto, ((CamelServiceAuthType *)ll->data)->authproto)) - break; - avail = ll != NULL; - } else { - avail = TRUE; - } - - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, authtype->name, 1, authtype, 2, !avail, -1); - - if (url && url->authmech && !strcmp(url->authmech, authtype->authproto)) - active = i; - } - } - - gtk_combo_box_set_model(dropdown, (GtkTreeModel *)store); - gtk_combo_box_set_active(dropdown, -1); - - if (service->auth_changed_id == 0) { - GtkCellRenderer *cell = gtk_cell_renderer_text_new(); - - gtk_cell_layout_pack_start((GtkCellLayout *)dropdown, cell, TRUE); - gtk_cell_layout_set_attributes((GtkCellLayout *)dropdown, cell, "text", 0, "strikethrough", 2, NULL); - - service->auth_changed_id = g_signal_connect(dropdown, "changed", G_CALLBACK(emae_authtype_changed), service); - g_signal_connect(service->check_supported, "clicked", G_CALLBACK(emae_check_authtype), service); - } - - gtk_combo_box_set_active(dropdown, active); - - if (url) - camel_url_free(url); -} - -static void emae_check_authtype_done(const gchar *uri, CamelProviderType type, GList *types, gpointer data) -{ - EMAccountEditorService *service = data; - - if (service->check_dialog) { - if (service->authtypes) - g_list_free(service->authtypes); - - service->authtypes = g_list_copy(types); - emae_refresh_authtype(service->emae, service); - gtk_widget_destroy(service->check_dialog); - } - - if (service->emae->editor) - gtk_widget_set_sensitive(service->emae->editor, TRUE); - - service->check_id = -1; - g_object_unref(service->emae); -} - -static void emae_check_authtype_response(GtkWidget *d, gint button, EMAccountEditorService *service) -{ - mail_msg_cancel(service->check_id); - gtk_widget_destroy(service->check_dialog); - service->check_dialog = NULL; - - if (service->emae->editor) - gtk_widget_set_sensitive(service->emae->editor, TRUE); -} - -static void emae_check_authtype(GtkWidget *w, EMAccountEditorService *service) -{ - EMAccountEditor *emae = service->emae; - const gchar *uri; - - /* TODO: do we need to remove the auth mechanism from the uri? */ - uri = e_account_get_string(emae->account, emae_service_info[service->type].account_uri_key); - g_object_ref(emae); - - service->check_dialog = e_error_new(emae->editor ? (GtkWindow *)gtk_widget_get_toplevel(emae->editor) : NULL, - "mail:checking-service", NULL); - g_signal_connect(service->check_dialog, "response", G_CALLBACK(emae_check_authtype_response), service); - gtk_widget_show(service->check_dialog); - if (emae->editor) - gtk_widget_set_sensitive(emae->editor, FALSE); - service->check_id = mail_check_service(uri, service->type, emae_check_authtype_done, service); -} - -static void -emae_setup_service(EMAccountEditor *emae, EMAccountEditorService *service, GladeXML *xml) -{ - struct _service_info *info = &emae_service_info[service->type]; - CamelURL *url = emae_account_url(emae, info->account_uri_key); - const gchar *uri = e_account_get_string(emae->account, info->account_uri_key); - const gchar *tmp; - gint i; - - service->provider = uri?camel_provider_get(uri, NULL):NULL; - service->frame = glade_xml_get_widget(xml, info->frame); - service->container = glade_xml_get_widget(xml, info->container); - service->description = GTK_LABEL (glade_xml_get_widget (xml, info->description)); - service->hostname = GTK_ENTRY (glade_xml_get_widget (xml, info->hostname)); - service->hostlabel = (GtkLabel *)glade_xml_get_widget (xml, info->hostlabel); - service->username = GTK_ENTRY (glade_xml_get_widget (xml, info->username)); - service->userlabel = (GtkLabel *)glade_xml_get_widget (xml, info->userlabel); - if (info->pathentry) { - service->pathlabel = (GtkLabel *)glade_xml_get_widget(xml, info->pathlabel); - service->pathentry = glade_xml_get_widget(xml, info->pathentry); - } - - service->ssl_frame = glade_xml_get_widget (xml, info->security_frame); - gtk_widget_hide (service->ssl_frame); - service->ssl_hbox = glade_xml_get_widget (xml, info->ssl_hbox); - service->use_ssl = (GtkComboBox *)glade_xml_get_widget (xml, info->use_ssl); - service->no_ssl = glade_xml_get_widget (xml, info->ssl_disabled); - - /* configure ui for current settings */ - if (url->host) { - if (url->port) { - gchar *host = g_strdup_printf("%s:%d", url->host, url->port); - - gtk_entry_set_text(service->hostname, host); - g_free(host); - } else - gtk_entry_set_text(service->hostname, url->host); - } - if (url->user && *url->user) { - gtk_entry_set_text(service->username, url->user); - } - if (service->pathentry) { - GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; - - if (service->provider && (service->provider->url_flags & CAMEL_URL_NEED_PATH_DIR) == 0) - action = GTK_FILE_CHOOSER_ACTION_OPEN; - - if (action != gtk_file_chooser_get_action (GTK_FILE_CHOOSER (service->pathentry))) - gtk_file_chooser_set_action (GTK_FILE_CHOOSER (service->pathentry), action); - - if (url->path) - gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (service->pathentry), url->path); - } - - tmp = camel_url_get_param(url, "use_ssl"); - if (tmp == NULL) - tmp = "never"; - - for (i=0;iuse_ssl, i); - break; - } - } - - g_signal_connect (service->hostname, "changed", G_CALLBACK (emae_hostname_changed), service); - g_signal_connect (service->username, "changed", G_CALLBACK (emae_username_changed), service); - if (service->pathentry) - g_signal_connect (GTK_FILE_CHOOSER (service->pathentry), "selection-changed", G_CALLBACK (emae_path_changed), service); - - g_signal_connect(service->use_ssl, "changed", G_CALLBACK(emae_ssl_changed), service); - - service->auth_frame = glade_xml_get_widget(xml, info->auth_frame); - service->remember = emae_account_toggle(emae, info->remember_password, info->save_passwd_key, xml); - service->check_supported = (GtkButton *)glade_xml_get_widget(xml, info->authtype_check); - service->authtype = (GtkComboBox *)glade_xml_get_widget(xml, info->authtype); - /* old authtype will be destroyed when we exit */ - service->auth_changed_id = 0; - service->providers = (GtkComboBox *)glade_xml_get_widget(xml, info->type_dropdown); - emae_refresh_providers(emae, service); - emae_refresh_authtype(emae, service); - - if (info->needs_auth) { - service->needs_auth = (GtkToggleButton *)glade_xml_get_widget (xml, info->needs_auth); - gtk_toggle_button_set_active(service->needs_auth, url->authmech != NULL); - g_signal_connect(service->needs_auth, "toggled", G_CALLBACK(emae_needs_auth), service); - emae_needs_auth(service->needs_auth, service); - } else { - service->needs_auth = NULL; - } - - if (!e_account_writable (emae->account, info->account_uri_key)) - gtk_widget_set_sensitive(service->container, FALSE); - else - gtk_widget_set_sensitive(service->container, TRUE); - - emae_service_provider_changed(service); - - camel_url_free(url); -} - -/* do not re-order these, the order is used by various code to look up emae->priv->identity_entries[] */ -static struct { - const gchar *name; - gint item; -} emae_identity_entries[] = { - { "management_name", E_ACCOUNT_NAME }, - { "identity_full_name", E_ACCOUNT_ID_NAME }, - { "identity_address", E_ACCOUNT_ID_ADDRESS }, - { "identity_reply_to", E_ACCOUNT_ID_REPLY_TO }, - { "identity_organization", E_ACCOUNT_ID_ORGANIZATION }, -}; - -/* its a bit obtuse, but its simple */ -static void -emae_queue_widgets(EMAccountEditor *emae, GladeXML *xml, const gchar *first, ...) -{ - gint i = 0; - va_list ap; - - va_start(ap, first); - while (first) { - emae->priv->widgets_name[i] = first; - emae->priv->widgets[i++] = glade_xml_get_widget(xml, first); - first = va_arg(ap, const gchar *); - } - va_end(ap); - - g_return_if_fail(i < sizeof(emae->priv->widgets)/sizeof(emae->priv->widgets[0])); - - emae->priv->widgets[i] = NULL; - emae->priv->widgets_index = 0; -} - -static GtkWidget * -emae_identity_page(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - EMAccountEditor *emae = data; - EMAccountEditorPrivate *gui = emae->priv; - EAccount *account = emae->account; - gint i; - GtkWidget *w; - GladeXML *xml; - gchar *gladefile; - - /*if (old) - return old;*/ - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - "mail-config.glade", - NULL); - xml = glade_xml_new(gladefile, item->label, NULL); - g_free (gladefile); - - /* Management & Identity fields, in the druid the management frame is relocated to the last page later on */ - for (i=0;iidentity_entries[i] = emae_account_entry(emae, emae_identity_entries[i].name, emae_identity_entries[i].item, xml); - - gui->management_frame = glade_xml_get_widget(xml, "management_frame"); - - gui->default_account = GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "management_default")); - if (!e_get_default_account () - || (account == e_get_default_account ()) - || (GPOINTER_TO_INT(g_object_get_data (G_OBJECT (emae->account), "default_flagged"))) ) - gtk_toggle_button_set_active (gui->default_account, TRUE); - - if (emae->do_signature) { - emae_setup_signatures(emae, xml); - } else { - /* TODO: this could/should probably be neater */ - gtk_widget_hide(glade_xml_get_widget(xml, "sigLabel")); -#if 0 - gtk_widget_hide(glade_xml_get_widget(xml, "sigOption")); -#endif - gtk_widget_hide(glade_xml_get_widget(xml, "sigAddNew")); - } - - w = glade_xml_get_widget(xml, item->label); - if (emae->type == EMAE_PAGES) { - gtk_box_pack_start ((GtkBox *)emae->pages[0], w, TRUE, TRUE, 0); - } else if (((EConfig *)gui->config)->type == E_CONFIG_DRUID) { - GladeXML *druidxml; - GtkWidget *page; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - "mail-config.glade", - NULL); - druidxml = glade_xml_new(gladefile, "identity_page", NULL); - g_free (gladefile); - - page = glade_xml_get_widget(druidxml, "identity_page"); - - gtk_box_pack_start((GtkBox*)((GnomeDruidPageStandard *)page)->vbox, w, TRUE, TRUE, 0); - w = page; - g_object_unref(druidxml); - gnome_druid_append_page((GnomeDruid *)parent, (GnomeDruidPage *)page); - } else { - gtk_notebook_append_page((GtkNotebook *)parent, w, gtk_label_new(_("Identity"))); - } - - emae_queue_widgets(emae, xml, "account_vbox", "identity_required_table", "identity_optional_table", NULL); - - g_object_unref(xml); - - return w; -} - -static GtkWidget * -emae_receive_page(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - EMAccountEditor *emae = data; - EMAccountEditorPrivate *gui = emae->priv; - GtkWidget *w; - GladeXML *xml; - gchar *gladefile; - - /*if (old) - return old;*/ - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - "mail-config.glade", - NULL); - xml = glade_xml_new(gladefile, item->label, NULL); - g_free (gladefile); - - gui->source.type = CAMEL_PROVIDER_STORE; - emae_setup_service(emae, &gui->source, xml); - - w = glade_xml_get_widget(xml, item->label); - if (emae->type == EMAE_PAGES) { - gtk_box_pack_start ((GtkBox *)emae->pages[1], w, TRUE, TRUE, 0); - } else if (((EConfig *)gui->config)->type == E_CONFIG_DRUID) { - GladeXML *druidxml; - GtkWidget *page; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - "mail-config.glade", - NULL); - druidxml = glade_xml_new(gladefile, "source_page", NULL); - g_free (gladefile); - - page = glade_xml_get_widget(druidxml, "source_page"); - - gtk_box_pack_start((GtkBox*)((GnomeDruidPageStandard *)page)->vbox, w, TRUE, TRUE, 0); - w = page; - g_object_unref(druidxml); - gnome_druid_append_page((GnomeDruid *)parent, (GnomeDruidPage *)page); - } else { - gtk_notebook_append_page((GtkNotebook *)parent, w, gtk_label_new(_("Receiving Email"))); - } - - emae_queue_widgets(emae, xml, "source_type_table", "table4", "vbox181", "vbox179", NULL); - - g_object_unref(xml); - - return w; -} - -static void -emae_option_toggle_changed(GtkToggleButton *toggle, EMAccountEditorService *service) -{ - const gchar *name = g_object_get_data((GObject *)toggle, "option-name"); - GSList *depl = g_object_get_data((GObject *)toggle, "dependent-list"); - gint active = gtk_toggle_button_get_active(toggle); - CamelURL *url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); - - for (;depl;depl = g_slist_next(depl)) - gtk_widget_set_sensitive((GtkWidget *)depl->data, active); - - camel_url_set_param(url, name, active?"":NULL); - emae_uri_changed(service, url); - camel_url_free(url); -} - -static GtkWidget * -emae_option_toggle(EMAccountEditorService *service, CamelURL *url, const gchar *text, const gchar *name, gint def) -{ - GtkWidget *w; - - /* FIXME: how do we get the default value ever? */ - w = gtk_check_button_new_with_mnemonic(text); - g_object_set_data((GObject *)w, "option-name", (gpointer)name); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), camel_url_get_param (url, name) != NULL); - g_signal_connect(w, "toggled", G_CALLBACK(emae_option_toggle_changed), service); - gtk_widget_show(w); - - return w; -} - -static void -emae_option_entry_changed(GtkEntry *entry, EMAccountEditorService *service) -{ - const gchar *name = g_object_get_data((GObject *)entry, "option-name"); - const gchar *text = gtk_entry_get_text(entry); - CamelURL *url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); - - camel_url_set_param(url, name, text && text[0]?text:NULL); - emae_uri_changed(service, url); - camel_url_free(url); -} - -static GtkWidget * -emae_option_entry(EMAccountEditorService *service, CamelURL *url, const gchar *name, const gchar *def, GtkWidget *l) -{ - GtkWidget *w; - const gchar *val = camel_url_get_param(url, name); - - if (val == NULL) { - if (def) { - val = def; - camel_url_set_param(url, name, val); - emae_uri_changed(service, url); - } else - val = ""; - } - - w = g_object_new(gtk_entry_get_type(), - "text", val, - NULL); - gtk_label_set_mnemonic_widget ((GtkLabel*)l, w); - g_object_set_data((GObject *)w, "option-name", (gpointer)name); - g_signal_connect(w, "changed", G_CALLBACK(emae_option_entry_changed), service); - gtk_widget_show(w); - - return w; -} - -static void -emae_option_checkspin_changed(GtkSpinButton *spin, EMAccountEditorService *service) -{ - const gchar *name = g_object_get_data((GObject *)spin, "option-name"); - gchar value[16]; - CamelURL *url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); - - sprintf(value, "%d", gtk_spin_button_get_value_as_int(spin)); - camel_url_set_param(url, name, value); - emae_uri_changed(service, url); - camel_url_free(url); -} - -static void -emae_option_checkspin_check_changed(GtkToggleButton *toggle, EMAccountEditorService *service) -{ - const gchar *name = g_object_get_data((GObject *)toggle, "option-name"); - GtkSpinButton *spin = g_object_get_data((GObject *)toggle, "option-target"); - - if (gtk_toggle_button_get_active(toggle)) { - gtk_widget_set_sensitive((GtkWidget *)spin, TRUE); - emae_option_checkspin_changed(spin, service); - } else { - CamelURL *url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); - - camel_url_set_param(url, name, NULL); - gtk_widget_set_sensitive((GtkWidget *)spin, FALSE); - emae_uri_changed(service, url); - camel_url_free(url); - } -} - -/* this is a fugly api */ -static GtkWidget * -emae_option_checkspin(EMAccountEditorService *service, CamelURL *url, const gchar *name, const gchar *fmt, const gchar *info) -{ - GtkWidget *hbox, *check, *spin, *label = NULL; - double min, def, max; - gchar *pre, *post; - const gchar *val; - gchar on; - gint enable; - - pre = g_alloca(strlen(fmt)+1); - strcpy(pre, fmt); - post = strstr(pre, "%s"); - if (post) { - *post = 0; - post+=2; - } - - if (sscanf(info, "%c:%lf:%lf:%lf", &on, &min, &def, &max) != 4) { - min = 0.0; - def = 0.0; - max = 1.0; - } - - if ((enable = (val = camel_url_get_param(url, name)) != NULL) ) - def = strtod(val, NULL); - else - enable = (on == 'y'); - - hbox = gtk_hbox_new(FALSE, 0); - check = g_object_new(gtk_check_button_get_type(), "label", pre, "use_underline", TRUE, "active", enable, NULL); - - spin = gtk_spin_button_new((GtkAdjustment *)gtk_adjustment_new(def, min, max, 1, 1, 0), 1, 0); - if (post) - label = gtk_label_new_with_mnemonic(post); - gtk_box_pack_start((GtkBox *)hbox, check, FALSE, TRUE, 0); - gtk_box_pack_start((GtkBox *)hbox, spin, FALSE, TRUE, 0); - if (label) - gtk_box_pack_start((GtkBox *)hbox, label, FALSE, TRUE, 4); - - g_object_set_data((GObject *)spin, "option-name", (gpointer)name); - g_object_set_data((GObject *)check, "option-name", (gpointer)name); - g_object_set_data((GObject *)check, "option-target", (gpointer)spin); - - g_signal_connect(spin, "value_changed", G_CALLBACK(emae_option_checkspin_changed), service); - g_signal_connect(check, "toggled", G_CALLBACK(emae_option_checkspin_check_changed), service); - - gtk_widget_show_all(hbox); - - return hbox; -} - -static void -emae_option_options_changed (GtkComboBox *options, EMAccountEditorService *service) -{ - const gchar *name = g_object_get_data (G_OBJECT (options), "option-name"); - gchar *value = NULL; - CamelURL *url = emae_account_url (service->emae, emae_service_info[service->type].account_uri_key); - gint id = gtk_combo_box_get_active (options); - - if (id != -1) { - GtkTreeModel *model; - GtkTreeIter iter; - - model = gtk_combo_box_get_model (options); - if (gtk_tree_model_iter_nth_child (model, &iter, NULL, id)) { - gtk_tree_model_get (model, &iter, 0, &value, -1); - } - } - - camel_url_set_param (url, name, value); - emae_uri_changed (service, url); - camel_url_free (url); - g_free (value); -} - -/* 'values' is in format "value0:caption0:value2:caption2:...valueN:captionN" */ -static GtkWidget * -emae_option_options (EMAccountEditorService *service, CamelURL *url, const gchar *name, const gchar *values, GtkWidget *l) -{ - GtkComboBox *w; - GtkListStore *store; - GtkTreeIter iter; - const gchar *p, *value, *caption; - GtkCellRenderer *cell; - gint active = 0; /* the first item entered is always a default item */ - gint i; - const gchar *val = camel_url_get_param (url, name); - - w = GTK_COMBO_BOX (gtk_combo_box_new ()); - - /* value and caption */ - store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); - - p = values; - for (p = values, i = 0; p; i++) { - gchar *vl, *cp; - - value = p; - caption = strchr (p, ':'); - if (caption) { - caption++; - } else { - g_warning (G_STRLOC ": expected ':' not found at '%s'", p); - break; - } - p = strchr (caption, ':'); - - vl = g_strndup (value, caption - value - 1); - if (p) { - p++; - cp = g_strndup (caption, p - caption - 1); - } else - cp = g_strdup (caption); - - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, 0, vl, 1, dgettext (service->provider->translation_domain, cp), -1); - - if (val && g_ascii_strcasecmp (val, vl) == 0) - active = i; - - g_free (vl); - g_free (cp); - } - - gtk_combo_box_set_model (w, (GtkTreeModel *)store); - gtk_combo_box_set_active (w, i > 0 ? active : -1); - - cell = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (w), cell, TRUE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (w), cell, "text", 1, NULL); - - gtk_widget_show (GTK_WIDGET (w)); - - gtk_label_set_mnemonic_widget (GTK_LABEL (l), GTK_WIDGET (w)); - - g_object_set_data (G_OBJECT (w), "option-name", (gpointer)name); - g_signal_connect (w, "changed", G_CALLBACK (emae_option_options_changed), service); - - return GTK_WIDGET (w); -} - -static GtkWidget * -emae_receive_options_item(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - EMAccountEditor *emae = data; - GtkWidget *w, *box, *spin; - gint row; - - if (emae->priv->source.provider == NULL - || emae->priv->source.provider->extra_conf == NULL) - return NULL; - - if (old) - return old; - - /* We have to add the automatic mail check item with the rest of the receive options */ - row = ((GtkTable *)parent)->nrows; - - box = gtk_hbox_new(FALSE, 4); - w = gtk_check_button_new_with_mnemonic (_("Check for _new messages every")); - emae_account_toggle_widget(emae, (GtkToggleButton *)w, E_ACCOUNT_SOURCE_AUTO_CHECK); - gtk_box_pack_start((GtkBox *)box, w, FALSE, FALSE, 0); - - spin = gtk_spin_button_new_with_range(1.0, 1440.0, 1.0); - emae_account_spinint_widget(emae, (GtkSpinButton *)spin, E_ACCOUNT_SOURCE_AUTO_CHECK_TIME); - gtk_box_pack_start((GtkBox *)box, spin, FALSE, TRUE, 0); - - w = gtk_label_new_with_mnemonic (_("minu_tes")); - gtk_label_set_mnemonic_widget (GTK_LABEL (w), spin); - gtk_box_pack_start((GtkBox *)box, w, FALSE, FALSE, 0); - - gtk_widget_show_all(box); - - gtk_table_attach((GtkTable *)parent, box, 0, 2, row, row+1, GTK_EXPAND|GTK_FILL, 0, 0, 0); - - return box; -} - -static GtkWidget * -emae_receive_options_extra_item(EConfig *ec, EConfigItem *eitem, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - EMAccountEditor *emae = data; - struct _receive_options_item *item = (struct _receive_options_item *)eitem; - GtkWidget *w, *l, *h; - CamelProviderConfEntry *entries; - GtkWidget *depw; - GSList *depl = NULL, *n; - EMAccountEditorService *service = &emae->priv->source; - gint row, i; - GHashTable *extra; - CamelURL *url; - - if (emae->priv->source.provider == NULL - || emae->priv->source.provider->extra_conf == NULL) - return NULL; - - entries = emae->priv->source.provider->extra_conf; - for (i=0;entries && entries[i].type != CAMEL_PROVIDER_CONF_END;i++) - if (entries[i].type == CAMEL_PROVIDER_CONF_SECTION_START - && entries[i].name - && strcmp(entries[i].name, eitem->user_data) == 0) - goto section; - - return NULL; -section: - d(printf("Building extra section '%s'\n", eitem->path)); - - url = emae_account_url(emae, emae_service_info[service->type].account_uri_key); - item->extra_table = g_hash_table_new(g_str_hash, g_str_equal); - extra = g_hash_table_new(g_str_hash, g_str_equal); - row = ((GtkTable *)parent)->nrows; - - for (;entries[i].type != CAMEL_PROVIDER_CONF_END && entries[i].type != CAMEL_PROVIDER_CONF_SECTION_END;i++) { - if (entries[i].depname) { - depw = g_hash_table_lookup(extra, entries[i].depname); - if (depw) - depl = g_object_steal_data((GObject *)depw, "dependent-list"); - } else - depw = NULL; - - switch (entries[i].type) { - case CAMEL_PROVIDER_CONF_SECTION_START: - case CAMEL_PROVIDER_CONF_SECTION_END: - break; - case CAMEL_PROVIDER_CONF_LABEL: - /* FIXME: This is a hack for exchange connector, labels should be removed from confentry */ - if (!strcmp(entries[i].name, "hostname")) - l = (GtkWidget *)emae->priv->source.hostlabel; - else if (!strcmp(entries[i].name, "username")) - l = (GtkWidget *)emae->priv->source.userlabel; - else - l = NULL; - - if (l) { - gtk_label_set_text_with_mnemonic((GtkLabel *)l, entries[i].text); - if (depw) - depl = g_slist_prepend(depl, l); - } - break; - case CAMEL_PROVIDER_CONF_CHECKBOX: - w = emae_option_toggle(service, url, entries[i].text, entries[i].name, atoi(entries[i].value)); - gtk_table_attach((GtkTable *)parent, w, 0, 2, row, row+1, GTK_EXPAND|GTK_FILL, 0, 0, 0); - g_hash_table_insert(extra, (gpointer)entries[i].name, w); - if (depw) - depl = g_slist_prepend(depl, w); - row++; - /* HACK: keep_on_server is stored in the e-account, but is displayed as a properly on the uri, - make sure they track/match here */ - if (!strcmp(entries[i].name, "keep_on_server")) - emae_account_toggle_widget(emae, (GtkToggleButton *)w, E_ACCOUNT_SOURCE_KEEP_ON_SERVER); - break; - case CAMEL_PROVIDER_CONF_ENTRY: - l = g_object_new(gtk_label_get_type(), "label", entries[i].text, "xalign", 0.0, "use_underline", TRUE, NULL); - gtk_widget_show(l); - w = emae_option_entry(service, url, entries[i].name, entries[i].value, l); - gtk_table_attach((GtkTable *)parent, l, 0, 1, row, row+1, GTK_FILL, 0, 0, 0); - gtk_table_attach((GtkTable *)parent, w, 1, 2, row, row+1, GTK_EXPAND|GTK_FILL, 0, 0, 0); - if (depw) { - depl = g_slist_prepend(depl, w); - depl = g_slist_prepend(depl, l); - } - row++; - /* FIXME: this is another hack for exchange/groupwise connector */ - g_hash_table_insert(item->extra_table, (gpointer)entries[i].name, w); - break; - case CAMEL_PROVIDER_CONF_CHECKSPIN: - w = emae_option_checkspin(service, url, entries[i].name, entries[i].text, entries[i].value); - gtk_table_attach((GtkTable *)parent, w, 0, 2, row, row+1, GTK_EXPAND|GTK_FILL, 0, 0, 0); - if (depw) - depl = g_slist_prepend(depl, w); - row++; - break; - case CAMEL_PROVIDER_CONF_OPTIONS: - h = gtk_hbox_new (FALSE, 4); - gtk_widget_show (h); - l = g_object_new (gtk_label_get_type (), "label", entries[i].text, "xalign", 0.0, "use_underline", TRUE, NULL); - gtk_widget_show (l); - w = emae_option_options (service, url, entries[i].name, entries[i].value, l); - gtk_box_pack_start (GTK_BOX (h), l, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (h), w, FALSE, FALSE, 0); - gtk_table_attach ((GtkTable *)parent, h, 0, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); - if (depw) { - depl = g_slist_prepend (depl, h); - } - row++; - break; - default: - break; - } - - if (depw && depl) { - gint act = gtk_toggle_button_get_active((GtkToggleButton *)depw); - - g_object_set_data_full((GObject *)depw, "dependent-list", depl, (GDestroyNotify)g_slist_free); - for (n=depl;n;n=g_slist_next(n)) - gtk_widget_set_sensitive((GtkWidget *)n->data, act); - } - } - - camel_url_free(url); - - /* Since EConfig destroys the factory widget when it changes, we - * need to destroy our own ones as well, and add a dummy item - * so it knows this section isn't empty */ - - w = gtk_label_new(""); - gtk_widget_hide(w); - gtk_table_attach((GtkTable *)parent, w, 0, 2, row, row+1, 0, 0, 0, 0); - - return w; -} - -static GtkWidget * -emae_send_page(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - EMAccountEditor *emae = data; - EMAccountEditorPrivate *gui = emae->priv; - GtkWidget *w; - GladeXML *xml; - gchar *gladefile; - - /* no transport options page at all for these types of providers */ - if (gui->source.provider && CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT(gui->source.provider)) { - memset(&gui->transport.frame, 0, ((gchar *)&gui->transport.check_dialog)-((gchar *)&gui->transport.frame)); - return NULL; - } - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - "mail-config.glade", - NULL); - xml = glade_xml_new(gladefile, item->label, NULL); - g_free (gladefile); - - /* Transport */ - gui->transport.type = CAMEL_PROVIDER_TRANSPORT; - emae_setup_service(emae, &gui->transport, xml); - - w = glade_xml_get_widget(xml, item->label); - if (emae->type == EMAE_PAGES) { - gtk_box_pack_start ((GtkBox *)emae->pages[2], w, TRUE, TRUE, 0); - } else if (((EConfig *)gui->config)->type == E_CONFIG_DRUID) { - GladeXML *druidxml; - GtkWidget *page; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - "mail-config.glade", - NULL); - druidxml = glade_xml_new(gladefile, "transport_page", NULL); - g_free (gladefile); - - page = glade_xml_get_widget(druidxml, "transport_page"); - - gtk_box_pack_start((GtkBox*)((GnomeDruidPageStandard *)page)->vbox, w, TRUE, TRUE, 0); - w = page; - g_object_unref(druidxml); - gnome_druid_append_page((GnomeDruid *)parent, (GnomeDruidPage *)page); - } else { - gtk_notebook_append_page((GtkNotebook *)parent, w, gtk_label_new(_("Sending Email"))); - } - - emae_queue_widgets(emae, xml, "transport_type_table", "vbox12", "vbox183", "vbox61", NULL); - - g_object_unref(xml); - - return w; -} - -static GtkWidget * -emae_defaults_page(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - EMAccountEditor *emae = data; - EMAccountEditorPrivate *gui = emae->priv; - GtkWidget *w; - GladeXML *xml; - gchar *gladefile; - - /*if (old) - return old;*/ - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - "mail-config.glade", - NULL); - xml = glade_xml_new(gladefile, item->label, NULL); - g_free (gladefile); - - /* Special folders */ - gui->drafts_folder_button = (GtkButton *)emae_account_folder(emae, "drafts_button", E_ACCOUNT_DRAFTS_FOLDER_URI, E_MAIL_FOLDER_DRAFTS, xml); - gui->sent_folder_button = (GtkButton *)emae_account_folder(emae, "sent_button", E_ACCOUNT_SENT_FOLDER_URI, E_MAIL_FOLDER_SENT, xml); - - /* Special Folders "Reset Defaults" button */ - gui->restore_folders_button = (GtkButton *)glade_xml_get_widget (xml, "default_folders_button"); - g_signal_connect (gui->restore_folders_button, "clicked", G_CALLBACK (default_folders_clicked), emae); - - /* Always Cc/Bcc */ - emae_account_toggle(emae, "always_cc", E_ACCOUNT_CC_ALWAYS, xml); - emae_account_entry(emae, "cc_addrs", E_ACCOUNT_CC_ADDRS, xml); - emae_account_toggle(emae, "always_bcc", E_ACCOUNT_BCC_ALWAYS, xml); - emae_account_entry(emae, "bcc_addrs", E_ACCOUNT_BCC_ADDRS, xml); - - gtk_widget_set_sensitive((GtkWidget *)gui->drafts_folder_button, e_account_writable(emae->account, E_ACCOUNT_DRAFTS_FOLDER_URI)); - - gtk_widget_set_sensitive( (GtkWidget *)gui->sent_folder_button, - e_account_writable(emae->account, E_ACCOUNT_SENT_FOLDER_URI) - && - (emae->priv->source.provider ? !(emae->priv->source.provider->flags & CAMEL_PROVIDER_DISABLE_SENT_FOLDER): TRUE) - ); - - gtk_widget_set_sensitive((GtkWidget *)gui->restore_folders_button, - (e_account_writable(emae->account, E_ACCOUNT_SENT_FOLDER_URI) - && ((emae->priv->source.provider && !( emae->priv->source.provider->flags & CAMEL_PROVIDER_DISABLE_SENT_FOLDER)) - || e_account_writable(emae->account, E_ACCOUNT_DRAFTS_FOLDER_URI)))); - - /* Receipt policy */ - emae_setup_receipt_policy (emae, xml); - - w = glade_xml_get_widget(xml, item->label); - gtk_notebook_append_page((GtkNotebook *)parent, w, gtk_label_new(_("Defaults"))); - - emae_queue_widgets(emae, xml, "vbox184", "table8", NULL); - - g_object_unref(xml); - - return w; -} - -static GtkWidget * -emae_security_page(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - EMAccountEditor *emae = data; -#if defined (HAVE_NSS) - EMAccountEditorPrivate *gui = emae->priv; -#endif - GtkWidget *w; - GladeXML *xml; - gchar *gladefile; - - /*if (old) - return old;*/ - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - "mail-config.glade", - NULL); - xml = glade_xml_new(gladefile, item->label, NULL); - g_free (gladefile); - - /* Security */ - emae_account_entry(emae, "pgp_key", E_ACCOUNT_PGP_KEY, xml); - emae_account_toggle(emae, "pgp_encrypt_to_self", E_ACCOUNT_PGP_ENCRYPT_TO_SELF, xml); - emae_account_toggle(emae, "pgp_always_sign", E_ACCOUNT_PGP_ALWAYS_SIGN, xml); - emae_account_toggle(emae, "pgp_no_imip_sign", E_ACCOUNT_PGP_NO_IMIP_SIGN, xml); - emae_account_toggle(emae, "pgp_always_trust", E_ACCOUNT_PGP_ALWAYS_TRUST, xml); - -#if defined (HAVE_NSS) - /* TODO: this should handle its entry separately? */ - gui->smime_sign_key = emae_account_entry(emae, "smime_sign_key", E_ACCOUNT_SMIME_SIGN_KEY, xml); - gui->smime_sign_key_select = (GtkButton *)glade_xml_get_widget (xml, "smime_sign_key_select"); - gui->smime_sign_key_clear = (GtkButton *)glade_xml_get_widget (xml, "smime_sign_key_clear"); - g_signal_connect(gui->smime_sign_key_select, "clicked", G_CALLBACK(smime_sign_key_select), emae); - g_signal_connect(gui->smime_sign_key_clear, "clicked", G_CALLBACK(smime_sign_key_clear), emae); - - gui->smime_sign_default = emae_account_toggle(emae, "smime_sign_default", E_ACCOUNT_SMIME_SIGN_DEFAULT, xml); - - gui->smime_encrypt_key = emae_account_entry(emae, "smime_encrypt_key", E_ACCOUNT_SMIME_ENCRYPT_KEY, xml); - gui->smime_encrypt_key_select = (GtkButton *)glade_xml_get_widget (xml, "smime_encrypt_key_select"); - gui->smime_encrypt_key_clear = (GtkButton *)glade_xml_get_widget (xml, "smime_encrypt_key_clear"); - g_signal_connect(gui->smime_encrypt_key_select, "clicked", G_CALLBACK(smime_encrypt_key_select), emae); - g_signal_connect(gui->smime_encrypt_key_clear, "clicked", G_CALLBACK(smime_encrypt_key_clear), emae); - - gui->smime_encrypt_default = emae_account_toggle(emae, "smime_encrypt_default", E_ACCOUNT_SMIME_ENCRYPT_DEFAULT, xml); - gui->smime_encrypt_to_self = emae_account_toggle(emae, "smime_encrypt_to_self", E_ACCOUNT_SMIME_ENCRYPT_TO_SELF, xml); - smime_changed(emae); -#else - { - /* Since we don't have NSS, hide the S/MIME config options */ - GtkWidget *frame; - - frame = glade_xml_get_widget(xml, "smime_vbox"); - gtk_widget_destroy(frame); - } -#endif /* HAVE_NSS */ - - w = glade_xml_get_widget(xml, item->label); - gtk_notebook_append_page((GtkNotebook *)parent, w, gtk_label_new(_("Security"))); - - g_object_unref(xml); - - return w; -} - -static GtkWidget * -emae_widget_glade(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - EMAccountEditor *emae = data; - gint i; - - for (i=0;emae->priv->widgets[i];i++) - if (!strcmp(emae->priv->widgets_name[i], item->label)) - return emae->priv->widgets[i]; - - g_warning("Mail account widget '%s' not found", item->label); - - return NULL; -} - -/* plugin meta-data for "org.gnome.evolution.mail.config.accountEditor" */ -static EMConfigItem emae_editor_items[] = { - { E_CONFIG_BOOK, (gchar *) "" }, - { E_CONFIG_PAGE, (gchar *) "00.identity", (gchar *) "vboxIdentityBorder", emae_identity_page }, - { E_CONFIG_SECTION, (gchar *) "00.identity/00.name", (gchar *) "account_vbox", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "00.identity/10.required", (gchar *) "identity_required_table", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "00.identity/20.info", (gchar *) "identity_optional_table", emae_widget_glade }, - - { E_CONFIG_PAGE, (gchar *) "10.receive", (gchar *) "vboxSourceBorder", emae_receive_page }, - { E_CONFIG_SECTION_TABLE, (gchar *) "10.receive/00.type", (gchar *) "source_type_table", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "10.receive/10.config", (gchar *) "table4", emae_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "10.receive/20.security", (gchar *) "vbox181", emae_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "10.receive/30.auth", (gchar *) "vbox179", emae_widget_glade }, - - /* Most sections for this is auto-generated from the camel config */ - { E_CONFIG_PAGE, (gchar *) "20.receive_options", (gchar *) N_("Receiving Options"), }, - { E_CONFIG_SECTION_TABLE, (gchar *) "20.receive_options/10.mailcheck", (gchar *) N_("Checking for New Messages"), }, - { E_CONFIG_ITEM_TABLE, (gchar *) "20.receive_options/10.mailcheck/00.autocheck", NULL, emae_receive_options_item, }, - - { E_CONFIG_PAGE, (gchar *) "30.send", (gchar *) "vboxTransportBorder", emae_send_page }, - { E_CONFIG_SECTION_TABLE, (gchar *) "30.send/00.type", (gchar *) "transport_type_table", emae_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "30.send/10.config", (gchar *) "vbox12", emae_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "30.send/20.security", (gchar *) "vbox183", emae_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "30.send/30.auth", (gchar *) "vbox61", emae_widget_glade }, - - { E_CONFIG_PAGE, (gchar *) "40.defaults", (gchar *) "vboxFoldersBorder", emae_defaults_page }, - { E_CONFIG_SECTION, (gchar *) "40.defaults/00.folders", (gchar *) "vbox184", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "40.defaults/10.composing", (gchar *) "table8", emae_widget_glade }, - - { E_CONFIG_PAGE, (gchar *) "50.security", (gchar *) "vboxSecurityBorder", emae_security_page }, - /* 1x1 table(!) not vbox: { E_CONFIG_SECTION, "50.security/00.gpg", "table19", emae_widget_glade }, */ - /* table not vbox: { E_CONFIG_SECTION, "50.security/10.smime", "smime_table", emae_widget_glade }, */ - { 0 }, -}; -static gboolean emae_editor_items_translated = FALSE; - -static GtkWidget * -emae_management_page(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - EMAccountEditor *emae = data; - EMAccountEditorPrivate *gui = emae->priv; - GtkWidget *w; - - w = gui->management_frame; - if (((EConfig *)gui->config)->type == E_CONFIG_DRUID) { - GladeXML *druidxml; - GtkWidget *page; - gchar *gladefile; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - "mail-config.glade", - NULL); - druidxml = glade_xml_new(gladefile, "management_page", NULL); - g_free (gladefile); - - page = glade_xml_get_widget(druidxml, "management_page"); - - gtk_widget_reparent(w, ((GnomeDruidPageStandard *)page)->vbox); - w = page; - g_object_unref(druidxml); - gnome_druid_append_page((GnomeDruid *)parent, (GnomeDruidPage *)page); - } - - return w; -} - -static GtkWidget * -emae_widget_druid_glade(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - GladeXML *druidxml; - GtkWidget *w; - gchar *gladefile; - EMAccountEditor *emae = (EMAccountEditor *)data; - - if (emae->type == EMAE_PAGES) - return NULL; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - "mail-config.glade", - NULL); - druidxml = glade_xml_new(gladefile, item->label, NULL); - g_free (gladefile); - - w = glade_xml_get_widget(druidxml, item->label); - /* i think the glade file has issues, we need to show all on at least the end page */ - gtk_widget_show_all(w); - g_object_unref(druidxml); - - gnome_druid_append_page((GnomeDruid *)parent, (GnomeDruidPage *)w); - - return w; -} - -/* plugin meta-data for "org.gnome.evolution.mail.config.accountDruid" */ -static EMConfigItem emae_druid_items[] = { - { E_CONFIG_DRUID, (gchar *) "" }, - { E_CONFIG_PAGE_START, (gchar *) "0.start", (gchar *) "start_page", emae_widget_druid_glade }, - - { E_CONFIG_PAGE, (gchar *) "00.identity", (gchar *) "vboxIdentityBorder", emae_identity_page }, - { E_CONFIG_SECTION, (gchar *) "00.identity/00.name", (gchar *) "account_vbox", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "00.identity/10.required", (gchar *) "identity_required_table", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "00.identity/20.info", (gchar *) "identity_optional_table", emae_widget_glade }, - - { E_CONFIG_PAGE, (gchar *) "10.receive", (gchar *) "vboxSourceBorder", emae_receive_page }, - { E_CONFIG_SECTION_TABLE, (gchar *) "10.receive/00.type", (gchar *) "source_type_table", emae_widget_glade }, - { E_CONFIG_SECTION_TABLE, (gchar *) "10.receive/10.config", (gchar *) "table4", emae_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "10.receive/20.security", (gchar *) "vbox181", emae_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "10.receive/30.auth", (gchar *) "vbox179", emae_widget_glade }, - - /* Most sections for this is auto-generated fromt the camel config */ - { E_CONFIG_PAGE, (gchar *) "20.receive_options", (gchar *) N_("Receiving Options"), }, - { E_CONFIG_SECTION_TABLE, (gchar *) "20.receive_options/10.mailcheck", (gchar *) N_("Checking for New Messages"), }, - { E_CONFIG_ITEM_TABLE, (gchar *) "20.receive_options/10.mailcheck/00.autocheck", NULL, emae_receive_options_item, }, - - { E_CONFIG_PAGE, (gchar *) "30.send", (gchar *) "vboxTransportBorder", emae_send_page }, - { E_CONFIG_SECTION_TABLE, (gchar *) "30.send/00.type", (gchar *) "transport_type_table", emae_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "30.send/10.config", (gchar *) "vbox12", emae_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "30.send/20.security", (gchar *) "vbox183", emae_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "30.send/30.auth", (gchar *) "vbox61", emae_widget_glade }, - - { E_CONFIG_PAGE, (gchar *) "40.management", (gchar *) "management_frame", emae_management_page }, - - { E_CONFIG_PAGE_FINISH, (gchar *) "999.end", (gchar *) "finish_page", emae_widget_druid_glade }, - { 0 }, -}; -static gboolean emae_druid_items_translated = FALSE; - -static void -emae_free(EConfig *ec, GSList *items, gpointer data) -{ - g_slist_free(items); -} - -static void -emae_free_auto(EConfig *ec, GSList *items, gpointer data) -{ - GSList *l, *n; - - for (l=items;l;) { - struct _receive_options_item *item = l->data; - - n = g_slist_next(l); - g_free(item->item.path); - if (item->extra_table) - g_hash_table_destroy(item->extra_table); - g_free(item); - g_slist_free_1(l); - l = n; - } -} - -static gboolean -emae_service_complete(EMAccountEditor *emae, EMAccountEditorService *service) -{ - CamelURL *url; - gint ok = TRUE; - const gchar *uri; - - if (service->provider == NULL) - return TRUE; - - uri = e_account_get_string(emae->account, emae_service_info[service->type].account_uri_key); - if (uri == NULL || (url = camel_url_new(uri, NULL)) == NULL) - return FALSE; - - if (CAMEL_PROVIDER_NEEDS(service->provider, CAMEL_URL_PART_HOST)) { - if (url->host == NULL || url->host[0] == 0) - ok = FALSE; - } - /* We only need the user if the service needs auth as well, i think */ - if (ok - && (service->needs_auth == NULL - || CAMEL_PROVIDER_NEEDS(service->provider, CAMEL_URL_PART_AUTH) - || gtk_toggle_button_get_active(service->needs_auth)) - && CAMEL_PROVIDER_NEEDS(service->provider, CAMEL_URL_PART_USER) - && (url->user == NULL || url->user[0] == 0)) - ok = FALSE; - - if (ok - && CAMEL_PROVIDER_NEEDS(service->provider, CAMEL_URL_PART_PATH) - && (url->path == NULL || url->path[0] == 0)) - ok = FALSE; - - camel_url_free(url); - - return ok; -} - -enum { - GMAIL = 0, - YAHOO, - AOL -}; -struct _server_prefill { - const gchar *key; - const gchar *recv; - const gchar *send; - const gchar *proto; - const gchar *ssl; -} mail_servers [] = { - {"gmail", "imap.gmail.com", "smtp.gmail.com", "imap", "always"}, - {"yahoo", "pop3.yahoo.com", "smtp.yahoo.com", "pop", "never"}, - {"aol", "imap.aol.com", "smtp.aol.com", "pop", "never"}, - {"msn", "pop3.email.msn.com", "smtp.email.msn.com", "pop", "never"} -}; - -static gint -check_servers (gchar *server) -{ - gint len = G_N_ELEMENTS(mail_servers), i; - - for (i=0; ipriv->config)->type == E_CONFIG_DRUID) { - if (!strcmp(pageid, "00.identity")) { - if (!emae->priv->identity_set) { - gchar *uname; - - emae->priv->identity_set = 1; -#ifndef G_OS_WIN32 - uname = g_locale_to_utf8(g_get_real_name(), -1, NULL, NULL, NULL); -#else - uname = g_strdup(g_get_real_name()); -#endif - if (uname) { - gtk_entry_set_text(emae->priv->identity_entries[1], uname); - g_free(uname); - } - } - } else if (!strcmp(pageid, "10.receive")) { - if (!emae->priv->receive_set) { - gchar *user, *at; - gint index; - gchar *uri = g_strdup(e_account_get_string(emae->account, E_ACCOUNT_SOURCE_URL)); - CamelURL *url; - - emae->priv->receive_set = 1; - tmp = (gchar *)e_account_get_string(emae->account, E_ACCOUNT_ID_ADDRESS); - at = strchr(tmp, '@'); - user = g_alloca(at-tmp+1); - memcpy(user, tmp, at-tmp); - user[at-tmp] = 0; - at++; - - index = check_servers(at); - gtk_entry_set_text(emae->priv->source.username, user); - gtk_entry_set_text(emae->priv->transport.username, user); - if (uri && (url = camel_url_new(uri, NULL)) != NULL) { - refresh = TRUE; - camel_url_set_protocol(url, mail_servers[index].proto); - camel_url_set_param(url, "use_ssl", mail_servers[index].ssl); - camel_url_set_host (url, mail_servers[index].recv); - camel_url_set_user (url, user); - gtk_entry_set_text(emae->priv->source.hostname, mail_servers[index].recv); - gtk_entry_set_text(emae->priv->transport.hostname, mail_servers[index].send); - uri = camel_url_to_string(url, 0); - e_account_set_string(emae->account, E_ACCOUNT_SOURCE_URL, uri); - - g_free(uri); - camel_url_free(url); - } - - } - } else if (!strcmp(pageid, "30.send")) { - CamelURL *url; - gchar *at, *user; - gint index; - gchar *uri = (gchar *)e_account_get_string(emae->account, E_ACCOUNT_TRANSPORT_URL); - - tmp = e_account_get_string(emae->account, E_ACCOUNT_ID_ADDRESS); - at = strchr(tmp, '@'); - user = g_alloca(at-tmp+1); - memcpy(user, tmp, at-tmp); - user[at-tmp] = 0; - at++; - - index = check_servers(at); - if (uri && (url = camel_url_new(uri, NULL)) != NULL) { - refresh = TRUE; - camel_url_set_protocol (url, "smtp"); - camel_url_set_param(url, "use_ssl", mail_servers[index].ssl); - camel_url_set_host (url, mail_servers[index].send); - camel_url_set_user (url, user); - uri = camel_url_to_string(url, 0); - e_account_set_string(emae->account, E_ACCOUNT_TRANSPORT_URL, uri); - g_free(uri); - camel_url_free(url); - } else { - g_warning("buz2\n"); - } - - } else if (!strcmp(pageid, "20.receive_options")) { - if (emae->priv->source.provider - && emae->priv->extra_provider != emae->priv->source.provider) { - emae->priv->extra_provider = emae->priv->source.provider; - emae_auto_detect(emae); - } - } else if (!strcmp(pageid, "40.management")) { - if (!emae->priv->management_set) { - gchar *template; - guint i = 0, len; - - emae->priv->management_set = 1; - tmp = e_account_get_string(emae->account, E_ACCOUNT_ID_ADDRESS); - len = strlen(tmp); - template = alloca(len + 14); - strcpy(template, tmp); - while (e_get_account_by_name (template)) - sprintf(template + len, " (%d)", i++); - - gtk_entry_set_text(emae->priv->identity_entries[0], template); - } - } - } - - /* - Setting a flag on the Account if it is marked as default. It is done in this way instead of - using a temporary variable so as to keep track of which account is marked as default in case of - editing multiple accounts at a time - */ - if (gtk_toggle_button_get_active(emae->priv->default_account)) - g_object_set_data (G_OBJECT (emae->account), "default_flagged", GINT_TO_POINTER(1)); - - if (pageid == NULL || !strcmp(pageid, "00.identity")) { - /* TODO: check the account name is set, and unique in the account list */ - ok = (tmp = e_account_get_string(emae->account, E_ACCOUNT_ID_NAME)) - && tmp[0] - && (tmp = e_account_get_string(emae->account, E_ACCOUNT_ID_ADDRESS)) - && is_email(tmp) - && ((tmp = e_account_get_string(emae->account, E_ACCOUNT_ID_REPLY_TO)) == NULL - || tmp[0] == 0 - || is_email(tmp)); - if (!ok) { - d(printf("identity incomplete\n")); - } - } - - if (ok && (pageid == NULL || !strcmp(pageid, "10.receive"))) { - if (emae->type == EMAE_PAGES && refresh) { - emae_refresh_providers(emae, &emae->priv->source); - } - ok = emae_service_complete(emae, &emae->priv->source); - if (!ok) { - d(printf("receive page incomplete\n")); - } - } - - if (ok && (pageid == NULL || !strcmp(pageid, "30.send"))) { - if (emae->type == EMAE_PAGES && refresh) { - emae_refresh_providers(emae, &emae->priv->transport); - } - ok = emae_service_complete(emae, &emae->priv->transport); - if (!ok) { - d(printf("send page incomplete\n")); - } - } - - if (ok && (pageid == NULL || !strcmp(pageid, "40.management"))) { - ok = (tmp = e_account_get_string(emae->account, E_ACCOUNT_NAME)) - && tmp[0] - && ((ea = e_get_account_by_name (tmp)) == NULL - || ea == emae->original); - if (!ok) { - d(printf("management page incomplete\n")); - } - } - - return ok; -} - -void -em_account_editor_check (EMAccountEditor *emae, const gchar *page) -{ - emae_check_complete((EConfig *)emae->config, page, emae); -} - -/* HACK: FIXME: the component should listen to the account object directly */ -static void -add_new_store (gchar *uri, CamelStore *store, gpointer user_data) -{ -#if 0 /* KILL-BONOBO: Try to actually fix this? */ - MailComponent *component = mail_component_peek (); - EAccount *account = user_data; - - if (store == NULL) - return; - - mail_component_add_store (component, store, account->name); -#endif -} - -static void -emae_commit(EConfig *ec, GSList *items, gpointer data) -{ - EMAccountEditor *emae = data; - EAccountList *accounts = e_get_account_list (); - EAccount *account; - - /* the mail-config*acconts* api needs a lot of work */ - - if (emae->original) { - d(printf("Committing account '%s'\n", e_account_get_string(emae->account, E_ACCOUNT_NAME))); - e_account_import(emae->original, emae->account); - account = emae->original; - e_account_list_change(accounts, account); - } else { - d(printf("Adding new account '%s'\n", e_account_get_string(emae->account, E_ACCOUNT_NAME))); - e_account_list_add(accounts, emae->account); - account = emae->account; - - /* HACK: this will add the account to the folder tree. - We should just be listening to the account list directly for changed events */ - if (account->enabled - && emae->priv->source.provider - && (emae->priv->source.provider->flags & CAMEL_PROVIDER_IS_STORAGE)) - mail_get_store(e_account_get_string(emae->account, E_ACCOUNT_SOURCE_URL), NULL, add_new_store, account); - } - - if (gtk_toggle_button_get_active(emae->priv->default_account)) - e_account_list_set_default(accounts, account); - - e_account_list_save(accounts); -} - -void -em_account_editor_commit (EMAccountEditor *emae) -{ - emae_commit ((EConfig *)emae->config, NULL, emae); -} - -static void -emae_editor_destroyed(GtkWidget *dialog, EMAccountEditor *emae) -{ - emae->editor = NULL; - g_object_unref(emae); -} - -static void -em_account_editor_construct(EMAccountEditor *emae, EAccount *account, em_account_editor_t type, const gchar *id) -{ - EMAccountEditorPrivate *gui = emae->priv; - gint i, index; - GSList *l; - GList *prov; - EMConfig *ec; - EMConfigTargetAccount *target; - GHashTable *have; - EConfigItem *items; - - emae->type = type; - emae->original = account; - if (emae->original) { - gchar *xml; - - g_object_ref(emae->original); - xml = e_account_to_xml(emae->original); - emae->account = e_account_new_from_xml(xml); - g_free(xml); - - emae->do_signature = TRUE; - } else { - /* TODO: have a get_default_account thing?? */ - emae->account = e_account_new(); - emae->account->enabled = TRUE; - - e_account_set_string ( - emae->account, E_ACCOUNT_DRAFTS_FOLDER_URI, - e_mail_local_get_folder_uri (E_MAIL_FOLDER_DRAFTS)); - - e_account_set_string ( - emae->account, E_ACCOUNT_SENT_FOLDER_URI, - e_mail_local_get_folder_uri (E_MAIL_FOLDER_SENT)); - } - - /* sort the providers, remote first */ - gui->providers = g_list_sort(camel_provider_list(TRUE), (GCompareFunc)provider_compare); - - if (type == EMAE_NOTEBOOK) { - ec = em_config_new(E_CONFIG_BOOK, id); - items = emae_editor_items; - if (!emae_editor_items_translated) { - for (i=0;items[i].path;i++) { - if (items[i].label) - items[i].label = gettext(items[i].label); - } - emae_editor_items_translated = TRUE; - } - } else { - ec = em_config_new(E_CONFIG_DRUID, id); - items = emae_druid_items; - if (!emae_druid_items_translated) { - for (i=0;items[i].path;i++) { - if (items[i].label) - items[i].label = _(items[i].label); - } - emae_druid_items_translated = TRUE; - } - } - - emae->config = gui->config = ec; - l = NULL; - for (i=0;items[i].path;i++) - l = g_slist_prepend(l, &items[i]); - e_config_add_items((EConfig *)ec, l, emae_commit, NULL, emae_free, emae); - - /* This is kinda yuck, we're dynamically mapping from the 'old style' extensibility api to the new one */ - l = NULL; - have = g_hash_table_new(g_str_hash, g_str_equal); - index = 20; - for (prov=gui->providers;prov;prov=g_list_next(prov)) { - CamelProviderConfEntry *entries = ((CamelProvider *)prov->data)->extra_conf; - - for (i=0;entries && entries[i].type != CAMEL_PROVIDER_CONF_END;i++) { - struct _receive_options_item *item; - const gchar *name = entries[i].name; - gint myindex = index; - - if (entries[i].type != CAMEL_PROVIDER_CONF_SECTION_START - || name == NULL - || g_hash_table_lookup(have, name)) - continue; - - /* override mailcheck since we also insert our own mailcheck item at this index */ - if (name && !strcmp(name, "mailcheck")) - myindex = 10; - - item = g_malloc0(sizeof(*item)); - item->item.type = E_CONFIG_SECTION_TABLE; - item->item.path = g_strdup_printf("20.receive_options/%02d.%s", myindex, name?name:"unnamed"); - item->item.label = g_strdup (entries[i].text); - - l = g_slist_prepend(l, item); - - item = g_malloc0(sizeof(*item)); - item->item.type = E_CONFIG_ITEM_TABLE; - item->item.path = g_strdup_printf("20.receive_options/%02d.%s/80.camelitem", myindex, name?name:"unnamed"); - item->item.factory = emae_receive_options_extra_item; - item->item.user_data = g_strdup (entries[i].name); - - l = g_slist_prepend(l, item); - - index += 10; - g_hash_table_insert(have, (gpointer)entries[i].name, have); - } - } - g_hash_table_destroy(have); - e_config_add_items((EConfig *)ec, l, NULL, NULL, emae_free_auto, emae); - gui->extra_items = l; - - e_config_add_page_check((EConfig *)ec, NULL, emae_check_complete, emae); - - target = em_config_target_new_account(ec, emae->account); - e_config_set_target((EConfig *)ec, (EConfigTarget *)target); - - if (type != EMAE_PAGES) { - emae->editor = e_config_create_window((EConfig *)ec, NULL, type==EMAE_NOTEBOOK?_("Account Editor"):_("Evolution Account Assistant")); - g_signal_connect(emae->editor, "destroy", G_CALLBACK(emae_editor_destroyed), emae); - } else { - e_config_create_widget((EConfig *)ec); - } -} diff --git a/mail/em-account-editor.h b/mail/em-account-editor.h deleted file mode 100644 index d8d96f58f0..0000000000 --- a/mail/em-account-editor.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Jeffrey Stedfast - * Dan Winship - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef EM_ACCOUNT_EDITOR_H -#define EM_ACCOUNT_EDITOR_H - -#include - -#include - -G_BEGIN_DECLS - -typedef struct _EMAccountEditor EMAccountEditor; -typedef struct _EMAccountEditorClass EMAccountEditorClass; -typedef struct _EMAccountEditorPrivate EMAccountEditorPrivate; - -typedef enum { - EMAE_NOTEBOOK, - EMAE_DRUID, - EMAE_PAGES -} em_account_editor_t; - -struct _EMAccountEditor { - GObject gobject; - - EMAccountEditorPrivate *priv; - - em_account_editor_t type; - GtkWidget *editor; /* gtknotebook or druid, depending on type */ - - EMConfig *config; /* driver object */ - - EAccount *account; /* working account, must instant apply to this */ - EAccount *original; /* original account, not changed unless commit is invoked */ - - GtkWidget **pages; /* Pages for Anjal's page type editor */ - - guint do_signature:1; /* allow editing signature */ -}; - -struct _EMAccountEditorClass { - GObjectClass gobject_class; -}; - -GType em_account_editor_get_type(void); - -EMAccountEditor *em_account_editor_new(EAccount *account, em_account_editor_t type, const gchar *id); -EMAccountEditor *em_account_editor_new_for_pages(EAccount *account, em_account_editor_t type, gchar *id, GtkWidget **pages); -void em_account_editor_commit (EMAccountEditor *emae); -void em_account_editor_check (EMAccountEditor *emae, const gchar *page); - -gboolean em_account_editor_save (EMAccountEditor *gui); -void em_account_editor_destroy (EMAccountEditor *gui); - -gboolean em_account_editor_identity_complete (EMAccountEditor *gui, GtkWidget **incomplete); -gboolean em_account_editor_source_complete (EMAccountEditor *gui, GtkWidget **incomplete); -gboolean em_account_editor_transport_complete (EMAccountEditor *gui, GtkWidget **incomplete); -gboolean em_account_editor_management_complete (EMAccountEditor *gui, GtkWidget **incomplete); - -void em_account_editor_build_extra_conf (EMAccountEditor *gui, const gchar *url); - -void em_account_editor_auto_detect_extra_conf (EMAccountEditor *gui); - -G_END_DECLS - -#endif /* EM_ACCOUNT_EDITOR_H */ diff --git a/mail/em-account-prefs.c b/mail/em-account-prefs.c deleted file mode 100644 index f2c646d5ed..0000000000 --- a/mail/em-account-prefs.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * em-account-prefs.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -/* XXX EAccountManager handles all the user interface stuff. This subclass - * applies policies using mailer resources that EAccountManager does not - * have access to. The desire is to someday move account management - * completely out of the mailer, perhaps to evolution-data-server. */ - -#include "em-account-prefs.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include - -#include "e-util/e-error.h" - -#include "e-mail-store.h" -#include "em-config.h" -#include "em-account-editor.h" - -#define EM_ACCOUNT_PREFS_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), EM_TYPE_ACCOUNT_PREFS, EMAccountPrefsPrivate)) - -struct _EMAccountPrefsPrivate { - gpointer druid; /* weak pointer */ - gpointer editor; /* weak pointer */ -}; - -static gpointer parent_class; - -static void -account_prefs_enable_account_cb (EAccountTreeView *tree_view) -{ - EAccount *account; - - account = e_account_tree_view_get_selected (tree_view); - g_return_if_fail (account != NULL); - - e_mail_store_add_by_uri (account->source->url, account->name); -} - -static void -account_prefs_disable_account_cb (EAccountTreeView *tree_view) -{ - EAccountList *account_list; - EAccount *account; - gpointer parent; - gint response; - - account = e_account_tree_view_get_selected (tree_view); - g_return_if_fail (account != NULL); - - account_list = e_account_tree_view_get_account_list (tree_view); - g_return_if_fail (account_list != NULL); - - if (!e_account_list_account_has_proxies (account_list, account)) - return; - - parent = gtk_widget_get_toplevel (GTK_WIDGET (tree_view)); - parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; - - response = e_error_run ( - parent, "mail:ask-delete-proxy-accounts", NULL); - - if (response != GTK_RESPONSE_YES) { - g_signal_stop_emission_by_name (tree_view, "disable-account"); - return; - } - - e_account_list_remove_account_proxies (account_list, account); - - e_mail_store_remove_by_uri (account->source->url); -} - -static void -account_prefs_add_account (EAccountManager *manager) -{ - EMAccountPrefsPrivate *priv; - EMAccountEditor *emae; - gpointer parent; - - priv = EM_ACCOUNT_PREFS_GET_PRIVATE (manager); - - if (priv->druid != NULL) { - gtk_window_present (GTK_WINDOW (priv->druid)); - return; - } - - parent = gtk_widget_get_toplevel (GTK_WIDGET (manager)); - parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; - - /** @HookPoint-EMConfig: New Mail Account Druid - * @Id: org.gnome.evolution.mail.config.accountDruid - * @Type: E_CONFIG_DRUID - * @Class: org.gnome.evolution.mail.config:1.0 - * @Target: EMConfigTargetAccount - * - * The new mail account druid. - */ - emae = em_account_editor_new ( - NULL, EMAE_DRUID, - "org.gnome.evolution.mail.config.accountDruid"); - priv->druid = emae->editor; - - g_object_add_weak_pointer (G_OBJECT (priv->druid), &priv->druid); - gtk_window_set_transient_for (GTK_WINDOW (priv->druid), parent); - gtk_widget_show (priv->druid); -} - -static void -account_prefs_edit_account (EAccountManager *manager) -{ - EMAccountPrefsPrivate *priv; - EMAccountEditor *emae; - EAccountTreeView *tree_view; - EAccountList *account_list; - EAccount *account; - gpointer parent; - - priv = EM_ACCOUNT_PREFS_GET_PRIVATE (manager); - - if (priv->editor != NULL) { - gtk_window_present (GTK_WINDOW (priv->editor)); - return; - } - - account_list = e_account_manager_get_account_list (manager); - tree_view = e_account_manager_get_tree_view (manager); - account = e_account_tree_view_get_selected (tree_view); - g_return_if_fail (account != NULL); - - parent = gtk_widget_get_toplevel (GTK_WIDGET (manager)); - parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; - - /** @HookPoint-EMConfig: Mail Account Editor - * @Id: org.gnome.evolution.mail.config.accountEditor - * @Type: E_CONFIG_BOOK - * @Class: org.gnome.evolution.mail.config:1.0 - * @Target: EMConfigTargetAccount - * - * The account editor window. - */ - emae = em_account_editor_new ( - account, EMAE_NOTEBOOK, - "org.gnome.evolution.mail.config.accountEditor"); - priv->editor = emae->editor; - - g_object_add_weak_pointer (G_OBJECT (priv->editor), &priv->editor); - gtk_window_set_transient_for (GTK_WINDOW (priv->editor), parent); - gtk_widget_show (priv->editor); -} - -static void -account_prefs_delete_account (EAccountManager *manager) -{ - EMAccountPrefsPrivate *priv; - EAccountTreeView *tree_view; - EAccountList *account_list; - EAccount *account; - gboolean has_proxies; - gpointer parent; - gint response; - - priv = EM_ACCOUNT_PREFS_GET_PRIVATE (manager); - - account_list = e_account_manager_get_account_list (manager); - tree_view = e_account_manager_get_tree_view (manager); - account = e_account_tree_view_get_selected (tree_view); - g_return_if_fail (account != NULL); - - /* Make sure we aren't editing anything... */ - if (priv->editor != NULL) - return; - - parent = gtk_widget_get_toplevel (GTK_WIDGET (manager)); - parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; - - has_proxies = - e_account_list_account_has_proxies (account_list, account); - - response = e_error_run ( - parent, has_proxies ? - "mail:ask-delete-account-with-proxies" : - "mail:ask-delete-account", NULL); - - if (response != GTK_RESPONSE_YES) { - g_signal_stop_emission_by_name (manager, "delete-account"); - return; - } - - /* Remove the account from the folder tree. */ - if (account->enabled && account->source && account->source->url) - e_mail_store_remove_by_uri (account->source->url); - - /* Remove all the proxies the account has created. */ - if (has_proxies) - e_account_list_remove_account_proxies (account_list, account); - - /* Remove it from the config file. */ - e_account_list_remove (account_list, account); - - e_account_list_save (account_list); -} - -static void -account_prefs_dispose (GObject *object) -{ - EMAccountPrefsPrivate *priv; - - priv = EM_ACCOUNT_PREFS_GET_PRIVATE (object); - - if (priv->druid != NULL) { - g_object_remove_weak_pointer ( - G_OBJECT (priv->druid), &priv->druid); - priv->druid = NULL; - } - - if (priv->editor != NULL) { - g_object_remove_weak_pointer ( - G_OBJECT (priv->editor), &priv->editor); - priv->editor = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -account_prefs_class_init (EMAccountPrefsClass *class) -{ - GObjectClass *object_class; - EAccountManagerClass *account_manager_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (EMAccountPrefsPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->dispose = account_prefs_dispose; - - account_manager_class = E_ACCOUNT_MANAGER_CLASS (class); - account_manager_class->add_account = account_prefs_add_account; - account_manager_class->edit_account = account_prefs_edit_account; - account_manager_class->delete_account = account_prefs_delete_account; -} - -static void -account_prefs_init (EMAccountPrefs *prefs) -{ - EAccountManager *manager; - EAccountTreeView *tree_view; - - prefs->priv = EM_ACCOUNT_PREFS_GET_PRIVATE (prefs); - - manager = E_ACCOUNT_MANAGER (prefs); - tree_view = e_account_manager_get_tree_view (manager); - - g_signal_connect ( - tree_view, "enable-account", - G_CALLBACK (account_prefs_enable_account_cb), NULL); - - g_signal_connect ( - tree_view, "disable-account", - G_CALLBACK (account_prefs_disable_account_cb), NULL); -} - -GType -em_account_prefs_get_type (void) -{ - static GType type = 0; - - if (G_UNLIKELY (type == 0)) { - static const GTypeInfo type_info = { - sizeof (EMAccountPrefsClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) account_prefs_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (EMAccountPrefs), - 0, /* n_preallocs */ - (GInstanceInitFunc) account_prefs_init, - NULL /* value_table */ - }; - - type = g_type_register_static ( - E_TYPE_ACCOUNT_MANAGER, "EMAccountPrefs", - &type_info, 0); - } - - return type; -} - -GtkWidget * -em_account_prefs_new (EAccountList *account_list) -{ - g_return_val_if_fail (E_IS_ACCOUNT_LIST (account_list), NULL); - - return g_object_new ( - EM_TYPE_ACCOUNT_PREFS, "account-list", account_list, NULL); -} diff --git a/mail/em-account-prefs.h b/mail/em-account-prefs.h deleted file mode 100644 index 82df8fa941..0000000000 --- a/mail/em-account-prefs.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * em-account-prefs.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef EM_ACCOUNT_PREFS_H -#define EM_ACCOUNT_PREFS_H - -#include -#include -#include -#include - -/* Standard GObject macros */ -#define EM_TYPE_ACCOUNT_PREFS \ - (em_account_prefs_get_type ()) -#define EM_ACCOUNT_PREFS(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), EM_TYPE_ACCOUNT_PREFS, EMAccountPrefs)) -#define EM_ACCOUNT_PREFS_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), EM_TYPE_ACCOUNT_PREFS, EMAccountPrefsClass)) -#define EM_IS_ACCOUNT_PREFS(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), EM_TYPE_ACCOUNT_PREFS)) -#define EM_IS_ACCOUNT_PREFS_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), EM_TYPE_ACCOUNT_PREFS)) -#define EM_ACCOUNT_PREFS_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), EM_TYPE_ACCOUNT_PREFS, EMAccountPrefsClass)) - -G_BEGIN_DECLS - -typedef struct _EMAccountPrefs EMAccountPrefs; -typedef struct _EMAccountPrefsClass EMAccountPrefsClass; -typedef struct _EMAccountPrefsPrivate EMAccountPrefsPrivate; - -struct _EMAccountPrefs { - EAccountManager parent; - EMAccountPrefsPrivate *priv; -}; - -struct _EMAccountPrefsClass { - EAccountManagerClass parent_class; -}; - -GType em_account_prefs_get_type (void); -GtkWidget * em_account_prefs_new (EAccountList *account_list); - -G_END_DECLS - -#endif /* EM_ACCOUNT_PREFS_H */ diff --git a/mail/em-composer-prefs.c b/mail/em-composer-prefs.c deleted file mode 100644 index d87bb37ffb..0000000000 --- a/mail/em-composer-prefs.c +++ /dev/null @@ -1,621 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Jeffrey Stedfast - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "e-util/e-binding.h" -#include "e-util/e-signature-utils.h" -#include "e-util/gconf-bridge.h" - -#include "em-composer-prefs.h" -#include "composer/e-msg-composer.h" - -#include - -#include - -#include -#include - -#include -#include - -#include "misc/e-charset-picker.h" -#include "misc/e-signature-manager.h" -#include "misc/e-signature-preview.h" -#include "e-util/e-error.h" -#include "e-util/e-util-private.h" - -#include "mail-config.h" -#include "e-signature-editor.h" -#include "em-config.h" - -static gpointer parent_class; - -static gboolean -transform_color_to_string (const GValue *src_value, - GValue *dst_value, - gpointer user_data) -{ - const GdkColor *color; - gchar *string; - - color = g_value_get_boxed (src_value); - string = gdk_color_to_string (color); - g_value_set_string (dst_value, string); - g_free (string); - - return TRUE; -} - -static gboolean -transform_string_to_color (const GValue *src_value, - GValue *dst_value, - gpointer user_data) -{ - GdkColor color; - const gchar *string; - gboolean success = FALSE; - - string = g_value_get_string (src_value); - if (gdk_color_parse (string, &color)) { - g_value_set_boxed (dst_value, &color); - success = TRUE; - } - - return success; -} - -static gboolean -transform_old_to_new_reply_style (const GValue *src_value, - GValue *dst_value, - gpointer user_data) -{ - gboolean success = TRUE; - - /* XXX This is the kind of legacy crap we wind up - * with when we don't migrate things properly. */ - - switch (g_value_get_int (src_value)) { - case 0: /* Quoted: 0 -> 2 */ - g_value_set_int (dst_value, 2); - break; - - case 1: /* Do Not Quote: 1 -> 3 */ - g_value_set_int (dst_value, 3); - break; - - case 2: /* Attach: 2 -> 0 */ - g_value_set_int (dst_value, 0); - break; - - case 3: /* Outlook: 3 -> 1 */ - g_value_set_int (dst_value, 1); - break; - - default: - success = FALSE; - break; - } - - return success; -} - -static gboolean -transform_new_to_old_reply_style (const GValue *src_value, - GValue *dst_value, - gpointer user_data) -{ - gboolean success = TRUE; - - /* XXX This is the kind of legacy crap we wind up - * with when we don't migrate things properly. */ - - switch (g_value_get_int (src_value)) { - case 0: /* Attach: 0 -> 2 */ - g_value_set_int (dst_value, 2); - break; - - case 1: /* Outlook: 1 -> 3 */ - g_value_set_int (dst_value, 3); - break; - - case 2: /* Quoted: 2 -> 0 */ - g_value_set_int (dst_value, 0); - break; - - case 3: /* Do Not Quote: 3 -> 1 */ - g_value_set_int (dst_value, 1); - break; - - default: - success = FALSE; - break; - } - - return success; -} - -static void -composer_prefs_finalize (GObject *object) -{ - EMComposerPrefs *prefs = (EMComposerPrefs *) object; - - g_object_unref (prefs->gui); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -composer_prefs_class_init (EMComposerPrefsClass *class) -{ - GObjectClass *object_class; - - parent_class = g_type_class_peek_parent (class); - - object_class = G_OBJECT_CLASS (class); - object_class->finalize = composer_prefs_finalize; -} - -static void -composer_prefs_init (EMComposerPrefs *prefs) -{ -} - -GType -em_composer_prefs_get_type (void) -{ - static GType type = 0; - - if (G_UNLIKELY (type == 0)) { - static const GTypeInfo type_info = { - sizeof (EMComposerPrefsClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) composer_prefs_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (EMComposerPrefs), - 0, /* n_allocs */ - (GInstanceInitFunc) composer_prefs_init, - NULL /* value_table */ - }; - - type = g_type_register_static ( - GTK_TYPE_VBOX, "EMComposerPrefs", &type_info, 0); - } - - return type; -} - -void -em_composer_prefs_new_signature (GtkWindow *parent, - gboolean html_mode) -{ - GtkWidget *editor; - - editor = e_signature_editor_new (); - gtkhtml_editor_set_html_mode (GTKHTML_EDITOR (editor), html_mode); - gtk_window_set_transient_for (GTK_WINDOW (editor), parent); - gtk_widget_show (editor); -} - -static void -spell_language_toggled_cb (GtkCellRendererToggle *renderer, - const gchar *path_string, - EMComposerPrefs *prefs) -{ - GtkTreeModel *model; - GtkTreePath *path; - GtkTreeIter iter; - gboolean active; - gboolean valid; - - model = prefs->language_model; - - /* Convert the path string to a tree iterator. */ - path = gtk_tree_path_new_from_string (path_string); - valid = gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_path_free (path); - g_return_if_fail (valid); - - /* Toggle the active state. */ - gtk_tree_model_get (model, &iter, 0, &active, -1); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, !active, -1); -} - -static void -spell_language_save (EMComposerPrefs *prefs) -{ - GList *spell_languages = NULL; - GtkTreeModel *model; - GtkTreeIter iter; - gboolean valid; - - model = prefs->language_model; - - /* Build a list of active spell languages. */ - valid = gtk_tree_model_get_iter_first (model, &iter); - while (valid) { - const GtkhtmlSpellLanguage *language; - gboolean active; - - gtk_tree_model_get ( - model, &iter, 0, &active, 2, &language, -1); - - if (active) - spell_languages = g_list_prepend ( - spell_languages, (gpointer) language); - - valid = gtk_tree_model_iter_next (model, &iter); - } - spell_languages = g_list_reverse (spell_languages); - - /* Update the GConf value. */ - e_save_spell_languages (spell_languages); - - g_list_free (spell_languages); -} - -static void -spell_setup (EMComposerPrefs *prefs) -{ - const GList *available_languages; - GList *active_languages; - GtkListStore *store; - - store = GTK_LIST_STORE (prefs->language_model); - available_languages = gtkhtml_spell_language_get_available (); - - active_languages = e_load_spell_languages (); - - /* Populate the GtkListStore. */ - while (available_languages != NULL) { - const GtkhtmlSpellLanguage *language; - GtkTreeIter tree_iter; - const gchar *name; - gboolean active; - - language = available_languages->data; - name = gtkhtml_spell_language_get_name (language); - active = (g_list_find (active_languages, language) != NULL); - - gtk_list_store_append (store, &tree_iter); - - gtk_list_store_set ( - store, &tree_iter, - 0, active, 1, name, 2, language, -1); - - available_languages = available_languages->next; - } - - g_list_free (active_languages); -} - -static void -charset_activate (GtkWidget *item, - EMComposerPrefs *prefs) -{ - GConfClient *client; - GtkWidget *menu; - gchar *string; - - client = mail_config_get_gconf_client (); - menu = gtk_option_menu_get_menu (prefs->charset); - string = e_charset_picker_get_charset (menu); - - if (string == NULL) - string = g_strdup (camel_iconv_locale_charset ()); - - gconf_client_set_string ( - client, "/apps/evolution/mail/composer/charset", - string, NULL); - - g_free (string); -} - -static void -option_menu_connect (EMComposerPrefs *prefs, - GtkOptionMenu *omenu, - GCallback callback, - const gchar *key) -{ - GConfClient *client; - GtkWidget *menu; - GList *list; - - client = mail_config_get_gconf_client (); - menu = gtk_option_menu_get_menu (omenu); - list = GTK_MENU_SHELL (menu)->children; - - while (list != NULL) { - GtkWidget *widget = list->data; - - g_object_set_data (G_OBJECT (widget), "key", (gpointer) key); - g_signal_connect (widget, "activate", callback, prefs); - list = list->next; - } - - if (!gconf_client_key_is_writable (client, key, NULL)) - gtk_widget_set_sensitive (GTK_WIDGET (omenu), FALSE); -} - -static GtkWidget * -emcp_widget_glade (EConfig *ec, - EConfigItem *item, - GtkWidget *parent, - GtkWidget *old, - gpointer data) -{ - EMComposerPrefs *prefs = data; - - return glade_xml_get_widget (prefs->gui, item->label); -} - -/* plugin meta-data */ -static EMConfigItem emcp_items[] = { - { E_CONFIG_BOOK, (gchar *) "", (gchar *) "composer_toplevel", emcp_widget_glade }, - { E_CONFIG_PAGE, (gchar *) "00.general", (gchar *) "vboxGeneral", emcp_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "00.general/00.behavior", (gchar *) "vboxBehavior", emcp_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "00.general/10.alerts", (gchar *) "vboxAlerts", emcp_widget_glade }, - { E_CONFIG_PAGE, (gchar *) "10.signatures", (gchar *) "vboxSignatures", emcp_widget_glade }, - /* signature/signatures and signature/preview parts not usable */ - - { E_CONFIG_PAGE, (gchar *) "20.spellcheck", (gchar *) "vboxSpellChecking", emcp_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "20.spellcheck/00.languages", (gchar *) "vbox178", emcp_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "20.spellcheck/00.options", (gchar *) "vboxOptions", emcp_widget_glade }, -}; - -static void -emcp_free (EConfig *ec, GSList *items, gpointer data) -{ - /* the prefs data is freed automagically */ - g_slist_free (items); -} - -static void -em_composer_prefs_construct (EMComposerPrefs *prefs, - EShell *shell) -{ - GtkWidget *toplevel, *widget, *menu, *info_pixmap; - GtkWidget *container; - EShellSettings *shell_settings; - ESignatureList *signature_list; - ESignatureTreeView *signature_tree_view; - GladeXML *gui; - GtkTreeView *view; - GtkListStore *store; - GtkTreeSelection *selection; - GtkCellRenderer *renderer; - GConfBridge *bridge; - GConfClient *client; - gchar *buf; - EMConfig *ec; - EMConfigTargetPrefs *target; - GSList *l; - gint i; - gchar *gladefile; - - bridge = gconf_bridge_get (); - client = mail_config_get_gconf_client (); - shell_settings = e_shell_get_shell_settings (shell); - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - "mail-config.glade", - NULL); - gui = glade_xml_new (gladefile, "composer_toplevel", NULL); - prefs->gui = gui; - g_free (gladefile); - - /** @HookPoint-EMConfig: Mail Composer Preferences - * @Id: org.gnome.evolution.mail.composerPrefs - * @Type: E_CONFIG_BOOK - * @Class: org.gnome.evolution.mail.config:1.0 - * @Target: EMConfigTargetPrefs - * - * The mail composer preferences settings page. - */ - ec = em_config_new(E_CONFIG_BOOK, "org.gnome.evolution.mail.composerPrefs"); - l = NULL; - for (i = 0; i < G_N_ELEMENTS (emcp_items); i++) - l = g_slist_prepend(l, &emcp_items[i]); - e_config_add_items((EConfig *)ec, l, NULL, NULL, emcp_free, prefs); - - /* General tab */ - - /* Default Behavior */ - widget = glade_xml_get_widget (gui, "chkSendHTML"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "composer-format-html", - G_OBJECT (widget), "active"); - - widget = glade_xml_get_widget (gui, "chkPromptEmptySubject"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "composer-prompt-empty-subject", - G_OBJECT (widget), "active"); - - widget = glade_xml_get_widget (gui, "chkPromptBccOnly"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "composer-prompt-only-bcc", - G_OBJECT (widget), "active"); - - widget = glade_xml_get_widget (gui, "chkAutoSmileys"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "composer-magic-smileys", - G_OBJECT (widget), "active"); - - widget = glade_xml_get_widget (gui, "chkRequestReceipt"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "composer-request-receipt", - G_OBJECT (widget), "active"); - - widget = glade_xml_get_widget (gui, "chkReplyStartBottom"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "composer-reply-start-bottom", - G_OBJECT (widget), "active"); - - widget = glade_xml_get_widget (gui, "chkOutlookFilenames"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "composer-outlook-filenames", - G_OBJECT (widget), "active"); - - widget = glade_xml_get_widget (gui, "chkTopSignature"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "composer-top-signature", - G_OBJECT (widget), "active"); - - widget = glade_xml_get_widget (gui, "chkEnableSpellChecking"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "composer-inline-spelling", - G_OBJECT (widget), "active"); - - prefs->charset = GTK_OPTION_MENU ( - glade_xml_get_widget (gui, "omenuCharset1")); - buf = gconf_client_get_string ( - client, "/apps/evolution/mail/composer/charset", NULL); - menu = e_charset_picker_new ( - buf && *buf ? buf : camel_iconv_locale_charset ()); - gtk_option_menu_set_menu (prefs->charset, GTK_WIDGET (menu)); - option_menu_connect ( - prefs, prefs->charset, - G_CALLBACK (charset_activate), - "/apps/evolution/mail/composer/charset"); - g_free (buf); - - /* Spell Checking */ - widget = glade_xml_get_widget (gui, "listSpellCheckLanguage"); - view = GTK_TREE_VIEW (widget); - store = gtk_list_store_new ( - 3, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_POINTER); - g_signal_connect_swapped ( - store, "row-changed", - G_CALLBACK (spell_language_save), prefs); - prefs->language_model = GTK_TREE_MODEL (store); - gtk_tree_view_set_model (view, prefs->language_model); - renderer = gtk_cell_renderer_toggle_new (); - g_signal_connect ( - renderer, "toggled", - G_CALLBACK (spell_language_toggled_cb), prefs); - gtk_tree_view_insert_column_with_attributes ( - view, -1, _("Enabled"), - renderer, "active", 0, NULL); - - gtk_tree_view_insert_column_with_attributes ( - view, -1, _("Language(s)"), - gtk_cell_renderer_text_new (), - "text", 1, NULL); - selection = gtk_tree_view_get_selection (view); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE); - info_pixmap = glade_xml_get_widget (gui, "pixmapSpellInfo"); - gtk_image_set_from_stock ( - GTK_IMAGE (info_pixmap), - GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_BUTTON); - - widget = glade_xml_get_widget (gui, "colorButtonSpellCheckColor"); - e_mutual_binding_new_full ( - G_OBJECT (shell_settings), "composer-spell-color", - G_OBJECT (widget), "color", - transform_string_to_color, - transform_color_to_string, - NULL, NULL); - - spell_setup (prefs); - - /* Forwards and Replies */ - widget = glade_xml_get_widget (gui, "comboboxForwardStyle"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-forward-style", - G_OBJECT (widget), "active"); - - widget = glade_xml_get_widget (gui, "comboboxReplyStyle"); - e_mutual_binding_new_full ( - G_OBJECT (shell_settings), "mail-reply-style", - G_OBJECT (widget), "active", - transform_old_to_new_reply_style, - transform_new_to_old_reply_style, - NULL, NULL); - - /* Signatures */ - signature_list = e_get_signature_list (); - container = glade_xml_get_widget (gui, "alignSignatures"); - widget = e_signature_manager_new (signature_list); - gtk_container_add (GTK_CONTAINER (container), widget); - gtk_widget_show (widget); - - /* The mail shell backend responds to the "window-created" signal - * that this triggers and configures it with composer preferences. */ - g_signal_connect_swapped ( - widget, "editor-created", - G_CALLBACK (e_shell_watch_window), shell); - - e_binding_new ( - G_OBJECT (shell_settings), "composer-format-html", - G_OBJECT (widget), "prefer-html"); - - e_binding_new_with_negation ( - G_OBJECT (shell_settings), "disable-command-line", - G_OBJECT (widget), "allow-scripts"); - - signature_tree_view = e_signature_manager_get_tree_view ( - E_SIGNATURE_MANAGER (widget)); - - container = glade_xml_get_widget (gui, "scrolled-sig"); - widget = e_signature_preview_new (); - gtk_container_add (GTK_CONTAINER (container), widget); - gtk_widget_show (widget); - - e_binding_new_with_negation ( - G_OBJECT (shell_settings), "disable-command-line", - G_OBJECT (widget), "allow-scripts"); - - e_binding_new ( - G_OBJECT (signature_tree_view), "selected", - G_OBJECT (widget), "signature"); - - /* get our toplevel widget */ - target = em_config_target_new_prefs (ec, client); - e_config_set_target ((EConfig *)ec, (EConfigTarget *)target); - toplevel = e_config_create_widget ((EConfig *)ec); - gtk_container_add (GTK_CONTAINER (prefs), toplevel); -} - -GtkWidget * -em_composer_prefs_new (EShell *shell) -{ - EMComposerPrefs *prefs; - - g_return_val_if_fail (E_IS_SHELL (shell), NULL); - - prefs = g_object_new (EM_TYPE_COMPOSER_PREFS, NULL); - em_composer_prefs_construct (prefs, shell); - - return GTK_WIDGET (prefs); -} diff --git a/mail/em-composer-prefs.h b/mail/em-composer-prefs.h deleted file mode 100644 index 3b848f1a2f..0000000000 --- a/mail/em-composer-prefs.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Jeffrey Stedfast - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef EM_COMPOSER_PREFS_H -#define EM_COMPOSER_PREFS_H - -#include -#include -#include - -#include - -/* Standard GObject macros */ -#define EM_TYPE_COMPOSER_PREFS \ - (em_composer_prefs_get_type ()) -#define EM_COMPOSER_PREFS(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), EM_TYPE_COMPOSER_PREFS, EMComposerPrefs)) -#define EM_COMPOSER_PREFS_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), EM_TYPE_COMPOSER_PREFS, EMComposerPrefsClass)) -#define EM_IS_COMPOSER_PREFS(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), EM_TYPE_COMPOSER_PREFS)) -#define EM_IS_COMPOSER_PREFS_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), EM_TYPE_COMPOSER_PREFS)) -#define EM_COMPOSER_PREFS_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), EM_TYPE_COMPOSER_PREFS, EMComposerPrefsClass)) - -G_BEGIN_DECLS - -typedef struct _EMComposerPrefs EMComposerPrefs; -typedef struct _EMComposerPrefsClass EMComposerPrefsClass; - -struct _ESignature; - -struct _EMComposerPrefs { - GtkVBox parent; - - GladeXML *gui; - - /* General tab */ - - /* Default Behavior */ - GtkOptionMenu *charset; - - GtkTreeModel *language_model; - - /* Forwards and Replies */ - GtkComboBox *forward_style; - GtkComboBox *reply_style; - - /* Signatures */ - GtkHTML *sig_preview; -}; - -struct _EMComposerPrefsClass { - GtkVBoxClass parent_class; -}; - -GType em_composer_prefs_get_type (void); -GtkWidget * em_composer_prefs_new (EShell *shell); -void em_composer_prefs_new_signature (GtkWindow *parent, - gboolean html_mode); - -/* needed by global config */ -#define EM_COMPOSER_PREFS_CONTROL_ID \ - "OAFIID:GNOME_Evolution_Mail_ComposerPrefs_ConfigControl:" BASE_VERSION - -G_END_DECLS - -#endif /* EM_COMPOSER_PREFS_H */ diff --git a/mail/em-folder-tree.h b/mail/em-folder-tree.h index b92c0a2f4c..74b79d37ee 100644 --- a/mail/em-folder-tree.h +++ b/mail/em-folder-tree.h @@ -26,7 +26,6 @@ #include #include -#include #include /* Standard GObject macros */ diff --git a/mail/em-mailer-prefs.c b/mail/em-mailer-prefs.c deleted file mode 100644 index fa450dc2ee..0000000000 --- a/mail/em-mailer-prefs.c +++ /dev/null @@ -1,1332 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Jeffrey Stedfast - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "em-mailer-prefs.h" -#include "em-format/em-format.h" - -#include -#include -#include -#include "misc/e-charset-picker.h" - -#include - -#include - -#include "libedataserverui/e-cell-renderer-color.h" - -#include "e-util/e-binding.h" -#include "e-util/e-util-private.h" - -#include "e-mail-label-manager.h" -#include "mail-config.h" -#include "em-junk-hook.h" -#include "em-config.h" -#include "mail-session.h" - -static void em_mailer_prefs_class_init (EMMailerPrefsClass *class); -static void em_mailer_prefs_init (EMMailerPrefs *dialog); -static void em_mailer_prefs_finalize (GObject *object); - -static GtkVBoxClass *parent_class = NULL; - -enum { - HEADER_LIST_NAME_COLUMN, /* displayable name of the header (may be a translation) */ - HEADER_LIST_ENABLED_COLUMN, /* is the header enabled? */ - HEADER_LIST_IS_DEFAULT_COLUMN, /* is this header a default header, eg From: */ - HEADER_LIST_HEADER_COLUMN, /* the real name of this header */ - HEADER_LIST_N_COLUMNS -}; - -static GType col_types[] = { - G_TYPE_STRING, - G_TYPE_BOOLEAN, - G_TYPE_BOOLEAN, - G_TYPE_STRING -}; - -/* temporarily copied from em-format.c */ -static const gchar *default_headers[] = { - N_("From"), - N_("Reply-To"), - N_("To"), - N_("Cc"), - N_("Bcc"), - N_("Subject"), - N_("Date"), - N_("Newsgroups"), - N_("Face"), - "x-evolution-mailer", /* DO NOT translate */ -}; - -#define EM_FORMAT_HEADER_XMAILER "x-evolution-mailer" - -/* for empty trash on exit frequency */ -static const struct { - const gchar *label; - gint days; -} empty_trash_frequency[] = { - { N_("Every time"), 0 }, - { N_("Once per day"), 1 }, - { N_("Once per week"), 7 }, - { N_("Once per month"), 30 }, -}; - -GType -em_mailer_prefs_get_type (void) -{ - static GType type = 0; - - if (!type) { - GTypeInfo type_info = { - sizeof (EMMailerPrefsClass), - NULL, NULL, - (GClassInitFunc) em_mailer_prefs_class_init, - NULL, NULL, - sizeof (EMMailerPrefs), - 0, - (GInstanceInitFunc) em_mailer_prefs_init, - }; - - type = g_type_register_static (gtk_vbox_get_type (), "EMMailerPrefs", &type_info, 0); - } - - return type; -} - -static void -em_mailer_prefs_class_init (EMMailerPrefsClass *klass) -{ - GObjectClass *object_class; - - object_class = (GObjectClass *) klass; - parent_class = g_type_class_ref (gtk_vbox_get_type ()); - - object_class->finalize = em_mailer_prefs_finalize; -} - -static void -em_mailer_prefs_init (EMMailerPrefs *preferences) -{ - preferences->gconf = mail_config_get_gconf_client (); -} - -static void -em_mailer_prefs_finalize (GObject *obj) -{ - EMMailerPrefs *prefs = (EMMailerPrefs *) obj; - - g_object_unref (prefs->gui); - - if (prefs->labels_change_notify_id) { - gconf_client_notify_remove (prefs->gconf, prefs->labels_change_notify_id); - - prefs->labels_change_notify_id = 0; - } - - ((GObjectClass *)(parent_class))->finalize (obj); -} - -static gboolean -mark_seen_timeout_transform (const GValue *src_value, - GValue *dst_value, - gpointer user_data) -{ - gdouble v_double; - - /* Shell Settings (gint) -> Spin Button (double) */ - v_double = (gdouble) g_value_get_int (src_value); - g_value_set_double (dst_value, v_double / 1000.0); - - return TRUE; -} - -static gboolean -mark_seen_timeout_reverse_transform (const GValue *src_value, - GValue *dst_value, - gpointer user_data) -{ - gdouble v_double; - - /* Spin Button (double) -> Shell Settings (gint) */ - v_double = g_value_get_double (src_value); - g_value_set_int (dst_value, v_double * 1000); - - return TRUE; -} - -enum { - JH_LIST_COLUMN_NAME, - JH_LIST_COLUMN_VALUE -}; - -static void -jh_tree_refill (EMMailerPrefs *prefs) -{ - GtkListStore *store = prefs->junk_header_list_store; - GSList *l, *cjh = gconf_client_get_list (prefs->gconf, "/apps/evolution/mail/junk/custom_header", GCONF_VALUE_STRING, NULL); - - gtk_list_store_clear (store); - - for (l = cjh; l; l = l->next) { - GtkTreeIter iter; - gchar **tokens = g_strsplit (l->data, "=", 2); - - gtk_list_store_append (store, &iter); - gtk_list_store_set ( - store, &iter, - JH_LIST_COLUMN_NAME , tokens[0] ? tokens[0] : "", - JH_LIST_COLUMN_VALUE, tokens[1] ? tokens[1] : "" , - -1); - g_strfreev (tokens); - } - - g_slist_foreach (cjh, (GFunc) g_free, NULL); - g_slist_free (cjh); -} - -static void -jh_add_cb (GtkWidget *widget, gpointer user_data) -{ - EMMailerPrefs *prefs = (EMMailerPrefs *) user_data; - GtkWidget *dialog, *l1, *l2, *entry1, *entry2, *vbox, *hbox; - gint response; - dialog = gtk_dialog_new_with_buttons (_("Add Custom Junk Header"), (GtkWindow *)gtk_widget_get_toplevel (widget), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); - - vbox = gtk_vbox_new (FALSE, 6); - hbox = gtk_hbox_new (FALSE, 0); - l1 = gtk_label_new_with_mnemonic (_("Header Name:")); - l2 = gtk_label_new_with_mnemonic (_("Header Value Contains:")); - entry1 = gtk_entry_new (); - entry2 = gtk_entry_new (); - gtk_box_pack_start ((GtkBox *) hbox, l1, FALSE, FALSE, 6); - gtk_box_pack_start ((GtkBox *)hbox, entry1, FALSE, FALSE, 6); - gtk_box_pack_start ((GtkBox *)vbox, hbox, FALSE, FALSE, 6); - - hbox = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start ((GtkBox *)hbox, l2, FALSE, FALSE, 6); - gtk_box_pack_start ((GtkBox *)hbox, entry2, FALSE, FALSE, 6); - gtk_box_pack_start ((GtkBox *)vbox, hbox, FALSE, FALSE, 6); - - gtk_widget_show_all (vbox); - gtk_container_add ((GtkContainer *)((GtkDialog *)dialog)->vbox, vbox); - response = gtk_dialog_run ((GtkDialog *)dialog); - if (response == GTK_RESPONSE_ACCEPT) { - const gchar *name = gtk_entry_get_text ((GtkEntry *)entry1); - const gchar *value = gtk_entry_get_text ((GtkEntry *)entry2); - gchar *tok; - GSList *list = gconf_client_get_list (prefs->gconf, "/apps/evolution/mail/junk/custom_header", GCONF_VALUE_STRING, NULL); - - /* FIXME: Validate the values */ - - tok = g_strdup_printf ("%s=%s", name, value); - list = g_slist_append (list, tok); - gconf_client_set_list (prefs->gconf, "/apps/evolution/mail/junk/custom_header", GCONF_VALUE_STRING, list, NULL); - g_slist_foreach (list, (GFunc)g_free, NULL); - - g_slist_free (list); - } - gtk_widget_destroy (dialog); - jh_tree_refill (prefs); -} - -static void -jh_remove_cb (GtkWidget *widget, gpointer user_data) -{ - EMMailerPrefs *prefs = user_data; - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - - g_return_if_fail (prefs != NULL); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->junk_header_tree)); - if (gtk_tree_selection_get_selected (selection, &model, &iter)) { - gchar *name=NULL, *value=NULL; - GSList *prev = NULL, *node, *list = gconf_client_get_list (prefs->gconf, "/apps/evolution/mail/junk/custom_header", GCONF_VALUE_STRING, NULL); - gtk_tree_model_get (model, &iter, JH_LIST_COLUMN_NAME, &name, JH_LIST_COLUMN_VALUE, &value, -1); - node = list; - while (node) { - gchar *test; - gint len = strlen (name); - test = strncmp (node->data, name, len) == 0 ? (gchar *) node->data+len:NULL; - - if (test) { - test++; - if (strcmp (test, value) == 0) - break; - } - - prev = node; - node = node->next; - } - - if (prev && !node) { - /* Not found. So what? */ - } else if (prev && node) { - prev->next = node->next; - g_free (node->data); - } else if (!prev && node) { - list = list->next; - g_free (node->data); - } - - gconf_client_set_list (prefs->gconf, "/apps/evolution/mail/junk/custom_header", GCONF_VALUE_STRING, list, NULL); - - g_slist_foreach (list, (GFunc)g_free, NULL); - g_slist_free (list); - g_free (name); - g_free (value); - - jh_tree_refill (prefs); - } -} - - -static GtkListStore * -init_junk_tree (GtkWidget *label_tree, EMMailerPrefs *prefs) -{ - GtkListStore *store; - GtkCellRenderer *renderer; - gint col; - - g_return_val_if_fail (label_tree != NULL, NULL); - g_return_val_if_fail (prefs != NULL, NULL); - - store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); - gtk_tree_view_set_model (GTK_TREE_VIEW (label_tree), GTK_TREE_MODEL (store)); - - renderer = gtk_cell_renderer_text_new (); - col = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (label_tree), -1, _("Header"), renderer, "text", JH_LIST_COLUMN_NAME, NULL); - g_object_set (G_OBJECT (renderer), "editable", TRUE, NULL); - - renderer = gtk_cell_renderer_text_new (); - gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (label_tree), -1, _("Contains Value"), renderer, "text", JH_LIST_COLUMN_VALUE, NULL); - g_object_set (G_OBJECT (renderer), "editable", TRUE, NULL); - - return store; -} - -static void -emmp_header_remove_sensitivity (EMMailerPrefs *prefs) -{ - GtkTreeIter iter; - GtkTreeSelection *selection = gtk_tree_view_get_selection (prefs->header_list); - gboolean is_default; - - /* remove button should be sensitive if the currenlty selected entry in the list view - is not a default header. if there are no entries, or none is selected, it should be - disabled - */ - if (gtk_tree_selection_get_selected (selection, NULL, &iter)) { - gtk_tree_model_get (GTK_TREE_MODEL (prefs->header_list_store), &iter, - HEADER_LIST_IS_DEFAULT_COLUMN, &is_default, - -1); - if (is_default) - gtk_widget_set_sensitive (GTK_WIDGET (prefs->remove_header), FALSE); - else - gtk_widget_set_sensitive (GTK_WIDGET (prefs->remove_header), TRUE); - } else { - gtk_widget_set_sensitive (GTK_WIDGET (prefs->remove_header), FALSE); - } -} - -static gboolean -emmp_header_is_valid (const gchar *header) -{ - gint len = g_utf8_strlen (header, -1); - - if (header[0] == 0 - || g_utf8_strchr (header, len, ':') != NULL - || g_utf8_strchr (header, len, ' ') != NULL) - return FALSE; - - return TRUE; -} - -static void -emmp_header_add_sensitivity (EMMailerPrefs *prefs) -{ - const gchar *entry_contents; - GtkTreeIter iter; - gboolean valid; - - /* the add header button should be sensitive if the text box contains - a valid header string, that is not a duplicate with something already - in the list view - */ - entry_contents = gtk_entry_get_text (GTK_ENTRY (prefs->entry_header)); - if (!emmp_header_is_valid (entry_contents)) { - gtk_widget_set_sensitive (GTK_WIDGET (prefs->add_header), FALSE); - return; - } - - /* check if this is a duplicate */ - valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (prefs->header_list_store), &iter); - while (valid) { - gchar *header_name; - - gtk_tree_model_get (GTK_TREE_MODEL (prefs->header_list_store), &iter, - HEADER_LIST_HEADER_COLUMN, &header_name, - -1); - if (g_ascii_strcasecmp (header_name, entry_contents) == 0) { - gtk_widget_set_sensitive (GTK_WIDGET (prefs->add_header), FALSE); - return; - } - - valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (prefs->header_list_store), &iter); - } - - gtk_widget_set_sensitive (GTK_WIDGET (prefs->add_header), TRUE); -} - -static void -emmp_save_headers (EMMailerPrefs *prefs) -{ - GSList *header_list; - GtkTreeIter iter; - gboolean valid; - - /* Headers */ - header_list = NULL; - valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (prefs->header_list_store), &iter); - while (valid) { - struct _EMMailerPrefsHeader h; - gboolean enabled; - gchar *xml; - - gtk_tree_model_get (GTK_TREE_MODEL (prefs->header_list_store), &iter, - HEADER_LIST_HEADER_COLUMN, &h.name, - HEADER_LIST_ENABLED_COLUMN, &enabled, - -1); - h.enabled = enabled; - - if ((xml = em_mailer_prefs_header_to_xml (&h))) - header_list = g_slist_append (header_list, xml); - - valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (prefs->header_list_store), &iter); - } - - gconf_client_set_list (prefs->gconf, "/apps/evolution/mail/display/headers", GCONF_VALUE_STRING, header_list, NULL); - g_slist_foreach (header_list, (GFunc) g_free, NULL); - g_slist_free (header_list); -} - -static void -emmp_header_list_enabled_toggled (GtkCellRendererToggle *cell, const gchar *path_string, EMMailerPrefs *prefs) -{ - GtkTreeModel *model = GTK_TREE_MODEL (prefs->header_list_store); - GtkTreePath *path = gtk_tree_path_new_from_string (path_string); - GtkTreeIter iter; - gint enabled; - - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_model_get (model, &iter, HEADER_LIST_ENABLED_COLUMN, &enabled, -1); - enabled = !enabled; - gtk_list_store_set (GTK_LIST_STORE (model), &iter, HEADER_LIST_ENABLED_COLUMN, - enabled, -1); - gtk_tree_path_free (path); - - emmp_save_headers (prefs); -} - -static void -emmp_header_add_header (GtkWidget *widget, EMMailerPrefs *prefs) -{ - GtkTreeModel *model = GTK_TREE_MODEL (prefs->header_list_store); - GtkTreeIter iter; - const gchar *text = gtk_entry_get_text (prefs->entry_header); - - g_strstrip ((gchar *)text); - - if (text && (strlen (text)>0)) { - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - HEADER_LIST_NAME_COLUMN, text, - HEADER_LIST_ENABLED_COLUMN, TRUE, - HEADER_LIST_HEADER_COLUMN, text, - HEADER_LIST_IS_DEFAULT_COLUMN, FALSE, - -1); - gtk_entry_set_text (prefs->entry_header, ""); - emmp_header_remove_sensitivity (prefs); - emmp_header_add_sensitivity (prefs); - - emmp_save_headers (prefs); - } -} - -static void -emmp_header_remove_header (GtkWidget *button, gpointer user_data) -{ - EMMailerPrefs *prefs = (EMMailerPrefs *) user_data; - GtkTreeModel *model = GTK_TREE_MODEL (prefs->header_list_store); - GtkTreeSelection *selection = gtk_tree_view_get_selection (prefs->header_list); - GtkTreeIter iter; - - if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) - return; - - gtk_list_store_remove (GTK_LIST_STORE (model), &iter); - emmp_header_remove_sensitivity (prefs); - - emmp_save_headers (prefs); -} - -static void -emmp_header_list_row_selected (GtkTreeSelection *selection, gpointer user_data) -{ - EMMailerPrefs *prefs = (EMMailerPrefs *) user_data; - - emmp_header_remove_sensitivity (prefs); -} - -static void -emmp_header_entry_changed (GtkWidget *entry, gpointer user_data) -{ - EMMailerPrefs *prefs = (EMMailerPrefs *) user_data; - - emmp_header_add_sensitivity (prefs); -} - -static void -toggle_button_toggled (GtkToggleButton *toggle, EMMailerPrefs *prefs) -{ - const gchar *key; - - key = g_object_get_data ((GObject *) toggle, "key"); - gconf_client_set_bool (prefs->gconf, key, gtk_toggle_button_get_active (toggle), NULL); -} - -static void -junk_book_lookup_button_toggled (GtkToggleButton *toggle, EMMailerPrefs *prefs) -{ - toggle_button_toggled (toggle, prefs); - gtk_widget_set_sensitive (GTK_WIDGET (prefs->junk_lookup_local_only), gtk_toggle_button_get_active (toggle)); -} - -static void -custom_junk_button_toggled (GtkToggleButton *toggle, EMMailerPrefs *prefs) -{ - toggle_button_toggled (toggle, prefs); - if (gtk_toggle_button_get_active (toggle)) { - gtk_widget_set_sensitive ((GtkWidget *) prefs->junk_header_remove, TRUE); - gtk_widget_set_sensitive ((GtkWidget *) prefs->junk_header_add, TRUE); - gtk_widget_set_sensitive ((GtkWidget *) prefs->junk_header_tree, TRUE); - } else { - gtk_widget_set_sensitive ((GtkWidget *) prefs->junk_header_tree, FALSE); - gtk_widget_set_sensitive ((GtkWidget *) prefs->junk_header_add, FALSE); - gtk_widget_set_sensitive ((GtkWidget *) prefs->junk_header_remove, FALSE); - } - - -} - -static void -toggle_button_init (EMMailerPrefs *prefs, GtkToggleButton *toggle, gint not, const gchar *key, GCallback toggled) -{ - gboolean bool; - - bool = gconf_client_get_bool (prefs->gconf, key, NULL); - gtk_toggle_button_set_active (toggle, not ? !bool : bool); - - if (toggled) { - g_object_set_data ((GObject *) toggle, "key", (gpointer) key); - g_signal_connect (toggle, "toggled", toggled, prefs); - } - - if (!gconf_client_key_is_writable (prefs->gconf, key, NULL)) - gtk_widget_set_sensitive ((GtkWidget *) toggle, FALSE); -} - -static void -charset_activate (GtkWidget *item, EMMailerPrefs *prefs) -{ - GtkWidget *menu; - gchar *string; - - menu = gtk_option_menu_get_menu (prefs->charset); - if (!(string = e_charset_picker_get_charset (menu))) - string = g_strdup (camel_iconv_locale_charset ()); - - gconf_client_set_string (prefs->gconf, "/apps/evolution/mail/display/charset", string, NULL); - g_free (string); -} - -static void -charset_menu_init (EMMailerPrefs *prefs) -{ - GtkWidget *menu, *item; - GList *items; - gchar *buf; - - buf = gconf_client_get_string (prefs->gconf, "/apps/evolution/mail/display/charset", NULL); - menu = e_charset_picker_new (buf && *buf ? buf : camel_iconv_locale_charset ()); - gtk_option_menu_set_menu (prefs->charset, GTK_WIDGET (menu)); - g_free (buf); - - items = GTK_MENU_SHELL (menu)->children; - while (items) { - item = items->data; - g_signal_connect (item, "activate", G_CALLBACK (charset_activate), prefs); - items = items->next; - } - - if (!gconf_client_key_is_writable (prefs->gconf, "/apps/evolution/mail/display/charset", NULL)) - gtk_widget_set_sensitive ((GtkWidget *) prefs->charset, FALSE); -} - -static void -trash_days_activate (GtkWidget *item, EMMailerPrefs *prefs) -{ - gint days; - - days = GPOINTER_TO_INT (g_object_get_data ((GObject *) item, "days")); - gconf_client_set_int (prefs->gconf, "/apps/evolution/mail/trash/empty_on_exit_days", days, NULL); -} - -static void -emmp_empty_trash_init (EMMailerPrefs *prefs) -{ - gint locked, days, hist = 0, i; - GtkWidget *menu, *item; - - days = gconf_client_get_int(prefs->gconf, "/apps/evolution/mail/trash/empty_on_exit_days", NULL); - menu = gtk_menu_new(); - for (i = 0; i < G_N_ELEMENTS (empty_trash_frequency); i++) { - if (days >= empty_trash_frequency[i].days) - hist = i; - - item = gtk_menu_item_new_with_label (_(empty_trash_frequency[i].label)); - g_object_set_data ((GObject *) item, "days", GINT_TO_POINTER (empty_trash_frequency[i].days)); - g_signal_connect (item, "activate", G_CALLBACK (trash_days_activate), prefs); - - gtk_widget_show (item); - gtk_menu_shell_append((GtkMenuShell *)menu, item); - } - - gtk_widget_show(menu); - gtk_option_menu_set_menu((GtkOptionMenu *)prefs->empty_trash_days, menu); - gtk_option_menu_set_history((GtkOptionMenu *)prefs->empty_trash_days, hist); - - locked = !gconf_client_key_is_writable (prefs->gconf, "/apps/evolution/mail/trash/empty_on_exit_days", NULL); - gtk_widget_set_sensitive ((GtkWidget *) prefs->empty_trash_days, !locked); -} - -static void -junk_days_activate (GtkWidget *item, EMMailerPrefs *prefs) -{ - gint days; - - days = GPOINTER_TO_INT (g_object_get_data ((GObject *) item, "days")); - gconf_client_set_int (prefs->gconf, "/apps/evolution/mail/junk/empty_on_exit_days", days, NULL); -} - -static void -emmp_empty_junk_init (EMMailerPrefs *prefs) -{ - gint locked, days, hist = 0, i; - GtkWidget *menu, *item; - - toggle_button_init (prefs, prefs->empty_junk, FALSE, - "/apps/evolution/mail/junk/empty_on_exit", - G_CALLBACK (toggle_button_toggled)); - - days = gconf_client_get_int(prefs->gconf, "/apps/evolution/mail/junk/empty_on_exit_days", NULL); - menu = gtk_menu_new(); - for (i = 0; i < G_N_ELEMENTS (empty_trash_frequency); i++) { - if (days >= empty_trash_frequency[i].days) - hist = i; - - item = gtk_menu_item_new_with_label (_(empty_trash_frequency[i].label)); - g_object_set_data ((GObject *) item, "days", GINT_TO_POINTER (empty_trash_frequency[i].days)); - g_signal_connect (item, "activate", G_CALLBACK (junk_days_activate), prefs); - - gtk_widget_show (item); - gtk_menu_shell_append((GtkMenuShell *)menu, item); - } - - gtk_widget_show(menu); - gtk_option_menu_set_menu((GtkOptionMenu *)prefs->empty_junk_days, menu); - gtk_option_menu_set_history((GtkOptionMenu *)prefs->empty_junk_days, hist); - - locked = !gconf_client_key_is_writable (prefs->gconf, "/apps/evolution/mail/junk/empty_on_exit_days", NULL); - gtk_widget_set_sensitive ((GtkWidget *) prefs->empty_junk_days, !locked); -} - -static void -http_images_changed (GtkWidget *widget, EMMailerPrefs *prefs) -{ - gint when; - - if (gtk_toggle_button_get_active (prefs->images_always)) - when = MAIL_CONFIG_HTTP_ALWAYS; - else if (gtk_toggle_button_get_active (prefs->images_sometimes)) - when = MAIL_CONFIG_HTTP_SOMETIMES; - else - when = MAIL_CONFIG_HTTP_NEVER; - - gconf_client_set_int (prefs->gconf, "/apps/evolution/mail/display/load_http_images", when, NULL); -} - - -static GtkWidget * -emmp_widget_glade(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - EMMailerPrefs *prefs = data; - - return glade_xml_get_widget(prefs->gui, item->label); -} - -/* plugin meta-data */ -static EMConfigItem emmp_items[] = { - { E_CONFIG_BOOK, (gchar *) "", (gchar *) "preferences_toplevel", emmp_widget_glade }, - { E_CONFIG_PAGE, (gchar *) "00.general", (gchar *) "vboxGeneral", emmp_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "00.general/00.fonts", (gchar *) "vboxMessageFonts", emmp_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "00.general/10.display", (gchar *) "vboxMessageDisplay", emmp_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "00.general/20.delete", (gchar *) "vboxDeletingMail", emmp_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "00.general/30.newmail", (gchar *) "vboxNewMailNotify", emmp_widget_glade }, - { E_CONFIG_PAGE, (gchar *) "10.html", (gchar *) "vboxHtmlMail", emmp_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "10.html/00.general", (gchar *) "vbox173", emmp_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "10.html/10.images", (gchar *) "vbox190", emmp_widget_glade }, - { E_CONFIG_PAGE, (gchar *) "20.labels", (gchar *) "frameColours", emmp_widget_glade }, - /* this is a table, so we can't use it { E_CONFIG_SECTION, "20.labels/00.labels", "tableColours", emmp_widget_glade }, */ - { E_CONFIG_PAGE, (gchar *) "30.headers", (gchar *) "vboxHeaderTab", emmp_widget_glade }, - /* no subvbox for section { E_CONFIG_PAGE, "30.headers/00.headers", "vbox199", emmp_widget_glade }, */ - { E_CONFIG_PAGE, (gchar *) "40.junk", (gchar *) "vbox161", emmp_widget_glade }, - /* no subvbox for section { E_CONFIG_SECTION, "40.junk/00.general", xxx, emmp_widget_glade } */ - { E_CONFIG_SECTION, (gchar *) "40.junk/10.options", (gchar *) "vbox204", emmp_widget_glade }, -}; - -static void -emmp_free(EConfig *ec, GSList *items, gpointer data) -{ - /* the prefs data is freed automagically */ - - g_slist_free(items); -} - -static void -junk_plugin_changed (GtkWidget *combo, EMMailerPrefs *prefs) -{ - gchar *def_plugin = gtk_combo_box_get_active_text(GTK_COMBO_BOX (combo)); - const GList *plugins = mail_session_get_junk_plugins(); - - gconf_client_set_string (prefs->gconf, "/apps/evolution/mail/junk/default_plugin", def_plugin, NULL); - while (plugins) { - struct _EMJunkHookItem *item = plugins->data;; - - if (item->plugin_name && def_plugin && !strcmp (item->plugin_name, def_plugin)) { - gboolean status; - - session->junk_plugin = CAMEL_JUNK_PLUGIN (&(item->csp)); - status = e_plugin_invoke (item->hook->hook.plugin, item->validate_binary, NULL) != NULL; - if ((gboolean)status == TRUE) { - gchar *text, *html; - gtk_image_set_from_stock (prefs->plugin_image, "gtk-dialog-info", GTK_ICON_SIZE_MENU); - text = g_strdup_printf (_("%s plugin is available and the binary is installed."), item->plugin_name); - html = g_strdup_printf ("%s", text); - gtk_label_set_markup (prefs->plugin_status, html); - g_free (html); - g_free (text); - } else { - gchar *text, *html; - gtk_image_set_from_stock (prefs->plugin_image, "gtk-dialog-warning", GTK_ICON_SIZE_MENU); - text = g_strdup_printf (_("%s plugin is not available. Please check whether the package is installed."), item->plugin_name); - html = g_strdup_printf ("%s", text); - gtk_label_set_markup (prefs->plugin_status, html); - g_free (html); - g_free (text); - } - break; - } - plugins = plugins->next; - } -} - -static void -junk_plugin_setup (GtkWidget *combo, EMMailerPrefs *prefs) -{ - gint index = 0; - gboolean def_set = FALSE; - const GList *plugins = mail_session_get_junk_plugins(); - gchar *pdefault = gconf_client_get_string (prefs->gconf, "/apps/evolution/mail/junk/default_plugin", NULL); - - if (!plugins || !g_list_length ((GList *)plugins)) { - gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("No Junk plugin available")); - gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0); - gtk_widget_set_sensitive (GTK_WIDGET (combo), FALSE); - gtk_widget_hide (GTK_WIDGET (prefs->plugin_image)); - gtk_widget_hide (GTK_WIDGET (prefs->plugin_status)); - gtk_image_set_from_stock (prefs->plugin_image, NULL, 0); - g_free (pdefault); - - return; - } - - while (plugins) { - struct _EMJunkHookItem *item = plugins->data;; - - gtk_combo_box_append_text (GTK_COMBO_BOX (combo), item->plugin_name); - if (!def_set && pdefault && item->plugin_name && !strcmp(pdefault, item->plugin_name)) { - gboolean status; - - def_set = TRUE; - gtk_combo_box_set_active (GTK_COMBO_BOX (combo), index); - status = e_plugin_invoke (item->hook->hook.plugin, item->validate_binary, NULL) != NULL; - if (status) { - gchar *text, *html; - gtk_image_set_from_stock (prefs->plugin_image, "gtk-dialog-info", GTK_ICON_SIZE_MENU); - /* May be a better text */ - text = g_strdup_printf (_("%s plugin is available and the binary is installed."), item->plugin_name); - html = g_strdup_printf ("%s", text); - gtk_label_set_markup (prefs->plugin_status, html); - g_free (html); - g_free (text); - } else { - gchar *text, *html; - gtk_image_set_from_stock (prefs->plugin_image, "gtk-dialog-warning", GTK_ICON_SIZE_MENU); - /* May be a better text */ - text = g_strdup_printf (_("%s plugin is not available. Please check whether the package is installed."), item->plugin_name); - html = g_strdup_printf ("%s", text); - gtk_label_set_markup (prefs->plugin_status, html); - g_free (html); - g_free (text); - } - } - plugins = plugins->next; - index++; - } - - g_signal_connect (combo, "changed", G_CALLBACK(junk_plugin_changed), prefs); - g_free (pdefault); -} - -GtkWidget * -create_combo_text_widget (void) { - return gtk_combo_box_new_text (); -} - -static void -em_mailer_prefs_construct (EMMailerPrefs *prefs, - EShell *shell) -{ - GSList *header_config_list, *header_add_list, *p; - EShellSettings *shell_settings; - GHashTable *default_header_hash; - GtkWidget *toplevel; - GtkWidget *container; - GtkWidget *widget; - GtkTreeSelection *selection; - GtkCellRenderer *renderer; - GtkTreeIter iter; - GladeXML *gui; - gboolean locked; - gint val, i; - EMConfig *ec; - EMConfigTargetPrefs *target; - GSList *l; - gchar *gladefile; - - shell_settings = e_shell_get_shell_settings (shell); - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - "mail-config.glade", - NULL); - gui = glade_xml_new (gladefile, "preferences_toplevel", NULL); - g_free (gladefile); - - prefs->gui = gui; - - /** @HookPoint-EMConfig: Mail Preferences Page - * @Id: org.gnome.evolution.mail.prefs - * @Type: E_CONFIG_BOOK - * @Class: org.gnome.evolution.mail.config:1.0 - * @Target: EMConfigTargetPrefs - * - * The main mail preferences page. - */ - ec = em_config_new(E_CONFIG_BOOK, "org.gnome.evolution.mail.prefs"); - l = NULL; - for (i=0;itimeout = GTK_SPIN_BUTTON (widget); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-mark-seen", - G_OBJECT (widget), "sensitive"); - e_mutual_binding_new_full ( - G_OBJECT (shell_settings), "mail-mark-seen-timeout", - G_OBJECT (widget), "value", - mark_seen_timeout_transform, - mark_seen_timeout_reverse_transform, - NULL, NULL); - - widget = glade_xml_get_widget (gui, "mlimit_checkbutton"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-force-message-limit", - G_OBJECT (widget), "active"); - - widget = glade_xml_get_widget (gui, "mlimit_spin"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-force-message-limit", - G_OBJECT (widget), "sensitive"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-message-text-part-limit", - G_OBJECT (widget), "value"); - - widget = glade_xml_get_widget (gui, "address_checkbox"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-address-compress", - G_OBJECT (widget), "active"); - - widget = glade_xml_get_widget (gui, "address_spin"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-address-compress", - G_OBJECT (widget), "sensitive"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-address-count", - G_OBJECT (widget), "value"); - - widget = glade_xml_get_widget (gui, "magic_spacebar_checkbox"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-magic-spacebar", - G_OBJECT (widget), "active"); - - prefs->charset = GTK_OPTION_MENU (glade_xml_get_widget (gui, "omenuCharset")); - charset_menu_init (prefs); - - widget = glade_xml_get_widget (gui, "chkHighlightCitations"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-mark-citations", - G_OBJECT (widget), "active"); - - widget = glade_xml_get_widget (gui, "colorButtonHighlightCitations"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-mark-citations", - G_OBJECT (widget), "sensitive"); - e_mutual_binding_new_full ( - G_OBJECT (shell_settings), "mail-citation-color", - G_OBJECT (widget), "color", - e_binding_transform_string_to_color, - e_binding_transform_color_to_string, - NULL, NULL); - - widget = glade_xml_get_widget (gui, "chkEnableSearchFolders"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-enable-search-folders", - G_OBJECT (widget), "active"); - - /* Deleting Mail */ - widget = glade_xml_get_widget (gui, "chkEmptyTrashOnExit"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-empty-trash-on-exit", - G_OBJECT (widget), "active"); - - prefs->empty_trash_days = GTK_OPTION_MENU (glade_xml_get_widget (gui, "omenuEmptyTrashDays")); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-empty-trash-on-exit", - G_OBJECT (prefs->empty_trash_days), "sensitive"); - emmp_empty_trash_init (prefs); - - widget = glade_xml_get_widget (gui, "chkConfirmExpunge"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-confirm-expunge", - G_OBJECT (widget), "active"); - - /* Mail Fonts */ - widget = glade_xml_get_widget (gui, "radFontUseSame"); - e_mutual_binding_new_with_negation ( - G_OBJECT (shell_settings), "mail-use-custom-fonts", - G_OBJECT (widget), "active"); - - widget = glade_xml_get_widget (gui, "FontFixed"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-font-monospace", - G_OBJECT (widget), "font-name"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-use-custom-fonts", - G_OBJECT (widget), "sensitive"); - - widget = glade_xml_get_widget (gui, "FontVariable"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-font-variable", - G_OBJECT (widget), "font-name"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-use-custom-fonts", - G_OBJECT (widget), "sensitive"); - - /* HTML Mail tab */ - - /* Loading Images */ - locked = !gconf_client_key_is_writable (prefs->gconf, "/apps/evolution/mail/display/load_http_images", NULL); - - val = gconf_client_get_int (prefs->gconf, "/apps/evolution/mail/display/load_http_images", NULL); - prefs->images_never = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "radImagesNever")); - gtk_toggle_button_set_active (prefs->images_never, val == MAIL_CONFIG_HTTP_NEVER); - if (locked) - gtk_widget_set_sensitive ((GtkWidget *) prefs->images_never, FALSE); - - prefs->images_sometimes = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "radImagesSometimes")); - gtk_toggle_button_set_active (prefs->images_sometimes, val == MAIL_CONFIG_HTTP_SOMETIMES); - if (locked) - gtk_widget_set_sensitive ((GtkWidget *) prefs->images_sometimes, FALSE); - - prefs->images_always = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "radImagesAlways")); - gtk_toggle_button_set_active (prefs->images_always, val == MAIL_CONFIG_HTTP_ALWAYS); - if (locked) - gtk_widget_set_sensitive ((GtkWidget *) prefs->images_always, FALSE); - - g_signal_connect (prefs->images_never, "toggled", G_CALLBACK (http_images_changed), prefs); - g_signal_connect (prefs->images_sometimes, "toggled", G_CALLBACK (http_images_changed), prefs); - g_signal_connect (prefs->images_always, "toggled", G_CALLBACK (http_images_changed), prefs); - - widget = glade_xml_get_widget (gui, "chkShowAnimatedImages"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-show-animated-images", - G_OBJECT (widget), "active"); - - widget = glade_xml_get_widget (gui, "chkPromptWantHTML"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-confirm-unwanted-html", - G_OBJECT (widget), "active"); - - container = glade_xml_get_widget (gui, "labels-alignment"); - widget = e_mail_label_manager_new (); - gtk_container_add (GTK_CONTAINER (container), widget); - gtk_widget_show (widget); - - e_binding_new ( - G_OBJECT (shell_settings), "mail-label-list-store", - G_OBJECT (widget), "list-store"); - - /* headers */ - locked = !gconf_client_key_is_writable (prefs->gconf, "/apps/evolution/mail/display/headers", NULL); - - widget = glade_xml_get_widget (gui, "photo_show"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-show-sender-photo", - G_OBJECT (widget), "active"); - - widget = glade_xml_get_widget (gui, "photo_local"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-show-sender-photo", - G_OBJECT (widget), "sensitive"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-only-local-photos", - G_OBJECT (widget), "active"); - - /* always de-sensitised until the user types something in the entry */ - prefs->add_header = GTK_BUTTON (glade_xml_get_widget (gui, "cmdHeadersAdd")); - gtk_widget_set_sensitive ((GtkWidget *) prefs->add_header, FALSE); - - /* always de-sensitised until the user selects a header in the list */ - prefs->remove_header = GTK_BUTTON (glade_xml_get_widget (gui, "cmdHeadersRemove")); - gtk_widget_set_sensitive ((GtkWidget *) prefs->remove_header, FALSE); - - prefs->entry_header = GTK_ENTRY (glade_xml_get_widget (gui, "txtHeaders")); - gtk_widget_set_sensitive ((GtkWidget *) prefs->entry_header, !locked); - - prefs->header_list = GTK_TREE_VIEW (glade_xml_get_widget (gui, "treeHeaders")); - gtk_widget_set_sensitive ((GtkWidget *) prefs->header_list, !locked); - - selection = gtk_tree_view_get_selection (prefs->header_list); - g_signal_connect (selection, "changed", G_CALLBACK (emmp_header_list_row_selected), prefs); - g_signal_connect (prefs->entry_header, "changed", G_CALLBACK (emmp_header_entry_changed), prefs); - g_signal_connect (prefs->entry_header, "activate", G_CALLBACK (emmp_header_add_header), prefs); - /* initialise the tree with appropriate headings */ - prefs->header_list_store = gtk_list_store_newv (HEADER_LIST_N_COLUMNS, col_types); - g_signal_connect (prefs->add_header, "clicked", G_CALLBACK (emmp_header_add_header), prefs); - g_signal_connect (prefs->remove_header, "clicked", G_CALLBACK (emmp_header_remove_header), prefs); - gtk_tree_view_set_model (prefs->header_list, GTK_TREE_MODEL (prefs->header_list_store)); - - renderer = gtk_cell_renderer_toggle_new (); - g_object_set (renderer, "activatable", TRUE, NULL); - g_signal_connect (renderer, "toggled", G_CALLBACK (emmp_header_list_enabled_toggled), prefs); - gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (prefs->header_list), -1, - "Enabled", renderer, - "active", HEADER_LIST_ENABLED_COLUMN, - NULL); - renderer = gtk_cell_renderer_text_new (); - gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (prefs->header_list), -1, - "Name", renderer, - "text", HEADER_LIST_NAME_COLUMN, - NULL); - - /* populated the listview with entries; firstly we add all the default headers, and then - we add read header configuration out of gconf. If a header in gconf is a default header, - we update the enabled flag accordingly - */ - header_add_list = NULL; - default_header_hash = g_hash_table_new (g_str_hash, g_str_equal); - for (i = 0; i < G_N_ELEMENTS (default_headers); i++) { - struct _EMMailerPrefsHeader *h; - - h = g_malloc (sizeof (struct _EMMailerPrefsHeader)); - h->is_default = TRUE; - h->name = g_strdup (default_headers[i]); - h->enabled = strcmp ((gchar *)default_headers[i], "x-evolution-mailer") != 0; - g_hash_table_insert (default_header_hash, (gpointer) default_headers[i], h); - header_add_list = g_slist_append (header_add_list, h); - } - - /* read stored headers from gconf */ - header_config_list = gconf_client_get_list (prefs->gconf, "/apps/evolution/mail/display/headers", GCONF_VALUE_STRING, NULL); - p = header_config_list; - while (p) { - struct _EMMailerPrefsHeader *h, *def; - gchar *xml = (gchar *) p->data; - - h = em_mailer_prefs_header_from_xml (xml); - if (h) { - def = g_hash_table_lookup (default_header_hash, h->name); - if (def) { - def->enabled = h->enabled; - em_mailer_prefs_header_free (h); - } else { - h->is_default = FALSE; - header_add_list = g_slist_append (header_add_list, h); - } - } - - p = p->next; - } - - g_hash_table_destroy (default_header_hash); - g_slist_foreach (header_config_list, (GFunc) g_free, NULL); - g_slist_free (header_config_list); - - p = header_add_list; - while (p) { - struct _EMMailerPrefsHeader *h = (struct _EMMailerPrefsHeader *) p->data; - const gchar *name; - - if (g_ascii_strcasecmp (h->name, EM_FORMAT_HEADER_XMAILER) == 0) - name = _("Mailer"); - else - name = _(h->name); - - gtk_list_store_append (prefs->header_list_store, &iter); - gtk_list_store_set (prefs->header_list_store, &iter, - HEADER_LIST_NAME_COLUMN, name, - HEADER_LIST_ENABLED_COLUMN, h->enabled, - HEADER_LIST_IS_DEFAULT_COLUMN, h->is_default, - HEADER_LIST_HEADER_COLUMN, h->name, - -1); - - em_mailer_prefs_header_free (h); - p = p->next; - } - - g_slist_free (header_add_list); - - /* Junk prefs */ - widget = glade_xml_get_widget (gui, "chkCheckIncomingMail"); - e_mutual_binding_new ( - G_OBJECT (shell_settings), "mail-check-for-junk", - G_OBJECT (widget), "active"); - - prefs->empty_junk = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "junk_empty_check")); - prefs->empty_junk_days = GTK_OPTION_MENU (glade_xml_get_widget (gui, "junk_empty_combo")); - emmp_empty_junk_init (prefs); - - prefs->default_junk_plugin = GTK_COMBO_BOX (glade_xml_get_widget (gui, "default_junk_plugin")); - prefs->plugin_status = GTK_LABEL (glade_xml_get_widget (gui, "plugin_status")); - prefs->plugin_image = GTK_IMAGE (glade_xml_get_widget (gui, "plugin_image")); - junk_plugin_setup (GTK_WIDGET (prefs->default_junk_plugin), prefs); - - prefs->junk_header_check = (GtkToggleButton *)glade_xml_get_widget (gui, "junk_header_check"); - prefs->junk_header_tree = (GtkTreeView *)glade_xml_get_widget (gui, "junk_header_tree"); - prefs->junk_header_add = (GtkButton *)glade_xml_get_widget (gui, "junk_header_add"); - prefs->junk_header_remove = (GtkButton *)glade_xml_get_widget (gui, "junk_header_remove"); - prefs->junk_book_lookup = (GtkToggleButton *)glade_xml_get_widget (gui, "lookup_book"); - prefs->junk_lookup_local_only = (GtkToggleButton *)glade_xml_get_widget (gui, "junk_lookup_local_only"); - toggle_button_init (prefs, prefs->junk_book_lookup, FALSE, - "/apps/evolution/mail/junk/lookup_addressbook", - G_CALLBACK (junk_book_lookup_button_toggled)); - - toggle_button_init (prefs, prefs->junk_lookup_local_only, FALSE, - "/apps/evolution/mail/junk/lookup_addressbook_local_only", - G_CALLBACK (toggle_button_toggled)); - - junk_book_lookup_button_toggled (prefs->junk_book_lookup, prefs); - - prefs->junk_header_list_store = init_junk_tree ((GtkWidget *)prefs->junk_header_tree, prefs); - toggle_button_init (prefs, prefs->junk_header_check, FALSE, - "/apps/evolution/mail/junk/check_custom_header", - G_CALLBACK (custom_junk_button_toggled)); - - custom_junk_button_toggled (prefs->junk_header_check, prefs); - jh_tree_refill (prefs); - g_signal_connect (G_OBJECT (prefs->junk_header_add), "clicked", G_CALLBACK (jh_add_cb), prefs); - g_signal_connect (G_OBJECT (prefs->junk_header_remove), "clicked", G_CALLBACK (jh_remove_cb), prefs); - - /* get our toplevel widget */ - target = em_config_target_new_prefs(ec, prefs->gconf); - e_config_set_target((EConfig *)ec, (EConfigTarget *)target); - toplevel = e_config_create_widget((EConfig *)ec); - gtk_container_add (GTK_CONTAINER (prefs), toplevel); -} - -GtkWidget * -em_mailer_prefs_new (EShell *shell) -{ - EMMailerPrefs *new; - - g_return_val_if_fail (E_IS_SHELL (shell), NULL); - - new = g_object_new (EM_TYPE_MAILER_PREFS, NULL); - - /* FIXME Kill this function. */ - em_mailer_prefs_construct (new, shell); - - return GTK_WIDGET (new); -} - - -static struct _EMMailerPrefsHeader * -emmp_header_from_xmldoc (xmlDocPtr doc) -{ - struct _EMMailerPrefsHeader *h; - xmlNodePtr root; - xmlChar *name; - - if (doc == NULL) - return NULL; - - root = doc->children; - if (strcmp ((gchar *)root->name, "header") != 0) - return NULL; - - name = xmlGetProp (root, (const guchar *)"name"); - if (name == NULL) - return NULL; - - h = g_malloc0 (sizeof (struct _EMMailerPrefsHeader)); - h->name = g_strdup ((gchar *)name); - xmlFree (name); - - if (xmlHasProp (root, (const guchar *)"enabled")) - h->enabled = 1; - else - h->enabled = 0; - - return h; -} - -/** - * em_mailer_prefs_header_from_xml - * @xml: XML configuration data - * - * Parses passed XML data, which should be of - * the format
, and - * returns a EMMailerPrefs structure, or NULL if there - * is an error. - **/ -struct _EMMailerPrefsHeader * -em_mailer_prefs_header_from_xml (const gchar *xml) -{ - struct _EMMailerPrefsHeader *header; - xmlDocPtr doc; - - if (!(doc = xmlParseDoc ((guchar *) xml))) - return NULL; - - header = emmp_header_from_xmldoc (doc); - xmlFreeDoc (doc); - - return header; -} - -/** - * em_mailer_prefs_header_free - * @header: header to free - * - * Frees the memory associated with the passed header - * structure. - */ -void -em_mailer_prefs_header_free (struct _EMMailerPrefsHeader *header) -{ - if (header == NULL) - return; - - g_free (header->name); - g_free (header); -} - -/** - * em_mailer_prefs_header_to_xml - * @header: header from which to generate XML - * - * Returns the passed header as a XML structure, - * or NULL on error - */ -gchar * -em_mailer_prefs_header_to_xml (struct _EMMailerPrefsHeader *header) -{ - xmlDocPtr doc; - xmlNodePtr root; - xmlChar *xml; - gchar *out; - gint size; - - g_return_val_if_fail (header != NULL, NULL); - g_return_val_if_fail (header->name != NULL, NULL); - - doc = xmlNewDoc ((const guchar *)"1.0"); - - root = xmlNewDocNode (doc, NULL, (const guchar *)"header", NULL); - xmlSetProp (root, (const guchar *)"name", (guchar *)header->name); - if (header->enabled) - xmlSetProp (root, (const guchar *)"enabled", NULL); - - xmlDocSetRootElement (doc, root); - xmlDocDumpMemory (doc, &xml, &size); - xmlFreeDoc (doc); - - out = g_malloc (size + 1); - memcpy (out, xml, size); - out[size] = '\0'; - xmlFree (xml); - - return out; -} diff --git a/mail/em-mailer-prefs.h b/mail/em-mailer-prefs.h deleted file mode 100644 index b33e620392..0000000000 --- a/mail/em-mailer-prefs.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Jeffrey Stedfast - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef EM_MAILER_PREFS_H -#define EM_MAILER_PREFS_H - -#include -#include -#include -#include - -/* Standard GObject macros */ -#define EM_TYPE_MAILER_PREFS \ - (em_mailer_prefs_get_type ()) -#define EM_MAILER_PREFS(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), EM_TYPE_MAILER_PREFS, EMMailerPrefs)) -#define EM_MAILER_PREFS_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), EM_TYPE_MAILER_PREFS, EMMailerPrefsClass)) -#define EM_IS_MAILER_PREFS(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), EM_TYPE_MAILER_PREFS)) -#define EM_IS_MAILER_PREFS_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), EM_TYPE_MAILER_PREFS)) -#define EM_MAILER_PREFS_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), EM_TYPE_MAILER_PREFS)) - -G_BEGIN_DECLS - -typedef struct _EMMailerPrefs EMMailerPrefs; -typedef struct _EMMailerPrefsClass EMMailerPrefsClass; -typedef struct _EMMailerPrefsHeader EMMailerPrefsHeader; - -struct _EMMailerPrefsHeader { - gchar *name; - guint enabled:1; - guint is_default:1; -}; - -struct _EMMailerPrefs { - GtkVBox parent_object; - - GladeXML *gui; - GConfClient *gconf; - - /* General tab */ - - /* Message Display */ - GtkSpinButton *timeout; - GtkOptionMenu *charset; - - /* Deleting Mail */ - GtkToggleButton *empty_trash; - GtkComboBox *empty_trash_days; - GtkToggleButton *confirm_expunge; - - /* HTML Mail tab */ - GtkFontButton *font_variable; - GtkFontButton *font_fixed; - GtkToggleButton *font_share; - - /* Loading Images */ - GtkToggleButton *images_always; - GtkToggleButton *images_sometimes; - GtkToggleButton *images_never; - - GtkToggleButton *autodetect_links; - - /* Labels and Colours tab */ - GtkWidget *label_add; - GtkWidget *label_edit; - GtkWidget *label_remove; - GtkWidget *label_tree; - GtkListStore *label_list_store; - guint labels_change_notify_id; /* mail_config's notify id */ - - /* Headers tab */ - GtkButton *add_header; - GtkButton *remove_header; - GtkEntry *entry_header; - GtkTreeView *header_list; - GtkListStore *header_list_store; - - /* Junk prefs */ - GtkToggleButton *empty_junk; - GtkComboBox *empty_junk_days; - - GtkToggleButton *sa_local_tests_only; - GtkToggleButton *sa_use_daemon; - GtkComboBox *default_junk_plugin; - GtkLabel *plugin_status; - GtkImage *plugin_image; - - GtkToggleButton *junk_header_check; - GtkTreeView *junk_header_tree; - GtkListStore *junk_header_list_store; - GtkButton *junk_header_add; - GtkButton *junk_header_remove; - GtkToggleButton *junk_book_lookup; - GtkToggleButton *junk_lookup_local_only; -}; - -struct _EMMailerPrefsClass { - GtkVBoxClass parent_class; -}; - -GType em_mailer_prefs_get_type (void); -GtkWidget * create_combo_text_widget (void); - -GtkWidget * em_mailer_prefs_new (EShell *shell); - -EMMailerPrefsHeader * - em_mailer_prefs_header_from_xml (const gchar *xml); -gchar * em_mailer_prefs_header_to_xml (EMMailerPrefsHeader *header); -void em_mailer_prefs_header_free (EMMailerPrefsHeader *header); - -G_END_DECLS - -#endif /* EM_MAILER_PREFS_H */ diff --git a/mail/em-network-prefs.c b/mail/em-network-prefs.c deleted file mode 100644 index e530d4d076..0000000000 --- a/mail/em-network-prefs.c +++ /dev/null @@ -1,499 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Veerapuram Varadhan - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "em-network-prefs.h" - -#include -#include -#include - -#include - -#include "e-util/e-error.h" -#include "e-util/e-util-private.h" - -#include "mail-config.h" -#include "em-config.h" - -#define d(x) - -#define GCONF_E_SHELL_NETWORK_CONFIG_PATH "/apps/evolution/shell/network_config/" -#define GCONF_E_HTTP_HOST_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "http_host" -#define GCONF_E_HTTP_PORT_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "http_port" -#define GCONF_E_HTTPS_HOST_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "secure_host" -#define GCONF_E_HTTPS_PORT_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "secure_port" -#define GCONF_E_SOCKS_HOST_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "socks_host" -#define GCONF_E_SOCKS_PORT_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "socks_port" -#define GCONF_E_IGNORE_HOSTS_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "ignore_hosts" -#define GCONF_E_USE_AUTH_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "use_authentication" -#define GCONF_E_PROXY_TYPE_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "proxy_type" -#define GCONF_E_AUTH_USER_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "authentication_user" -#define GCONF_E_AUTH_PWD_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "authentication_password" -#define GCONF_E_USE_PROXY_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "use_http_proxy" -#define GCONF_E_AUTOCONFIG_URL_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "autoconfig_url" - -static void em_network_prefs_class_init (EMNetworkPrefsClass *class); -static void em_network_prefs_init (EMNetworkPrefs *dialog); -static void em_network_prefs_destroy (GtkObject *obj); -static void em_network_prefs_finalise (GObject *obj); - - -static GtkVBoxClass *parent_class = NULL; - - -GType -em_network_prefs_get_type (void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof (EMNetworkPrefsClass), - NULL, NULL, - (GClassInitFunc) em_network_prefs_class_init, - NULL, NULL, - sizeof (EMNetworkPrefs), - 0, - (GInstanceInitFunc) em_network_prefs_init, - }; - - type = g_type_register_static (gtk_vbox_get_type (), "EMNetworkPrefs", &info, 0); - } - - return type; -} - -static void -em_network_prefs_class_init (EMNetworkPrefsClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); - - parent_class = g_type_class_ref (gtk_vbox_get_type ()); - - object_class->destroy = em_network_prefs_destroy; - gobject_class->finalize = em_network_prefs_finalise; -} - -static void -em_network_prefs_init (EMNetworkPrefs *prefs) -{ - /* do something here */ -} - -static void -em_network_prefs_finalise (GObject *obj) -{ - d(g_print ("Network preferences finalize is called\n")); - - /* do something here */ - G_OBJECT_CLASS (parent_class)->finalize (obj); -} - -static void -em_network_prefs_destroy (GtkObject *obj) -{ - d(g_print ("Network preferences destroy is called\n")); - - GTK_OBJECT_CLASS (parent_class)->destroy (obj); -} - -static void -toggle_button_toggled (GtkToggleButton *toggle, EMNetworkPrefs *prefs) -{ - const gchar *key; - - key = g_object_get_data ((GObject *) toggle, "key"); - gconf_client_set_bool (prefs->gconf, key, gtk_toggle_button_get_active (toggle), NULL); - if (toggle == prefs->use_auth) { - gboolean sensitivity = gtk_toggle_button_get_active (prefs->use_auth); - gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_auth_user, sensitivity); - gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_auth_pwd, sensitivity); - gtk_widget_set_sensitive ((GtkWidget *) prefs->auth_user, sensitivity); - gtk_widget_set_sensitive ((GtkWidget *) prefs->auth_pwd, sensitivity); - } -} - -static void -toggle_button_init (EMNetworkPrefs *prefs, GtkToggleButton *toggle, const gchar *key) -{ - gboolean bool; - - bool = gconf_client_get_bool (prefs->gconf, key, NULL); - gtk_toggle_button_set_active (toggle, bool); - - g_object_set_data ((GObject *) toggle, "key", (gpointer) key); - g_signal_connect (toggle, "toggled", G_CALLBACK (toggle_button_toggled), prefs); - - if (!gconf_client_key_is_writable (prefs->gconf, key, NULL)) - gtk_widget_set_sensitive ((GtkWidget *) toggle, FALSE); -} - -static GtkWidget * -emnp_widget_glade(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - EMNetworkPrefs *prefs = data; - - return glade_xml_get_widget(prefs->gui, item->label); -} - -static void -emnp_set_sensitiveness (EMNetworkPrefs *prefs, NetworkConfigProxyType type, gboolean sensitivity) -{ -#if 0 - if (type == NETWORK_PROXY_AUTOCONFIG) { - gtk_widget_set_sensitive ((GtkWidget *) prefs->auto_proxy_url, sensitivity); - d(g_print ("Setting sensitivity of autoconfig to: %d\n", sensitivity)); - } else -#endif - if (type == NETWORK_PROXY_MANUAL) { - gboolean state; - - gtk_widget_set_sensitive ((GtkWidget *) prefs->http_host, sensitivity); - gtk_widget_set_sensitive ((GtkWidget *) prefs->https_host, sensitivity); - gtk_widget_set_sensitive ((GtkWidget *) prefs->ignore_hosts, sensitivity); - gtk_widget_set_sensitive ((GtkWidget *) prefs->use_auth, sensitivity); - gtk_widget_set_sensitive ((GtkWidget *) prefs->http_port, sensitivity); - gtk_widget_set_sensitive ((GtkWidget *) prefs->https_port, sensitivity); - gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_ignore_hosts, sensitivity); - gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_http_host, sensitivity); - gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_http_port, sensitivity); - gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_https_host, sensitivity); - gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_https_port, sensitivity); -#if 0 - gtk_widget_set_sensitive ((GtkWidget *) prefs->socks_host, sensitivity); - gtk_widget_set_sensitive ((GtkWidget *) prefs->socks_port, sensitivity); - gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_socks_host, sensitivity); - gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_socks_port, sensitivity); -#endif - state = sensitivity && gtk_toggle_button_get_active (prefs->use_auth); - gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_auth_user, state); - gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_auth_pwd, state); - gtk_widget_set_sensitive ((GtkWidget *) prefs->auth_user, state); - gtk_widget_set_sensitive ((GtkWidget *) prefs->auth_pwd, state); - - d(g_print ("Setting sensitivity of manual proxy to: %d\n", sensitivity)); - } -} - -static void -notify_proxy_type_changed (GtkWidget *widget, EMNetworkPrefs *prefs) -{ - gint type; - - if (gtk_toggle_button_get_active (prefs->sys_proxy)) - type = NETWORK_PROXY_SYS_SETTINGS; - else if (gtk_toggle_button_get_active (prefs->no_proxy)) - type = NETWORK_PROXY_DIRECT_CONNECTION; - else if (gtk_toggle_button_get_active (prefs->manual_proxy)) - type = NETWORK_PROXY_MANUAL; - else -#if 0 - type = NETWORK_PROXY_AUTOCONFIG; -#else - type = NETWORK_PROXY_SYS_SETTINGS; -#endif - - gconf_client_set_int (prefs->gconf, "/apps/evolution/shell/network_config/proxy_type", type, NULL); - - if (type == NETWORK_PROXY_DIRECT_CONNECTION || - type == NETWORK_PROXY_SYS_SETTINGS) { - emnp_set_sensitiveness (prefs, NETWORK_PROXY_MANUAL, FALSE); - emnp_set_sensitiveness (prefs, NETWORK_PROXY_AUTOCONFIG, FALSE); - } else if (type == NETWORK_PROXY_AUTOCONFIG) { - emnp_set_sensitiveness (prefs, NETWORK_PROXY_MANUAL, FALSE); - emnp_set_sensitiveness (prefs, NETWORK_PROXY_AUTOCONFIG, TRUE); - } else if (type == NETWORK_PROXY_MANUAL) { - emnp_set_sensitiveness (prefs, NETWORK_PROXY_AUTOCONFIG, FALSE); - emnp_set_sensitiveness (prefs, NETWORK_PROXY_MANUAL, TRUE); - } - - if (type != NETWORK_PROXY_DIRECT_CONNECTION) - gconf_client_set_bool (prefs->gconf, GCONF_E_USE_PROXY_KEY, TRUE, NULL); - else if (type != NETWORK_PROXY_SYS_SETTINGS) - gconf_client_set_bool (prefs->gconf, GCONF_E_USE_PROXY_KEY, FALSE, NULL); - -} - -static void -widget_entry_changed_cb (GtkWidget *widget, gpointer data) -{ - const gchar *value; - gint port = -1; - GConfClient *gconf = mail_config_get_gconf_client (); - - /* - Do not change the order of comparison - - GtkSpinButton is an extended form of GtkEntry - */ - if (GTK_IS_SPIN_BUTTON (widget)) { - port = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget)); - gconf_client_set_int (gconf, (const gchar *)data, port, NULL); - d(g_print ("%s:%s: %s is SpinButton: value = [%d]\n", G_STRLOC, G_STRFUNC, (const gchar *)data, port)); - } else if (GTK_IS_ENTRY (widget)) { - value = gtk_entry_get_text (GTK_ENTRY (widget)); - gconf_client_set_string (gconf, (const gchar *)data, value, NULL); - d(g_print ("%s:%s: %s is Entry: value = [%s]\n", G_STRLOC, G_STRFUNC, (const gchar *)data, value)); - } - -} - -/* plugin meta-data */ -static EMConfigItem emnp_items[] = { - { E_CONFIG_BOOK, (gchar *) "", (gchar *) "network_preferences_toplevel", emnp_widget_glade }, - { E_CONFIG_PAGE, (gchar *) "00.general", (gchar *) "vboxGeneral", emnp_widget_glade }, - { E_CONFIG_SECTION, (gchar *) "00.general/00.proxy", (gchar *) "frameProxy", emnp_widget_glade }, -}; - -static void -emnp_free(EConfig *ec, GSList *items, gpointer data) -{ - /* the prefs data is freed automagically */ - - g_slist_free(items); -} - -static void -emnp_set_markups (EMNetworkPrefs *prefs) -{ - gtk_label_set_use_markup (GTK_LABEL (GTK_BIN(prefs->sys_proxy)->child), TRUE); - gtk_label_set_use_markup (GTK_LABEL (GTK_BIN(prefs->no_proxy)->child), TRUE); - gtk_label_set_use_markup (GTK_LABEL (GTK_BIN(prefs->manual_proxy)->child), TRUE); -#if 0 - gtk_label_set_use_markup (GTK_LABEL (GTK_BIN(prefs->auto_proxy)->child), TRUE); -#endif -} - -static void -em_network_prefs_construct (EMNetworkPrefs *prefs) -{ - GtkWidget *toplevel; - GladeXML *gui; - GSList* l; - gchar *buf; - EMConfig *ec; - EMConfigTargetPrefs *target; - gboolean locked; - gint i, val, port; - gchar *gladefile; - - prefs->gconf = mail_config_get_gconf_client (); - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - "mail-config.glade", - NULL); - gui = glade_xml_new (gladefile, "network_preferences_toplevel", NULL); - prefs->gui = gui; - g_free (gladefile); - - /** @HookPoint-EMConfig: Network Preferences - * @Id: org.gnome.evolution.mail.networkPrefs - * @Type: E_CONFIG_BOOK - * @Class: org.gnome.evolution.mail.config:1.0 - * @Target: EMConfigTargetPrefs - * - * The network preferences settings page. - */ - ec = em_config_new(E_CONFIG_BOOK, "org.gnome.evolution.mail.networkPrefs"); - l = NULL; - for (i=0;igconf, GCONF_E_PROXY_TYPE_KEY, NULL); - - val = gconf_client_get_int (prefs->gconf, GCONF_E_PROXY_TYPE_KEY, NULL); - - /* no auto-proxy at the moment */ - if (val == NETWORK_PROXY_AUTOCONFIG) - val = NETWORK_PROXY_SYS_SETTINGS; - - prefs->sys_proxy = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "rdoSysSettings")); - gtk_toggle_button_set_active (prefs->sys_proxy, val == NETWORK_PROXY_SYS_SETTINGS); - if (locked) - gtk_widget_set_sensitive ((GtkWidget *) prefs->sys_proxy, FALSE); - - d(g_print ("Sys settings ----!!! \n")); - - prefs->no_proxy = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "rdoNoProxy")); - gtk_toggle_button_set_active (prefs->no_proxy, val == NETWORK_PROXY_DIRECT_CONNECTION); - if (locked) - gtk_widget_set_sensitive ((GtkWidget *) prefs->no_proxy, FALSE); - - d(g_print ("No proxy settings ----!!! \n")); - - /* no auto-proxy at the moment */ -#if 0 - prefs->auto_proxy = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "rdoAutoConfig")); - prefs->auto_proxy_url = GTK_ENTRY (glade_xml_get_widget (gui, "txtAutoConfigUrl")); - - gtk_toggle_button_set_active (prefs->auto_proxy, val == NETWORK_PROXY_AUTOCONFIG); - - g_signal_connect(prefs->auto_proxy_url, "changed", G_CALLBACK(widget_entry_changed_cb), GCONF_E_AUTOCONFIG_URL_KEY); - if (locked) - gtk_widget_set_sensitive ((GtkWidget *) prefs->auto_proxy, FALSE); -#endif - - d(g_print ("Auto config settings ----!!! \n")); - - prefs->manual_proxy = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "rdoManualProxy")); - prefs->http_host = GTK_ENTRY (glade_xml_get_widget (gui, "txtHttpHost")); - prefs->https_host = GTK_ENTRY (glade_xml_get_widget (gui, "txtHttpsHost")); - prefs->ignore_hosts = GTK_ENTRY (glade_xml_get_widget (gui, "txtIgnoreHosts")); - prefs->http_port = GTK_SPIN_BUTTON (glade_xml_get_widget (gui, "spnHttpPort")); - prefs->https_port = GTK_SPIN_BUTTON (glade_xml_get_widget (gui, "spnHttpsPort")); - prefs->lbl_http_host = GTK_LABEL (glade_xml_get_widget (gui, "lblHttpHost")); - prefs->lbl_http_port = GTK_LABEL (glade_xml_get_widget (gui, "lblHttpPort")); - prefs->lbl_https_host = GTK_LABEL (glade_xml_get_widget (gui, "lblHttpsHost")); - prefs->lbl_https_port = GTK_LABEL (glade_xml_get_widget (gui, "lblHttpsPort")); - prefs->lbl_ignore_hosts = GTK_LABEL (glade_xml_get_widget (gui, "lblIgnoreHosts")); - prefs->use_auth = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "chkUseAuth")); - toggle_button_init (prefs, prefs->use_auth, GCONF_E_USE_AUTH_KEY); - prefs->lbl_auth_user = GTK_LABEL (glade_xml_get_widget (gui, "lblAuthUser")); - prefs->lbl_auth_pwd = GTK_LABEL (glade_xml_get_widget (gui, "lblAuthPwd")); - prefs->auth_user = GTK_ENTRY (glade_xml_get_widget (gui, "txtAuthUser")); - prefs->auth_pwd = GTK_ENTRY (glade_xml_get_widget (gui, "txtAuthPwd")); - -#if 0 - prefs->socks_host = GTK_ENTRY (glade_xml_get_widget (gui, "txtSocksHost")); - prefs->socks_port = GTK_SPIN_BUTTON (glade_xml_get_widget (gui, "spnSocksPort")); - prefs->lbl_socks_host = GTK_LABEL (glade_xml_get_widget (gui, "lblSocksHost")); - prefs->lbl_socks_port = GTK_LABEL (glade_xml_get_widget (gui, "lblSocksPort")); - g_signal_connect (prefs->socks_host, "changed", - G_CALLBACK(widget_entry_changed_cb), GCONF_E_SOCKS_HOST_KEY); - g_signal_connect (prefs->socks_port, "value_changed", - G_CALLBACK(widget_entry_changed_cb), GCONF_E_SOCKS_PORT_KEY); -#endif - - /* Manual proxy options */ - g_signal_connect (prefs->http_host, "changed", - G_CALLBACK(widget_entry_changed_cb), - (gpointer) GCONF_E_HTTP_HOST_KEY); - g_signal_connect (prefs->https_host, "changed", - G_CALLBACK(widget_entry_changed_cb), - (gpointer) GCONF_E_HTTPS_HOST_KEY); - g_signal_connect (prefs->ignore_hosts, "changed", - G_CALLBACK(widget_entry_changed_cb), - (gpointer) GCONF_E_IGNORE_HOSTS_KEY); - g_signal_connect (prefs->http_port, "value_changed", - G_CALLBACK(widget_entry_changed_cb), - (gpointer) GCONF_E_HTTP_PORT_KEY); - g_signal_connect (prefs->https_port, "value_changed", - G_CALLBACK(widget_entry_changed_cb), - (gpointer) GCONF_E_HTTPS_PORT_KEY); - g_signal_connect (prefs->auth_user, "changed", - G_CALLBACK(widget_entry_changed_cb), - (gpointer) GCONF_E_AUTH_USER_KEY); - g_signal_connect (prefs->auth_pwd, "changed", - G_CALLBACK(widget_entry_changed_cb), - (gpointer) GCONF_E_AUTH_PWD_KEY); - - gtk_toggle_button_set_active (prefs->manual_proxy, val == NETWORK_PROXY_MANUAL); - g_signal_connect (prefs->sys_proxy, "toggled", G_CALLBACK (notify_proxy_type_changed), prefs); - g_signal_connect (prefs->no_proxy, "toggled", G_CALLBACK (notify_proxy_type_changed), prefs); -#if 0 - g_signal_connect (prefs->auto_proxy, "toggled", G_CALLBACK (notify_proxy_type_changed), prefs); -#endif - g_signal_connect (prefs->manual_proxy, "toggled", G_CALLBACK (notify_proxy_type_changed), prefs); - - if (locked) - gtk_widget_set_sensitive ((GtkWidget *) prefs->manual_proxy, FALSE); - d(g_print ("Manual settings ----!!! \n")); - - buf = gconf_client_get_string (prefs->gconf, GCONF_E_HTTP_HOST_KEY, NULL); - gtk_entry_set_text (prefs->http_host, buf ? buf : ""); - g_free (buf); - - buf = gconf_client_get_string (prefs->gconf, GCONF_E_HTTPS_HOST_KEY, NULL); - gtk_entry_set_text (prefs->https_host, buf ? buf : ""); - g_free (buf); - - buf = gconf_client_get_string (prefs->gconf, GCONF_E_IGNORE_HOSTS_KEY, NULL); - gtk_entry_set_text (prefs->ignore_hosts, buf ? buf : ""); - g_free (buf); - - buf = gconf_client_get_string (prefs->gconf, GCONF_E_AUTH_USER_KEY, NULL); - gtk_entry_set_text (prefs->auth_user, buf ? buf : ""); - g_free (buf); - - buf = gconf_client_get_string (prefs->gconf, GCONF_E_AUTH_PWD_KEY, NULL); - gtk_entry_set_text (prefs->auth_pwd, buf ? buf : ""); - g_free (buf); - - port = gconf_client_get_int (prefs->gconf, GCONF_E_HTTP_PORT_KEY, NULL); - gtk_spin_button_set_value (prefs->http_port, (gdouble)port); - - port = gconf_client_get_int (prefs->gconf, GCONF_E_HTTPS_PORT_KEY, NULL); - gtk_spin_button_set_value (prefs->https_port, (gdouble)port); - -#if 0 - buf = gconf_client_get_string (prefs->gconf, GCONF_E_SOCKS_HOST_KEY, NULL); - gtk_entry_set_text (prefs->socks_host, buf ? buf : ""); - g_free (buf); - - port = gconf_client_get_int (prefs->gconf, GCONF_E_SOCKS_PORT_KEY, NULL); - gtk_spin_button_set_value (prefs->socks_port, (gdouble)port); -#endif - emnp_set_markups (prefs); - - if (val == NETWORK_PROXY_DIRECT_CONNECTION || - val == NETWORK_PROXY_SYS_SETTINGS) { - emnp_set_sensitiveness (prefs, NETWORK_PROXY_MANUAL, FALSE); - emnp_set_sensitiveness (prefs, NETWORK_PROXY_AUTOCONFIG, FALSE); - } else if (val == NETWORK_PROXY_AUTOCONFIG) { - emnp_set_sensitiveness (prefs, NETWORK_PROXY_MANUAL, FALSE); - emnp_set_sensitiveness (prefs, NETWORK_PROXY_AUTOCONFIG, TRUE); - } else if (val == NETWORK_PROXY_MANUAL) { - emnp_set_sensitiveness (prefs, NETWORK_PROXY_AUTOCONFIG, FALSE); - emnp_set_sensitiveness (prefs, NETWORK_PROXY_MANUAL, TRUE); - } - - /* get our toplevel widget */ - target = em_config_target_new_prefs(ec, prefs->gconf); - e_config_set_target((EConfig *)ec, (EConfigTarget *)target); - toplevel = e_config_create_widget((EConfig *)ec); - gtk_container_add (GTK_CONTAINER (prefs), toplevel); -} - -GtkWidget * -em_network_prefs_new (void) -{ - EMNetworkPrefs *new; - - new = (EMNetworkPrefs *) g_object_new (em_network_prefs_get_type (), NULL); - em_network_prefs_construct (new); - - return (GtkWidget *) new; -} diff --git a/mail/em-network-prefs.h b/mail/em-network-prefs.h deleted file mode 100644 index 057247b750..0000000000 --- a/mail/em-network-prefs.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Veerapuram Varadhan - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef EM_NETWORK_PREFS_H -#define EM_NETWORK_PREFS_H - -#include -#include -#include - -/* Standard GObject macros */ -#define EM_TYPE_NETWORK_PREFS \ - (em_network_prefs_get_type ()) -#define EM_NETWORK_PREFS(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), EM_TYPE_NETWORK_PREFS, EMNetworkPrefs)) -#define EM_NETWORK_PREFS_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), EM_TYPE_NETWORK_PREFS, EMNetworkPrefsClass)) -#define EM_IS_NETWORK_PREFS(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), EM_TYPE_NETWORK_PREFS)) -#define EM_IS_NETWORK_PREFS_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), EM_TYPE_NETWORK_PREFS)) -#define EM_NETWORK_PREFS_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), EM_TYPE_NETWORK_PREFS, EMNetworkPrefsClass)) - -G_BEGIN_DECLS - -typedef struct _EMNetworkPrefs EMNetworkPrefs; -typedef struct _EMNetworkPrefsClass EMNetworkPrefsClass; - -typedef enum { - NETWORK_PROXY_SYS_SETTINGS, - NETWORK_PROXY_DIRECT_CONNECTION, - NETWORK_PROXY_MANUAL, - NETWORK_PROXY_AUTOCONFIG -} NetworkConfigProxyType; - -struct _EMNetworkPrefs { - GtkVBox parent_object; - - GConfClient *gconf; - - GladeXML *gui; - - /* Default Behavior */ - GtkToggleButton *sys_proxy; - GtkToggleButton *no_proxy; - GtkToggleButton *manual_proxy; - GtkToggleButton *use_auth; - - GtkEntry *http_host; - GtkEntry *https_host; - GtkEntry *socks_host; - GtkEntry *ignore_hosts; - GtkEntry *auth_user; - GtkEntry *auth_pwd; - - GtkLabel *lbl_http_host; - GtkLabel *lbl_http_port; - GtkLabel *lbl_https_host; - GtkLabel *lbl_https_port; - GtkLabel *lbl_ignore_hosts; - GtkLabel *lbl_auth_user; - GtkLabel *lbl_auth_pwd; - - GtkSpinButton *http_port; - GtkSpinButton *https_port; -}; - -struct _EMNetworkPrefsClass { - GtkVBoxClass parent_class; -}; - -GType em_network_prefs_get_type (void); -GtkWidget * em_network_prefs_new (void); - -G_END_DECLS - -#endif /* EM_NETWORK_PREFS_H */ diff --git a/mail/em-utils.c b/mail/em-utils.c index dffa11b132..a971b90f34 100644 --- a/mail/em-utils.c +++ b/mail/em-utils.c @@ -71,21 +71,49 @@ #include "e-util/e-account-utils.h" #include "e-util/e-dialog-utils.h" #include "e-util/e-error.h" +#include "shell/e-shell.h" #include "widgets/misc/e-alert-activity.h" #include "widgets/misc/e-attachment.h" #include "em-utils.h" #include "em-composer-utils.h" #include "em-format-quote.h" -#include "em-account-editor.h" - #include "e-mail-local.h" -#include "e-mail-shell-backend.h" static void emu_save_part_done (CamelMimePart *part, gchar *name, gint done, gpointer data); #define d(x) +const gchar * +em_utils_get_data_dir (void) +{ + EShell *shell; + EShellBackend *shell_backend; + + /* XXX This is a temporary solution until I can figure out a + * better way. Ideally, nothing below the module layer + * should need to know about the user data directory. */ + shell = e_shell_get_default (); + shell_backend = e_shell_get_backend_by_name (shell, "mail"); + + return e_shell_backend_get_data_dir (shell_backend); +} + +const gchar * +em_utils_get_config_dir (void) +{ + EShell *shell; + EShellBackend *shell_backend; + + /* XXX This is a temporary solution until I can figure out a + * better way. Ideally, nothing below the module layer + * should need to know about the user config directory. */ + shell = e_shell_get_default (); + shell_backend = e_shell_get_backend_by_name (shell, "mail"); + + return e_shell_backend_get_config_dir (shell_backend); +} + /** * em_utils_prompt_user: * @parent: parent window @@ -174,69 +202,22 @@ em_utils_uids_free (GPtrArray *uids) g_ptr_array_free (uids, TRUE); } -static void -druid_destroy_cb (gpointer user_data, GObject *deadbeef) -{ - gtk_main_quit (); -} - -/** - * em_utils_configure_account: - * @parent: parent window for the druid to be a child of. - * - * Displays a druid allowing the user to configure an account. If - * @parent is non-NULL, then the druid will be created as a child - * window of @parent's toplevel window. - * - * Returns %TRUE if an account has been configured or %FALSE - * otherwise. - **/ -gboolean -em_utils_configure_account (GtkWindow *parent) -{ - EMAccountEditor *emae; - EAccountList *account_list; - - g_return_val_if_fail (GTK_IS_WINDOW (parent), FALSE); - - emae = em_account_editor_new(NULL, EMAE_DRUID, "org.gnome.evolution.mail.config.accountDruid"); - gtk_window_set_transient_for (GTK_WINDOW (emae->editor), parent); - - g_object_weak_ref((GObject *)emae->editor, (GWeakNotify) druid_destroy_cb, NULL); - gtk_widget_show(emae->editor); - gtk_grab_add(emae->editor); - gtk_main(); - - account_list = e_get_account_list (); - - return (e_list_length ((EList *) account_list) > 0); -} - /** * em_utils_check_user_can_send_mail: - * @parent: parent window for the druid to be a child of. - * - * If no accounts have been configured, the user will be given a - * chance to configure an account. In the case that no accounts are - * configured, a druid will be created. If @parent is non-NULL, then - * the druid will be created as a child window of @parent's toplevel - * window. * * Returns %TRUE if the user has an account configured (to send mail) * or %FALSE otherwise. **/ gboolean -em_utils_check_user_can_send_mail (GtkWindow *parent) +em_utils_check_user_can_send_mail (void) { EAccountList *account_list; EAccount *account; account_list = e_get_account_list (); - if (e_list_length ((EList *) account_list) == 0) { - if (!em_utils_configure_account (parent)) - return FALSE; - } + if (e_list_length ((EList *) account_list) == 0) + return FALSE; if (!(account = e_get_default_account ())) return FALSE; @@ -255,16 +236,13 @@ static GtkWidget *filter_editor = NULL; static void em_filter_editor_response (GtkWidget *dialog, gint button, gpointer user_data) { - EShellBackend *shell_backend; EMFilterContext *fc; - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - if (button == GTK_RESPONSE_OK) { const gchar *data_dir; gchar *user; - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = em_utils_get_data_dir (); fc = g_object_get_data ((GObject *) dialog, "context"); user = g_strdup_printf ("%s/filters.xml", data_dir); rule_context_save ((RuleContext *) fc, user); @@ -293,7 +271,6 @@ static EMFilterSource em_filter_source_element_names[] = { void em_utils_edit_filters (GtkWidget *parent) { - EShellBackend *shell_backend; const gchar *data_dir; gchar *user, *system; EMFilterContext *fc; @@ -303,8 +280,7 @@ em_utils_edit_filters (GtkWidget *parent) return; } - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = em_utils_get_data_dir (); fc = em_filter_context_new (); user = g_build_filename (data_dir, "filters.xml", NULL); @@ -2292,10 +2268,12 @@ em_utils_clear_get_password_canceled_accounts_flag (void) void em_utils_show_error_silent (GtkWidget *widget) { + EShell *shell; EShellBackend *shell_backend; EActivity *activity; - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); + shell = e_shell_get_default (); + shell_backend = e_shell_get_backend_by_name (shell, "mail"); activity = e_alert_activity_new_warning (widget); e_shell_backend_add_activity (shell_backend, activity); @@ -2310,10 +2288,12 @@ em_utils_show_error_silent (GtkWidget *widget) void em_utils_show_info_silent (GtkWidget *widget) { + EShell *shell; EShellBackend *shell_backend; EActivity *activity; - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); + shell = e_shell_get_default (); + shell_backend = e_shell_get_backend_by_name (shell, "mail"); activity = e_alert_activity_new_info (widget); e_shell_backend_add_activity (shell_backend, activity); diff --git a/mail/em-utils.h b/mail/em-utils.h index 64c4d7aba7..14dc8cef23 100644 --- a/mail/em-utils.h +++ b/mail/em-utils.h @@ -38,13 +38,15 @@ G_BEGIN_DECLS struct _EMFormat; +const gchar * em_utils_get_data_dir (void); +const gchar * em_utils_get_config_dir (void); + gboolean em_utils_prompt_user(GtkWindow *parent, const gchar *promptkey, const gchar *tag, const gchar *arg0, ...); GPtrArray *em_utils_uids_copy (GPtrArray *uids); void em_utils_uids_free (GPtrArray *uids); -gboolean em_utils_configure_account (GtkWindow *parent); -gboolean em_utils_check_user_can_send_mail (GtkWindow *parent); +gboolean em_utils_check_user_can_send_mail (void); void em_utils_edit_filters (GtkWidget *parent); void em_filename_make_safe (gchar *string); diff --git a/mail/evolution-module-mail.c b/mail/evolution-module-mail.c deleted file mode 100644 index 97bc953c41..0000000000 --- a/mail/evolution-module-mail.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * evolution-module-mail.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-mail-shell-backend.h" -#include "e-mail-shell-content.h" -#include "e-mail-shell-sidebar.h" -#include "e-mail-shell-view.h" - -/* Module Entry Points */ -void e_module_load (GTypeModule *type_module); -void e_module_unload (GTypeModule *type_module); -const gchar * g_module_check_init (GModule *module); - -G_MODULE_EXPORT void -e_module_load (GTypeModule *type_module) -{ - /* Register dynamically loaded types. */ - - e_mail_shell_backend_register_type (type_module); - e_mail_shell_content_register_type (type_module); - e_mail_shell_sidebar_register_type (type_module); - e_mail_shell_view_register_type (type_module); -} - -G_MODULE_EXPORT void -e_module_unload (GTypeModule *type_module) -{ -} - -G_MODULE_EXPORT const gchar * -g_module_check_init (GModule *module) -{ - /* FIXME Until mail is split into a module library and a - * reusable shared library, prevent the module from - * being unloaded. Unloading the module resets all - * static variables, which screws up foo_get_type() - * functions among other things. */ - g_module_make_resident (module); - - return NULL; -} diff --git a/mail/importers/Makefile.am b/mail/importers/Makefile.am new file mode 100644 index 0000000000..ecd883cd8b --- /dev/null +++ b/mail/importers/Makefile.am @@ -0,0 +1,33 @@ +if OS_WIN32 +WIN32_BOOTSTRAP_LIBS = \ + $(top_builddir)/win32/libevolution-mail.la +endif + +privsolib_LTLIBRARIES = libevolution-mail-importers.la + +INCLUDES = -I.. \ + -I$(srcdir)/.. \ + -I$(top_srcdir) \ + -I$(top_srcdir)/widgets \ + $(EVOLUTION_MAIL_CFLAGS) \ + -DG_LOG_DOMAIN=\"evolution-mail-importer\" \ + -DEVOLUTION_PRIVDATADIR=\""$(privdatadir)"\" \ + $(IMPORTERS_CFLAGS) + +libevolution_mail_importers_la_SOURCES = \ + mail-importer.c \ + mail-importer.h \ + elm-importer.c \ + pine-importer.c \ + evolution-mbox-importer.c + +libevolution_mail_importers_la_LDFLAGS = $(NO_UNDEFINED) + +libevolution_mail_importers_la_LIBADD = \ + $(WIN32_BOOTSTRAP_LIBS) \ + $(top_builddir)/e-util/libeutil.la \ + $(top_builddir)/filter/libfilter.la \ + $(top_builddir)/mail/libevolution-mail.la \ + $(IMPORTERS_LIBS) + +-include $(top_srcdir)/git.mk diff --git a/mail/importers/evolution-mbox-importer.c b/mail/importers/evolution-mbox-importer.c index e44cf57fef..ade34526fc 100644 --- a/mail/importers/evolution-mbox-importer.c +++ b/mail/importers/evolution-mbox-importer.c @@ -42,7 +42,6 @@ #include "mail/e-mail-local.h" #include "mail/e-mail-store.h" -#include "mail/e-mail-shell-backend.h" #include "mail/em-folder-selection-button.h" #include "mail/em-folder-tree-model.h" #include "mail/mail-mt.h" diff --git a/mail/importers/mail-importer.c b/mail/importers/mail-importer.c index 1e1f423316..dd4de6370b 100644 --- a/mail/importers/mail-importer.c +++ b/mail/importers/mail-importer.c @@ -45,12 +45,12 @@ #include #include "e-util/e-util-private.h" +#include "shell/e-shell-backend.h" -#include "mail/mail-mt.h" -#include "mail/mail-tools.h" - -#include "mail/e-mail-local.h" -#include "mail/e-mail-shell-backend.h" +#include "mail-mt.h" +#include "mail-tools.h" +#include "e-mail-local.h" +#include "em-utils.h" #include "mail-importer.h" @@ -358,7 +358,6 @@ struct _import_folders_data { static void import_folders_rec(struct _import_folders_data *m, const gchar *filepath, const gchar *folderparent) { - EShellBackend *shell_backend; GDir *dir; const gchar *d; struct stat st; @@ -370,8 +369,7 @@ import_folders_rec(struct _import_folders_data *m, const gchar *filepath, const if (dir == NULL) return; - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = em_utils_get_data_dir (); utf8_filename = g_filename_to_utf8 (filepath, -1, NULL, NULL, NULL); camel_operation_start(NULL, _("Scanning %s"), utf8_filename); diff --git a/mail/mail-autofilter.c b/mail/mail-autofilter.c index a9f757e6fa..fd7fc5752b 100644 --- a/mail/mail-autofilter.c +++ b/mail/mail-autofilter.c @@ -48,8 +48,6 @@ #include #include -#include "e-mail-shell-backend.h" - #define d(x) static void @@ -346,7 +344,6 @@ filter_rule_from_message (EMFilterContext *context, CamelMimeMessage *msg, gint void filter_gui_add_from_message (CamelMimeMessage *msg, const gchar *source, gint flags) { - EShellBackend *shell_backend; EMFilterContext *fc; const gchar *data_dir; gchar *user, *system; @@ -354,10 +351,8 @@ filter_gui_add_from_message (CamelMimeMessage *msg, const gchar *source, gint fl g_return_if_fail (msg != NULL); - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - fc = em_filter_context_new (); - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = em_utils_get_data_dir (); user = g_build_filename (data_dir, "filters.xml", NULL); system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL); rule_context_load ((RuleContext *)fc, system, user); @@ -375,7 +370,6 @@ filter_gui_add_from_message (CamelMimeMessage *msg, const gchar *source, gint fl void mail_filter_rename_uri(CamelStore *store, const gchar *olduri, const gchar *newuri) { - EShellBackend *shell_backend; EMFilterContext *fc; const gchar *data_dir; gchar *user, *system; @@ -385,10 +379,8 @@ mail_filter_rename_uri(CamelStore *store, const gchar *olduri, const gchar *newu eolduri = em_uri_from_camel(olduri); enewuri = em_uri_from_camel(newuri); - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - fc = em_filter_context_new (); - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = em_utils_get_data_dir (); user = g_build_filename (data_dir, "filters.xml", NULL); system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL); rule_context_load ((RuleContext *)fc, system, user); @@ -412,7 +404,6 @@ mail_filter_rename_uri(CamelStore *store, const gchar *olduri, const gchar *newu void mail_filter_delete_uri(CamelStore *store, const gchar *uri) { - EShellBackend *shell_backend; EMFilterContext *fc; const gchar *data_dir; gchar *user, *system; @@ -421,10 +412,8 @@ mail_filter_delete_uri(CamelStore *store, const gchar *uri) euri = em_uri_from_camel(uri); - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - fc = em_filter_context_new (); - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = em_utils_get_data_dir (); user = g_build_filename (data_dir, "filters.xml", NULL); system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL); rule_context_load ((RuleContext *)fc, system, user); diff --git a/mail/mail-config.c b/mail/mail-config.c index 09763920eb..b1cfd5ab29 100644 --- a/mail/mail-config.c +++ b/mail/mail-config.c @@ -63,9 +63,8 @@ #include "mail-config.h" #include "mail-mt.h" #include "mail-tools.h" - +#include "em-utils.h" #include "e-mail-local.h" -#include "e-mail-shell-backend.h" typedef struct { GConfClient *gconf; @@ -773,13 +772,11 @@ mail_config_get_default_transport (void) static gchar * uri_to_evname (const gchar *uri, const gchar *prefix) { - EShellBackend *shell_backend; const gchar *data_dir; gchar *safe; gchar *tmp; - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = em_utils_get_data_dir (); safe = g_strdup (uri); e_filename_make_safe (safe); @@ -908,13 +905,10 @@ mail_config_folder_to_safe_url (CamelFolder *folder) gchar * mail_config_folder_to_cachename (CamelFolder *folder, const gchar *prefix) { - EShellBackend *shell_backend; gchar *url, *basename, *filename; const gchar *config_dir; - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - config_dir = e_shell_backend_get_config_dir (shell_backend); - + config_dir = em_utils_get_config_dir (); url = mail_config_folder_to_safe_url (folder); basename = g_strdup_printf ("%s%s", prefix, url); filename = g_build_filename (config_dir, basename, NULL); diff --git a/mail/mail-folder-cache.c b/mail/mail-folder-cache.c index faa80b2629..b3d7a1e12b 100644 --- a/mail/mail-folder-cache.c +++ b/mail/mail-folder-cache.c @@ -64,6 +64,7 @@ #include "em-folder-tree-model.h" #include "em-event.h" +#include "em-utils.h" #include "e-mail-local.h" #include "e-mail-store.h" @@ -629,7 +630,6 @@ folder_to_url(CamelStore *store, const gchar *full_name) static void rename_folders(struct _store_info *si, const gchar *oldbase, const gchar *newbase, CamelFolderInfo *fi) { - EShellBackend *shell_backend; gchar *old, *olduri, *oldfile, *newuri, *newfile; struct _folder_info *mfi; struct _folder_update *up; @@ -689,8 +689,7 @@ rename_folders(struct _store_info *si, const gchar *oldbase, const gchar *newbas #endif /* rename the meta-data we maintain ourselves */ - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - config_dir = e_shell_backend_get_config_dir (shell_backend); + config_dir = em_utils_get_config_dir (); olduri = folder_to_url(si->store, old); e_filename_make_safe(olduri); newuri = folder_to_url(si->store, fi->full_name); diff --git a/mail/mail-mt.c b/mail/mail-mt.c index ade31e56b9..c5b6edaa14 100644 --- a/mail/mail-mt.c +++ b/mail/mail-mt.c @@ -34,6 +34,7 @@ #include #include +#include "shell/e-shell.h" #include "misc/e-gui-utils.h" #include "e-util/e-error.h" #include "e-util/e-icon-factory.h" @@ -43,8 +44,6 @@ #include "mail-session.h" #include "mail-mt.h" -#include "e-mail-shell-backend.h" - /*#define MALLOC_CHECK*/ #define LOG_OPS #define LOG_LOCKS @@ -142,9 +141,11 @@ mail_msg_new (MailMsgInfo *info) static void end_event_callback (CamelObject *o, EActivity *activity, gpointer error) { + EShell *shell; EShellBackend *shell_backend; - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); + shell = e_shell_get_default (); + shell_backend = e_shell_get_backend_by_name (shell, "mail"); if (error == NULL) { e_activity_complete (activity); @@ -941,6 +942,7 @@ struct _op_status_msg { static void op_status_exec (struct _op_status_msg *m) { + EShell *shell; EShellBackend *shell_backend; MailMsg *msg; MailMsgPrivate *data; @@ -949,7 +951,8 @@ op_status_exec (struct _op_status_msg *m) g_return_if_fail (mail_in_main_thread ()); - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); + shell = e_shell_get_default (); + shell_backend = e_shell_get_backend_by_name (shell, "mail"); MAIL_MT_LOCK (mail_msg_lock); diff --git a/mail/mail-ops.c b/mail/mail-ops.c index a88a55e6c2..1c00420f89 100644 --- a/mail/mail-ops.c +++ b/mail/mail-ops.c @@ -70,12 +70,12 @@ #include "mail-vfolder.h" #include "e-mail-local.h" -#include "e-mail-shell-backend.h" #define w(x) #define d(x) -extern const gchar *x_mailer; +/* XXX Make this a preprocessor definition. */ +const gchar *x_mailer = "Evolution " VERSION SUB_VERSION " " VERSION_COMMENT; /* used for both just filtering a folder + uid's, and for filtering a whole folder */ /* used both for fetching mail, and for filtering mail */ @@ -247,19 +247,16 @@ static gchar * uid_cachename_hack (CamelStore *store) { CamelURL *url = CAMEL_SERVICE (store)->url; - EShellBackend *shell_backend; gchar *encoded_url, *filename; const gchar *data_dir; - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - encoded_url = g_strdup_printf ("%s%s%s@%s", url->user, url->authmech ? ";auth=" : "", url->authmech ? url->authmech : "", url->host); e_filename_make_safe (encoded_url); - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = em_utils_get_data_dir (); filename = g_build_filename (data_dir, "pop", encoded_url, "uid-cache", NULL); g_free (encoded_url); @@ -1762,17 +1759,14 @@ empty_trash_desc (struct _empty_trash_msg *m) static void empty_trash_exec (struct _empty_trash_msg *m) { - EShellBackend *shell_backend; const gchar *data_dir; CamelFolder *trash; gchar *uri; - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - if (m->account) { trash = mail_tool_get_trash (m->account->source->url, FALSE, &m->base.ex); } else { - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = em_utils_get_data_dir (); uri = g_strdup_printf ("mbox:%s/local", data_dir); trash = mail_tool_get_trash (uri, TRUE, &m->base.ex); g_free (uri); diff --git a/mail/mail-send-recv.c b/mail/mail-send-recv.c index 2f9cd77de6..9cc75057fa 100644 --- a/mail/mail-send-recv.c +++ b/mail/mail-send-recv.c @@ -51,7 +51,6 @@ #include "e-util/gconf-bridge.h" #include "e-mail-local.h" -#include "e-mail-shell-backend.h" #define d(x) diff --git a/mail/mail-session.c b/mail/mail-session.c index 862b611d15..bdb5d915c9 100644 --- a/mail/mail-session.c +++ b/mail/mail-session.c @@ -83,7 +83,7 @@ typedef struct _MailSessionClass { } MailSessionClass; -static EMailShellBackend *session_mail_shell_backend; +static EShellBackend *session_shell_backend; static CamelSessionClass *ms_parent_class; static gchar *get_password(CamelSession *session, CamelService *service, const gchar *domain, const gchar *prompt, const gchar *item, guint32 flags, CamelException *ex); @@ -503,7 +503,6 @@ session_system_beep (CamelFilterDriver *driver, gpointer user_data) static CamelFilterDriver * main_get_filter_driver (CamelSession *session, const gchar *type, CamelException *ex) { - EShellBackend *shell_backend; CamelFilterDriver *driver; FilterRule *rule = NULL; const gchar *data_dir; @@ -512,9 +511,8 @@ main_get_filter_driver (CamelSession *session, const gchar *type, CamelException RuleContext *fc; gconf = mail_config_get_gconf_client (); - shell_backend = E_SHELL_BACKEND (session_mail_shell_backend); - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = e_shell_backend_get_data_dir (session_shell_backend); user = g_build_filename (data_dir, "filters.xml", NULL); system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL); fc = (RuleContext *) em_filter_context_new (); @@ -708,17 +706,15 @@ mail_session_check_junk_notify (GConfClient *gconf, guint id, GConfEntry *entry, } void -mail_session_init (EMailShellBackend *mail_shell_backend) +mail_session_init (EShellBackend *shell_backend) { EShell *shell; - EShellBackend *shell_backend; GConfClient *gconf; gboolean online; const gchar *data_dir; - session_mail_shell_backend = mail_shell_backend; + session_shell_backend = shell_backend; - shell_backend = E_SHELL_BACKEND (mail_shell_backend); shell = e_shell_backend_get_shell (shell_backend); online = e_shell_get_online (shell); diff --git a/mail/mail-session.h b/mail/mail-session.h index 450404efcd..b1274403c0 100644 --- a/mail/mail-session.h +++ b/mail/mail-session.h @@ -25,11 +25,11 @@ #include #include -#include +#include G_BEGIN_DECLS -void mail_session_init (EMailShellBackend *mail_shell_backend); +void mail_session_init (EShellBackend *shell_backend); void mail_session_shutdown (void); gboolean mail_session_get_interactive (void); void mail_session_set_interactive (gboolean interactive); diff --git a/mail/mail-tools.c b/mail/mail-tools.c index 67407ae81f..a19c3dedb4 100644 --- a/mail/mail-tools.c +++ b/mail/mail-tools.c @@ -58,8 +58,6 @@ #include "mail-tools.h" #include "mail-vfolder.h" -#include "e-mail-shell-backend.h" - /* **************************************** */ CamelFolder * @@ -107,7 +105,6 @@ mail_tool_get_trash (const gchar *url, gint connect, CamelException *ex) static gchar * mail_tool_get_local_movemail_path (const guchar *uri, CamelException *ex) { - EShellBackend *shell_backend; guchar *safe_uri, *c; const gchar *data_dir; gchar *path, *full; @@ -118,8 +115,7 @@ mail_tool_get_local_movemail_path (const guchar *uri, CamelException *ex) if (strchr("/:;=|%&#!*^()\\, ", *c) || !isprint((gint) *c)) *c = '_'; - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = em_utils_get_data_dir (); path = g_build_filename (data_dir, "spool", NULL); if (g_stat(path, &st) == -1 && g_mkdir_with_parents(path, 0777) == -1) { diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c index 5a5f7324ed..487eea0e10 100644 --- a/mail/mail-vfolder.c +++ b/mail/mail-vfolder.c @@ -52,7 +52,6 @@ #include "e-mail-local.h" #include "e-mail-store.h" -#include "e-mail-shell-backend.h" #define d(x) /* (printf("%s:%s: ", G_STRLOC, G_STRFUNC), (x))*/ @@ -533,7 +532,6 @@ done: void mail_vfolder_delete_uri(CamelStore *store, const gchar *curi) { - EShellBackend *shell_backend; FilterRule *rule; const gchar *source; CamelVeeFolder *vf; @@ -550,8 +548,6 @@ mail_vfolder_delete_uri(CamelStore *store, const gchar *curi) g_return_if_fail (mail_in_main_thread()); - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - changed = g_string_new (""); LOCK(); @@ -612,7 +608,7 @@ done: dialog = e_error_new(NULL, "mail:vfolder-updated", changed->str, uri, NULL); em_utils_show_info_silent (dialog); - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = em_utils_get_data_dir (); user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_save ((RuleContext *) context, user); g_free (user); @@ -627,7 +623,6 @@ done: void mail_vfolder_rename_uri(CamelStore *store, const gchar *cfrom, const gchar *cto) { - EShellBackend *shell_backend; FilterRule *rule; const gchar *source; CamelVeeFolder *vf; @@ -641,8 +636,6 @@ mail_vfolder_rename_uri(CamelStore *store, const gchar *cfrom, const gchar *cto) g_return_if_fail (mail_in_main_thread()); - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - from = em_uri_from_camel(cfrom); to = em_uri_from_camel(cto); @@ -683,7 +676,7 @@ mail_vfolder_rename_uri(CamelStore *store, const gchar *cfrom, const gchar *cto) gchar *user; d(printf("Vfolders updated from renamed folder\n")); - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = em_utils_get_data_dir (); user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_save((RuleContext *)context, user); g_free(user); @@ -837,7 +830,6 @@ store_folder_created(CamelObject *o, gpointer event_data, gpointer data) static void store_folder_deleted(CamelObject *o, gpointer event_data, gpointer data) { - EShellBackend *shell_backend; CamelStore *store = (CamelStore *)o; CamelFolderInfo *info = event_data; FilterRule *rule; @@ -846,8 +838,6 @@ store_folder_deleted(CamelObject *o, gpointer event_data, gpointer data) d(printf("Folder deleted: %s\n", info->name)); store = store; - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - /* Warning not thread safe, but might be enough */ LOCK(); @@ -864,7 +854,7 @@ store_folder_deleted(CamelObject *o, gpointer event_data, gpointer data) g_object_unref(rule); g_signal_connect(context, "rule_removed", G_CALLBACK(context_rule_removed), context); - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = em_utils_get_data_dir (); user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_save((RuleContext *)context, user); g_free(user); @@ -878,15 +868,12 @@ store_folder_deleted(CamelObject *o, gpointer event_data, gpointer data) static void store_folder_renamed(CamelObject *o, gpointer event_data, gpointer data) { - EShellBackend *shell_backend; CamelRenameInfo *info = event_data; FilterRule *rule; gchar *user; gpointer key, folder; - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - /* This should be more-or-less thread-safe */ d(printf("Folder renamed to '%s' from '%s'\n", info->new->full_name, info->old_base)); @@ -913,7 +900,7 @@ store_folder_renamed(CamelObject *o, gpointer event_data, gpointer data) filter_rule_set_name(rule, info->new->full_name); g_signal_connect(rule, "changed", G_CALLBACK(rule_changed), folder); - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = em_utils_get_data_dir (); user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_save((RuleContext *)context, user); g_free(user); @@ -931,15 +918,12 @@ vfolder_load_storage(void) /* lock for loading storage, it is safe to call it more than once */ static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - EShellBackend *shell_backend; const gchar *data_dir; gchar *user, *storeuri; FilterRule *rule; gchar *xmlfile; GConfClient *gconf; - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - pthread_mutex_lock (&lock); if (vfolder_hash) { @@ -953,7 +937,7 @@ vfolder_load_storage(void) pthread_mutex_unlock (&lock); /* first, create the vfolder store, and set it up */ - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = em_utils_get_data_dir (); storeuri = g_strdup_printf("vfolder:%s/vfolder", data_dir); vfolder_store = camel_session_get_store(session, storeuri, NULL); if (vfolder_store == NULL) { @@ -1010,14 +994,11 @@ vfolder_load_storage(void) void vfolder_revert(void) { - EShellBackend *shell_backend; const gchar *data_dir; gchar *user; - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - d(printf("vfolder_revert\n")); - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = em_utils_get_data_dir (); user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_revert((RuleContext *)context, user); g_free(user); @@ -1064,10 +1045,6 @@ vfolder_edit (EShellView *shell_view) static void edit_rule_response(GtkWidget *w, gint button, gpointer data) { - EShellBackend *shell_backend; - - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - if (button == GTK_RESPONSE_OK) { const gchar *data_dir; gchar *user; @@ -1075,7 +1052,7 @@ edit_rule_response(GtkWidget *w, gint button, gpointer data) FilterRule *orig = g_object_get_data (G_OBJECT (w), "orig"); filter_rule_copy(orig, rule); - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = em_utils_get_data_dir (); user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_save((RuleContext *)context, user); g_free(user); @@ -1132,10 +1109,6 @@ vfolder_edit_rule(const gchar *uri) static void new_rule_clicked(GtkWidget *w, gint button, gpointer data) { - EShellBackend *shell_backend; - - shell_backend = E_SHELL_BACKEND (global_mail_shell_backend); - if (button == GTK_RESPONSE_OK) { const gchar *data_dir; gchar *user; @@ -1154,7 +1127,7 @@ new_rule_clicked(GtkWidget *w, gint button, gpointer data) g_object_ref(rule); rule_context_add_rule((RuleContext *)context, rule); - data_dir = e_shell_backend_get_data_dir (shell_backend); + data_dir = em_utils_get_data_dir (); user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_save((RuleContext *)context, user); g_free(user); diff --git a/modules/Makefile.am b/modules/Makefile.am new file mode 100644 index 0000000000..5030d2aeb6 --- /dev/null +++ b/modules/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = addressbook calendar mail + +-include $(top_srcdir)/git.mk diff --git a/modules/addressbook/Makefile.am b/modules/addressbook/Makefile.am new file mode 100644 index 0000000000..960df59e09 --- /dev/null +++ b/modules/addressbook/Makefile.am @@ -0,0 +1,129 @@ +if OS_WIN32 +WIN32_BOOTSTRAP_LIBS = $(top_builddir)/win32/libevolution-mail.la +endif + +INCLUDES = \ + -DG_LOG_DOMAIN=\"evolution-addressbook\" \ + -I$(top_srcdir) \ + -I$(top_srcdir)/widgets \ + -I$(top_srcdir)/shell \ + -I$(top_builddir)/shell \ + -I$(top_srcdir)/widgets/menus \ + -I$(top_srcdir)/widgets/misc \ + -I$(top_srcdir)/addressbook/util \ + -I$(top_srcdir)/addressbook/gui/contact-editor \ + -I$(top_srcdir)/addressbook/gui/contact-list-editor \ + -I$(top_srcdir)/addressbook/gui/widgets \ + -I$(top_srcdir)/a11y/addressbook \ + -DEVOLUTION_ETSPECDIR=\""$(etspecdir)"\" \ + -DEVOLUTION_GALVIEWSDIR=\""$(viewsdir)"\" \ + -DEVOLUTION_GLADEDIR=\""$(gladedir)"\" \ + -DEVOLUTION_LOCALEDIR=\""$(localedir)"\" \ + -DEVOLUTION_UIDIR=\""$(evolutionuidir)"\" \ + -DPREFIX=\""$(prefix)"\" \ + $(LDAP_CFLAGS) \ + $(EVOLUTION_ADDRESSBOOK_CFLAGS) + +module_LTLIBRARIES = libevolution-module-addressbook.la + +libevolution_module_addressbook_la_SOURCES = \ + evolution-module-addressbook.c \ + addressbook-config.c \ + addressbook-config.h \ + autocompletion-config.c \ + autocompletion-config.h \ + eab-composer-util.c \ + eab-composer-util.h \ + e-book-shell-backend.c \ + e-book-shell-backend.h \ + e-book-shell-content.c \ + e-book-shell-content.h \ + e-book-shell-migrate.c \ + e-book-shell-migrate.h \ + e-book-shell-sidebar.c \ + e-book-shell-sidebar.h \ + e-book-shell-view.c \ + e-book-shell-view.h \ + e-book-shell-view-actions.c \ + e-book-shell-view-actions.h \ + e-book-shell-view-private.c \ + e-book-shell-view-private.h + +if ENABLE_SMIME +SMIME_LIB=$(top_builddir)/smime/gui/libevolution-smime.la +endif + +libevolution_module_addressbook_la_LIBADD = \ + $(SMIME_LIB) \ + $(top_builddir)/e-util/libeutil.la \ + $(top_builddir)/composer/libcomposer.la \ + $(top_builddir)/addressbook/printing/libecontactprint.la \ + $(top_builddir)/shell/libeshell.la \ + $(top_builddir)/addressbook/gui/merging/libeabbookmerging.la \ + $(top_builddir)/addressbook/gui/widgets/libeabwidgets.la \ + $(top_builddir)/filter/libfilter.la \ + $(top_builddir)/addressbook/util/libeabutil.la \ + $(top_builddir)/addressbook/gui/contact-editor/libecontacteditor.la \ + $(top_builddir)/addressbook/gui/contact-list-editor/libecontactlisteditor.la \ + $(top_builddir)/widgets/table/libetable.la \ + $(top_builddir)/widgets/text/libetext.la \ + $(top_builddir)/widgets/misc/libemiscwidgets.la \ + $(top_builddir)/widgets/menus/libmenus.la \ + $(top_builddir)/addressbook/importers/libevolution-addressbook-importers.la \ + $(EVOLUTION_ADDRESSBOOK_LIBS) $(LDAP_LIBS) + + +libevolution_module_addressbook_la_LDFLAGS = \ + -module -avoid-version $(NO_UNDEFINED) + +# GConf schemas + +schemadir = $(GCONF_SCHEMA_FILE_DIR) +schema_in_files = apps_evolution_addressbook.schemas.in +schema_DATA = $(schema_in_files:.schemas.in=.schemas) + +@INTLTOOL_SCHEMAS_RULE@ + +if OS_WIN32 +install-data-local: + if test -z "$(DESTDIR)" ; then \ + for p in $(schema_DATA) ; do \ + (echo set GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE); \ + echo $(GCONFTOOL) --makefile-install-rule $$p) >_temp.bat; \ + cmd /c _temp.bat; \ + done \ + fi +else +install-data-local: + if test -z "$(DESTDIR)" ; then \ + for p in $(schema_DATA) ; do \ + GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $$p; \ + done \ + fi +endif + +glade_DATA = \ + ldap-config.glade + +DISTCLEANFILES = $(schema_DATA) + +EXTRA_DIST = \ + $(glade_DATA) \ + $(schema_in_files) \ + openldap-extract.h + +dist-hook: + cd $(distdir); rm -f $(BUILT_SOURCES) + +if ENABLE_PURIFY +PLINK = $(LIBTOOL) --mode=link $(PURIFY) $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ + +all-local: evolution-addressbook.pure + +evolution-addressbook.pure: evolution-addressbook + @rm -f evolution-addressbook.pure + $(PLINK) $(evolution_addressbook_LDFLAGS) $(evolution_addressbook_OBJECTS) $(evolution_addressbook_LDADD) $(LIBS) + +endif + +-include $(top_srcdir)/git.mk diff --git a/modules/addressbook/addressbook-config.c b/modules/addressbook/addressbook-config.c new file mode 100644 index 0000000000..e663de03da --- /dev/null +++ b/modules/addressbook/addressbook-config.c @@ -0,0 +1,1250 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Chris Toshok + * Chris Lahey + * Michael Zucchi + * And no doubt others ... + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/*#define STANDALONE*/ + +#include + +#include +#include +#include + +#include +#include + +#ifdef G_OS_WIN32 +/* Include early and work around DATADIR lossage */ +#define DATADIR crap_DATADIR +#include +#undef DATADIR +#endif + +#include + +#include "addressbook.h" +#include "addressbook-config.h" + +#include "e-util/e-error.h" +#include "e-util/e-util-private.h" + +#include "addressbook/gui/widgets/eab-config.h" + +#define d(x) + +#ifdef HAVE_LDAP +#ifndef G_OS_WIN32 +#include +#ifndef SUNLDAP +#include +#endif +#else +#include +#include "openldap-extract.h" +#endif +#endif + +#define LDAP_PORT_STRING "389" +#define LDAPS_PORT_STRING "636" + +#define GLADE_FILE_NAME "ldap-config.glade" + +GtkWidget* supported_bases_create_table (gchar *name, gchar *string1, gchar *string2, + gint num1, gint num2); + +/* default objectclasses */ +#define TOP "top" +#define PERSON "person" +#define ORGANIZATIONALPERSON "organizationalPerson" +#define INETORGPERSON "inetOrgPerson" +#define EVOLUTIONPERSON "evolutionPerson" +#define CALENTRY "calEntry" + + +typedef struct _AddressbookSourceDialog AddressbookSourceDialog; + +struct _AddressbookSourceDialog { + GladeXML *gui; + + EABConfig *config; /* the config manager */ + + GtkWidget *window; + + /* Source selection (druid only) */ + ESourceList *source_list; + GSList *menu_source_groups; + + /* ESource we're currently editing */ + ESource *source; + /* The original source in edit mode. Also used to flag when we are in edit mode. */ + ESource *original_source; + + /* Source group we're creating/editing a source in */ + ESourceGroup *source_group; + + /* info page fields */ + GtkWidget *host; + GtkWidget *auth_combobox; + AddressbookLDAPAuthType auth; + GtkWidget *auth_principal; + + /* connecting page fields */ + GtkWidget *port_comboentry; + GtkWidget *ssl_combobox; + AddressbookLDAPSSLType ssl; + + /* searching page fields */ + GtkWidget *rootdn; + AddressbookLDAPScopeType scope; + GtkWidget *scope_combobox; + GtkWidget *search_filter; + GtkWidget *timeout_scale; + GtkWidget *limit_spinbutton; + GtkWidget *canbrowsecheck; + + /* display name page fields */ + GtkWidget *display_name; +}; + + + +#ifdef HAVE_LDAP + +static const gchar * +ldap_unparse_auth (AddressbookLDAPAuthType auth_type) +{ + switch (auth_type) { + case ADDRESSBOOK_LDAP_AUTH_NONE: + return "none"; + case ADDRESSBOOK_LDAP_AUTH_SIMPLE_EMAIL: + return "ldap/simple-email"; + case ADDRESSBOOK_LDAP_AUTH_SIMPLE_BINDDN: + return "ldap/simple-binddn"; + default: + g_return_val_if_reached ("none"); + } +} + +static AddressbookLDAPAuthType +ldap_parse_auth (const gchar *auth) +{ + if (!auth) + return ADDRESSBOOK_LDAP_AUTH_NONE; + + if (!strcmp (auth, "ldap/simple-email") || !strcmp (auth, "simple")) + return ADDRESSBOOK_LDAP_AUTH_SIMPLE_EMAIL; + else if (!strcmp (auth, "ldap/simple-binddn")) + return ADDRESSBOOK_LDAP_AUTH_SIMPLE_BINDDN; + else + return ADDRESSBOOK_LDAP_AUTH_NONE; +} + +static const gchar * +ldap_unparse_scope (AddressbookLDAPScopeType scope_type) +{ + switch (scope_type) { + case ADDRESSBOOK_LDAP_SCOPE_BASE: + return "base"; + case ADDRESSBOOK_LDAP_SCOPE_ONELEVEL: + return "one"; + case ADDRESSBOOK_LDAP_SCOPE_SUBTREE: + return "sub"; + default: + g_return_val_if_reached (""); + } +} + +static const gchar * +ldap_unparse_ssl (AddressbookLDAPSSLType ssl_type) +{ + switch (ssl_type) { + case ADDRESSBOOK_LDAP_SSL_NEVER: + return "never"; + case ADDRESSBOOK_LDAP_SSL_WHENEVER_POSSIBLE: + return "whenever_possible"; + case ADDRESSBOOK_LDAP_SSL_ALWAYS: + return "always"; + default: + g_return_val_if_reached (""); + } +} + +static AddressbookLDAPSSLType +ldap_parse_ssl (const gchar *ssl) +{ + if (!ssl) + return ADDRESSBOOK_LDAP_SSL_WHENEVER_POSSIBLE; /* XXX good default? */ + + if (!strcmp (ssl, "always")) + return ADDRESSBOOK_LDAP_SSL_ALWAYS; + else if (!strcmp (ssl, "never")) + return ADDRESSBOOK_LDAP_SSL_NEVER; + else + return ADDRESSBOOK_LDAP_SSL_WHENEVER_POSSIBLE; +} + +static const gchar * +ldap_get_ssl_tooltip (AddressbookLDAPSSLType ssl_type) +{ + switch (ssl_type) { + case ADDRESSBOOK_LDAP_SSL_ALWAYS: + return _("Selecting this option means that Evolution will only connect to your LDAP server if your LDAP server supports SSL."); + case ADDRESSBOOK_LDAP_SSL_WHENEVER_POSSIBLE: + return _("Selecting this option means that Evolution will only connect to your LDAP server if your LDAP server supports TLS."); + case ADDRESSBOOK_LDAP_SSL_NEVER: + return _("Selecting this option means that your server does not support either SSL or TLS. This means that your connection will be insecure, and that you will be vulnerable to security exploits."); + } + + return NULL; +} + +static gboolean +source_to_uri_parts (ESource *source, gchar **host, gchar **rootdn, AddressbookLDAPScopeType *scope, gchar **search_filter, gint *port) +{ + gchar *uri; + LDAPURLDesc *lud; + gint ldap_error; + + g_return_val_if_fail (source, FALSE); + + uri = e_source_get_uri (source); + ldap_error = ldap_url_parse ((gchar *) uri, &lud); + g_free (uri); + + if (ldap_error != LDAP_SUCCESS) + return FALSE; + + if (host) + *host = g_strdup (lud->lud_host ? lud->lud_host : ""); + if (rootdn) + *rootdn = g_strdup (lud->lud_dn ? lud->lud_dn : ""); + if (port) + *port = lud->lud_port ? lud->lud_port : LDAP_PORT; + if (scope) + *scope = lud->lud_scope == LDAP_SCOPE_BASE ? ADDRESSBOOK_LDAP_SCOPE_BASE : + lud->lud_scope == LDAP_SCOPE_ONELEVEL ? ADDRESSBOOK_LDAP_SCOPE_ONELEVEL : + lud->lud_scope == LDAP_SCOPE_SUBTREE ? ADDRESSBOOK_LDAP_SCOPE_SUBTREE : + ADDRESSBOOK_LDAP_SCOPE_ONELEVEL; + if (search_filter && lud->lud_filter) + *search_filter = g_strdup (lud->lud_filter); + + ldap_free_urldesc (lud); + return TRUE; +} + +static gboolean +source_group_is_remote (ESourceGroup *group) +{ + return strncmp ("ldap:", e_source_group_peek_base_uri (group), 5) == 0; +} + +/* ldap api foo */ +static LDAP * +addressbook_ldap_init (GtkWidget *window, ESource *source) +{ + LDAP *ldap; + gchar *host; + gint port; + gint ldap_error; + gint protocol_version = LDAP_VERSION3; + + if (!source_to_uri_parts (source, &host, NULL, NULL, NULL, &port)) + return NULL; + + if (!(ldap = ldap_init (host, port))) { + e_error_run ((GtkWindow *) window, "addressbook:ldap-init", NULL); + goto done; + } + + ldap_error = ldap_set_option (ldap, LDAP_OPT_PROTOCOL_VERSION, &protocol_version); + if (LDAP_SUCCESS != ldap_error) + g_warning ("failed to set protocol version to LDAPv3"); + + /* XXX do TLS if it's configured in */ + + done: + g_free (host); + return ldap; +} + +static gint +addressbook_ldap_auth (GtkWidget *window, LDAP *ldap) +{ + gint ldap_error; + + /* XXX use auth info from source */ + ldap_error = ldap_simple_bind_s (ldap, NULL, NULL); + if (LDAP_SUCCESS != ldap_error) + e_error_run ((GtkWindow *) window, "addressbook:ldap-auth", NULL); + + return ldap_error; +} + +static gint +addressbook_root_dse_query (AddressbookSourceDialog *dialog, LDAP *ldap, + const gchar **attrs, LDAPMessage **resp) +{ + gint ldap_error; + struct timeval timeout; + + timeout.tv_sec = (gint) gtk_adjustment_get_value (GTK_RANGE(dialog->timeout_scale)->adjustment); + timeout.tv_usec = 0; + + ldap_error = ldap_search_ext_s (ldap, + LDAP_ROOT_DSE, LDAP_SCOPE_BASE, + "(objectclass=*)", + (gchar **) attrs, 0, NULL, NULL, &timeout, LDAP_NO_LIMIT, resp); + if (LDAP_SUCCESS != ldap_error) + e_error_run (GTK_WINDOW (dialog->window), "addressbook:ldap-search-base", NULL); + + return ldap_error; +} + +/* searching page */ +GtkWidget* +supported_bases_create_table (gchar *name, gchar *string1, gchar *string2, gint num1, gint num2) +{ + GtkWidget *table, *scrolled; + GtkTreeSelection *selection; + GtkCellRenderer *renderer; + GtkListStore *model; + + scrolled = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_IN); + + model = gtk_list_store_new (1, G_TYPE_STRING); + table = gtk_tree_view_new_with_model ((GtkTreeModel *) model); + g_object_unref (model); + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes ((GtkTreeView *) table, -1, _("Base"), renderer, "text", 0, NULL); + gtk_tree_view_set_headers_visible ((GtkTreeView *) table, FALSE); + selection = gtk_tree_view_get_selection ((GtkTreeView *) table); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); + + gtk_container_add (GTK_CONTAINER (scrolled), table); + g_object_set_data((GObject *)scrolled, "table", table); + + return scrolled; +} + +static gboolean +do_ldap_root_dse_query (AddressbookSourceDialog *sdialog, GtkListStore *model, ESource *source) +{ + LDAP *ldap; + const gchar *attrs[2]; + gint ldap_error; + gchar **values; + LDAPMessage *resp; + gint i; + + ldap = addressbook_ldap_init (sdialog->window, source); + if (!ldap) + return FALSE; + + if (LDAP_SUCCESS != addressbook_ldap_auth (sdialog->window, ldap)) + goto fail; + + attrs[0] = "namingContexts"; + attrs[1] = NULL; + + ldap_error = addressbook_root_dse_query (sdialog, ldap, attrs, &resp); + + if (ldap_error != LDAP_SUCCESS) + goto fail; + + values = ldap_get_values (ldap, resp, "namingContexts"); + if (!values || values[0] == NULL || strlen (values[0]) == 0) { + e_error_run (GTK_WINDOW (sdialog->window), "addressbook:ldap-search-base", NULL); + goto fail; + } + + for (i = 0; values[i]; i++) { + GtkTreeIter iter; + + gtk_list_store_append (model, &iter); + gtk_list_store_set (model, &iter, 0, values[i], -1); + } + + ldap_value_free (values); + ldap_unbind_s (ldap); + return TRUE; + + fail: + ldap_unbind_s (ldap); + return FALSE; +} + +static void +search_base_selection_model_changed (GtkTreeSelection *selection, GtkWidget *dialog) +{ + gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), + GTK_RESPONSE_OK, + gtk_tree_selection_get_selected(selection, NULL, NULL)); +} + +static void +query_for_supported_bases (GtkWidget *button, AddressbookSourceDialog *sdialog) +{ + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeView *table; + GtkWidget *dialog; + GtkWidget *supported_bases_table; + GladeXML *gui; + GtkTreeIter iter; + gchar *gladefile; + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + GLADE_FILE_NAME, + NULL); + gui = glade_xml_new (gladefile, "supported-bases-dialog", NULL); + g_free (gladefile); + + dialog = glade_xml_get_widget (gui, "supported-bases-dialog"); + + gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (sdialog->window)); + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + + gtk_widget_ensure_style (dialog); + gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 0); + gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area), 12); + + supported_bases_table = glade_xml_get_widget (gui, "supported-bases-table"); + gtk_widget_show_all (supported_bases_table); + + table = g_object_get_data (G_OBJECT (supported_bases_table), "table"); + model = gtk_tree_view_get_model (table); + selection = gtk_tree_view_get_selection (table); + g_signal_connect (selection, "changed", G_CALLBACK (search_base_selection_model_changed), dialog); + search_base_selection_model_changed (selection, dialog); + + if (do_ldap_root_dse_query (sdialog, GTK_LIST_STORE (model), sdialog->source)) { + gtk_widget_show (dialog); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK + && gtk_tree_selection_get_selected (selection, &model, &iter)) { + gchar *dn; + + gtk_tree_model_get (model, &iter, 0, &dn, -1); + gtk_entry_set_text((GtkEntry *)sdialog->rootdn, dn); + g_free(dn); + } + } + + gtk_widget_destroy (dialog); +} + +#endif /* HAVE_LDAP */ + +GtkWidget* +addressbook_config_create_new_source (GtkWidget *parent) +{ + return addressbook_config_edit_source(parent, NULL); +} + +/* ********************************************************************** */ + +static void +eabc_type_changed(GtkComboBox *dropdown, AddressbookSourceDialog *sdialog) +{ + gint id = gtk_combo_box_get_active(dropdown); + GtkTreeModel *model; + GtkTreeIter iter; + + model = gtk_combo_box_get_model(dropdown); + if (id == -1 || !gtk_tree_model_iter_nth_child(model, &iter, NULL, id)) + return; + + /* TODO: when we change the group type, we lose all of the pre-filled dialog info */ + + gtk_tree_model_get(model, &iter, 1, &sdialog->source_group, -1); + /* HACK: doesn't work if you don't do this */ + e_source_set_absolute_uri(sdialog->source, NULL); + e_source_set_group(sdialog->source, sdialog->source_group); + + /* BIG HACK: We load the defaults for each type here. + I guess plugins will have to use the do it in their factory callbacks */ + if (!strncmp(e_source_group_peek_base_uri(sdialog->source_group), "groupwise:", 10)) { + GSList *l; + ESource *source; + gchar *tmp; + + l = e_source_group_peek_sources(sdialog->source_group); + if (l && l->data ) { + source = l->data; + e_source_set_property(sdialog->source, "auth", e_source_get_property(source, "auth")); + e_source_set_property(sdialog->source, "user", e_source_get_property(source, "user")); + e_source_set_property(sdialog->source, "user_ssl", e_source_get_property(source, "use_ssl")); + } + + e_source_set_property(sdialog->source, "auth-domain", "Groupwise"); + tmp = g_strconcat (";", e_source_peek_name(sdialog->source), NULL); + e_source_set_relative_uri (sdialog->source, tmp); + g_free (tmp); +#ifdef HAVE_LDAP + } else if (!strncmp(e_source_group_peek_base_uri(sdialog->source_group), "ldap:", 5)) { + gchar *tmp; + + tmp = g_strdup_printf ("%s:%s/%s?" /* trigraph prevention */ "?%s", + "", LDAP_PORT_STRING, + "", + "one"); + e_source_set_relative_uri (sdialog->source, tmp); + g_free (tmp); + e_source_set_property(sdialog->source, "timeout", "3"); + e_source_set_property(sdialog->source, "limit", "100"); +#endif + } else { + e_source_set_relative_uri (sdialog->source, e_source_peek_uid (sdialog->source)); + } + + e_config_target_changed((EConfig *)sdialog->config, E_CONFIG_TARGET_CHANGED_REBUILD); +} + +static GtkWidget * +eabc_general_type(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + AddressbookSourceDialog *sdialog = data; + GtkComboBox *dropdown; + GtkCellRenderer *cell; + GtkListStore *store; + GtkTreeIter iter; + GSList *l; + GtkWidget *w, *label; + gint i, row = 0; + + if (old) + return old; + + w = gtk_hbox_new(FALSE, 6); + label = gtk_label_new_with_mnemonic(_("_Type:")); + gtk_box_pack_start((GtkBox *)w, label, FALSE, FALSE, 0); + + dropdown = (GtkComboBox *)gtk_combo_box_new(); + cell = gtk_cell_renderer_text_new(); + store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); + i = 0; + for (l=sdialog->menu_source_groups;l;l=g_slist_next(l)) { + ESourceGroup *group = l->data; + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, e_source_group_peek_name(group), 1, group, -1); + if (e_source_peek_group(sdialog->source) == group) + row = i; + i++; + } + + gtk_cell_layout_pack_start((GtkCellLayout *)dropdown, cell, TRUE); + gtk_cell_layout_set_attributes((GtkCellLayout *)dropdown, cell, "text", 0, NULL); + gtk_combo_box_set_model(dropdown, (GtkTreeModel *)store); + gtk_combo_box_set_active(dropdown, -1); + gtk_combo_box_set_active(dropdown, row); + g_signal_connect(dropdown, "changed", G_CALLBACK(eabc_type_changed), sdialog); + gtk_widget_show((GtkWidget *)dropdown); + gtk_box_pack_start((GtkBox *)w, (GtkWidget *)dropdown, TRUE, TRUE, 0); + gtk_label_set_mnemonic_widget((GtkLabel *)label, (GtkWidget *)dropdown); + + gtk_box_pack_start((GtkBox *)parent, (GtkWidget *)w, FALSE, FALSE, 0); + + gtk_widget_show_all(w); + + return (GtkWidget *)w; +} + +static void +name_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) +{ + e_source_set_name (sdialog->source, gtk_entry_get_text (GTK_ENTRY (sdialog->display_name))); +} + +static void +offline_status_changed_cb (GtkWidget *widget, AddressbookSourceDialog *sdialog) +{ + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) + e_source_set_property (sdialog->source, "offline_sync", "1"); + else + e_source_set_property (sdialog->source, "offline_sync", "0"); + +} + +static GtkWidget * +eabc_general_name(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + AddressbookSourceDialog *sdialog = data; + const gchar *uri; + GtkWidget *w; + GladeXML *gui; + gchar *gladefile; + + if (old) + return old; + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + GLADE_FILE_NAME, + NULL); + gui = glade_xml_new (gladefile, item->label, NULL); + g_free (gladefile); + + w = glade_xml_get_widget(gui, item->label); + gtk_box_pack_start((GtkBox *)parent, w, FALSE, FALSE, 0); + + sdialog->display_name = glade_xml_get_widget (gui, "account-editor-display-name-entry"); + g_signal_connect(sdialog->display_name, "changed", G_CALLBACK(name_changed_cb), sdialog); + gtk_entry_set_text((GtkEntry *)sdialog->display_name, e_source_peek_name(sdialog->source)); + + /* Hardcoded: groupwise can't edit the name (or anything else) */ + if (sdialog->original_source) { + uri = e_source_group_peek_base_uri (sdialog->source_group); + if (uri && strncmp(uri, "groupwise:", 10) == 0) { + gtk_widget_set_sensitive (GTK_WIDGET(sdialog->display_name), FALSE); + } + } + + g_object_unref(gui); + + return w; +} + + +static GtkWidget * +eabc_general_offline(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + AddressbookSourceDialog *sdialog = data; + GtkWidget *offline_setting; + const gchar *offline_sync; + gboolean is_local_book; + + is_local_book = g_str_has_prefix (e_source_group_peek_base_uri (sdialog->source_group), "file:"); + offline_sync = e_source_get_property (sdialog->source, "offline_sync"); + if (old) + return old; + else { + offline_setting = gtk_check_button_new_with_mnemonic (_("Copy _book content locally for offline operation")); + gtk_widget_show (offline_setting); + gtk_container_add (GTK_CONTAINER (parent), offline_setting); + g_signal_connect (offline_setting, "toggled", G_CALLBACK (offline_status_changed_cb), sdialog); + + } + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (offline_setting), (offline_sync && g_str_equal (offline_sync, "1")) ? TRUE : FALSE); + if (is_local_book) + gtk_widget_hide (offline_setting); + return offline_setting; + +} + +#ifdef HAVE_LDAP +static gchar * +form_ldap_search_filter (GtkWidget *w) +{ + gchar *filter; + const gchar *search_filter = gtk_entry_get_text ((GtkEntry *) w); + + /* this function can be used to format the search filter entered */ + if ((strlen (search_filter) !=0) && *search_filter != '(' && *(search_filter + (strlen (search_filter-1))) != ')') + filter = g_strdup_printf ("(%s)", search_filter); + else + filter = g_strdup_printf ("%s", search_filter); + + return filter; +} + +static void +url_changed(AddressbookSourceDialog *sdialog) +{ + gchar *str, *search_filter; + + search_filter = form_ldap_search_filter (sdialog->search_filter); + str = g_strdup_printf ("%s:%s/%s?" /* trigraph prevention */ "?%s?%s", + gtk_entry_get_text (GTK_ENTRY (sdialog->host)), + gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (sdialog->port_comboentry)))), + gtk_entry_get_text (GTK_ENTRY (sdialog->rootdn)), + ldap_unparse_scope (sdialog->scope), + search_filter); + e_source_set_relative_uri (sdialog->source, str); + g_free (search_filter); + g_free (str); +} + +static void +host_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) +{ + url_changed(sdialog); +} + +static void +port_entry_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) +{ + const gchar *port = gtk_entry_get_text((GtkEntry *)w); + + if (!strcmp (port, LDAPS_PORT_STRING)) { + sdialog->ssl = ADDRESSBOOK_LDAP_SSL_ALWAYS; + gtk_combo_box_set_active (GTK_COMBO_BOX (sdialog->ssl_combobox), sdialog->ssl); + gtk_widget_set_sensitive (sdialog->ssl_combobox, FALSE); + } else { + gtk_widget_set_sensitive (sdialog->ssl_combobox, TRUE); + } + + url_changed(sdialog); +} + +static void +ssl_combobox_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) +{ + sdialog->ssl = gtk_combo_box_get_active (GTK_COMBO_BOX (w)); + e_source_set_property (sdialog->source, "ssl", ldap_unparse_ssl (sdialog->ssl)); + + gtk_widget_set_tooltip_text (sdialog->ssl_combobox, ldap_get_ssl_tooltip (sdialog->ssl)); +} + + +static GtkWidget * +eabc_general_host(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + AddressbookSourceDialog *sdialog = data; + const gchar *tmp; + GtkWidget *w; + gchar *uri, port[16]; + LDAPURLDesc *lud; + GladeXML *gui; + gchar *gladefile; + + if (!source_group_is_remote(sdialog->source_group)) + return NULL; + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + GLADE_FILE_NAME, + NULL); + gui = glade_xml_new (gladefile, item->label, NULL); + g_free (gladefile); + + w = glade_xml_get_widget(gui, item->label); + gtk_box_pack_start((GtkBox *)parent, w, FALSE, FALSE, 0); + + uri = e_source_get_uri(sdialog->source); + if (ldap_url_parse(uri, &lud) != LDAP_SUCCESS) + lud = NULL; + g_free(uri); + + sdialog->host = glade_xml_get_widget (gui, "server-name-entry"); + gtk_entry_set_text((GtkEntry *)sdialog->host, lud && lud->lud_host ? lud->lud_host : ""); + g_signal_connect (sdialog->host, "changed", G_CALLBACK (host_changed_cb), sdialog); + + sdialog->port_comboentry = glade_xml_get_widget (gui, "port-comboentry"); + gtk_widget_set_has_tooltip (sdialog->port_comboentry, TRUE); + gtk_widget_set_tooltip_text (sdialog->port_comboentry, _("This is the port on the LDAP server that Evolution will try to connect to. A list of standard ports has been provided. Ask your system administrator what port you should specify.")); + sprintf(port, "%u", lud && lud->lud_port? lud->lud_port : LDAP_PORT); + gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (sdialog->port_comboentry))), port); + g_signal_connect (gtk_bin_get_child (GTK_BIN (sdialog->port_comboentry)), "changed", G_CALLBACK (port_entry_changed_cb), sdialog); + + if (lud) + ldap_free_urldesc (lud); + + sdialog->ssl_combobox = glade_xml_get_widget (gui, "ssl-combobox"); + gtk_widget_set_has_tooltip (sdialog->ssl_combobox, TRUE); + tmp = e_source_get_property (sdialog->source, "ssl"); + sdialog->ssl = tmp ? ldap_parse_ssl (tmp) : ADDRESSBOOK_LDAP_SSL_WHENEVER_POSSIBLE; + gtk_combo_box_set_active (GTK_COMBO_BOX (sdialog->ssl_combobox), sdialog->ssl); + gtk_widget_set_tooltip_text (sdialog->ssl_combobox, ldap_get_ssl_tooltip (sdialog->ssl)); + gtk_widget_set_sensitive (sdialog->ssl_combobox, strcmp (port, LDAPS_PORT_STRING) != 0); + g_signal_connect (sdialog->ssl_combobox, "changed", G_CALLBACK (ssl_combobox_changed_cb), sdialog); + + g_object_unref(gui); + + return w; +} + +static void +auth_entry_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) +{ + const gchar *principal = gtk_entry_get_text((GtkEntry *)w); + + /* seems messy ... but the api is */ + switch (sdialog->auth) { + case ADDRESSBOOK_LDAP_AUTH_SIMPLE_BINDDN: + e_source_set_property(sdialog->source, "email_addr", NULL); + e_source_set_property(sdialog->source, "binddn", principal); + break; + case ADDRESSBOOK_LDAP_AUTH_SIMPLE_EMAIL: + e_source_set_property(sdialog->source, "binddn", NULL); + e_source_set_property(sdialog->source, "email_addr", principal); + break; + case ADDRESSBOOK_LDAP_AUTH_NONE: + default: + e_source_set_property(sdialog->source, "email_addr", NULL); + e_source_set_property(sdialog->source, "binddn", NULL); + break; + } +} + +static void +auth_combobox_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) +{ + sdialog->auth = gtk_combo_box_get_active (GTK_COMBO_BOX (w)); + e_source_set_property (sdialog->source, "auth", ldap_unparse_auth (sdialog->auth)); + + /* make sure the right property is set for the auth - ugh, funny api */ + auth_entry_changed_cb(sdialog->auth_principal, sdialog); +} + +static GtkWidget * +eabc_general_auth(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + AddressbookSourceDialog *sdialog = data; + GtkWidget *w; + const gchar *tmp; + GladeXML *gui; + gchar *gladefile; + + if (!source_group_is_remote(sdialog->source_group)) + return NULL; + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + GLADE_FILE_NAME, + NULL); + gui = glade_xml_new (gladefile, item->label, NULL); + g_free (gladefile); + + w = glade_xml_get_widget(gui, item->label); + gtk_box_pack_start((GtkBox *)parent, w, FALSE, FALSE, 0); + + sdialog->auth_combobox = glade_xml_get_widget (gui, "auth-combobox"); + gtk_widget_set_has_tooltip (sdialog->auth_combobox, TRUE); + gtk_widget_set_tooltip_text (sdialog->auth_combobox, _("This is the method Evolution will use to authenticate you. Note that setting this to \"Email Address\" requires anonymous access to your LDAP server.")); + tmp = e_source_get_property(sdialog->source, "auth"); + sdialog->auth = tmp ? ldap_parse_auth(tmp) : ADDRESSBOOK_LDAP_AUTH_NONE; + gtk_combo_box_set_active (GTK_COMBO_BOX (sdialog->auth_combobox), sdialog->auth); + g_signal_connect (sdialog->auth_combobox, "changed", G_CALLBACK(auth_combobox_changed_cb), sdialog); + + sdialog->auth_principal = glade_xml_get_widget (gui, "auth-entry"); + switch (sdialog->auth) { + case ADDRESSBOOK_LDAP_AUTH_SIMPLE_EMAIL: + tmp = e_source_get_property(sdialog->source, "email_addr"); + break; + case ADDRESSBOOK_LDAP_AUTH_SIMPLE_BINDDN: + tmp = e_source_get_property(sdialog->source, "binddn"); + break; + case ADDRESSBOOK_LDAP_AUTH_NONE: + default: + tmp = ""; + break; + } + gtk_entry_set_text((GtkEntry *)sdialog->auth_principal, tmp?tmp:""); + g_signal_connect (sdialog->auth_principal, "changed", G_CALLBACK (auth_entry_changed_cb), sdialog); + + g_object_unref(gui); + + return w; +} + +static void +rootdn_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) +{ + url_changed(sdialog); +} + +static void +search_filter_changed_cb (GtkWidget *w, AddressbookSourceDialog *sdialog) +{ + url_changed (sdialog); +} + +static void +scope_combobox_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) +{ + sdialog->scope = gtk_combo_box_get_active (GTK_COMBO_BOX (w)); + url_changed(sdialog); +} + +static GtkWidget * +eabc_details_search(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + AddressbookSourceDialog *sdialog = data; + GtkWidget *w; + LDAPURLDesc *lud; + gchar *uri; + GladeXML *gui; + gchar *gladefile; + + if (!source_group_is_remote(sdialog->source_group)) + return NULL; + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + GLADE_FILE_NAME, + NULL); + gui = glade_xml_new (gladefile, item->label, NULL); + g_free (gladefile); + + w = glade_xml_get_widget(gui, item->label); + gtk_box_pack_start((GtkBox *)parent, w, FALSE, FALSE, 0); + + uri = e_source_get_uri(sdialog->source); + if (ldap_url_parse(uri, &lud) != LDAP_SUCCESS) + lud = NULL; + g_free(uri); + + sdialog->rootdn = glade_xml_get_widget (gui, "rootdn-entry"); + gtk_entry_set_text((GtkEntry *)sdialog->rootdn, lud && lud->lud_dn ? lud->lud_dn : ""); + g_signal_connect (sdialog->rootdn, "changed", G_CALLBACK (rootdn_changed_cb), sdialog); + + sdialog->scope_combobox = glade_xml_get_widget (gui, "scope-combobox"); + gtk_widget_set_has_tooltip (sdialog->scope_combobox, TRUE); + gtk_widget_set_tooltip_text (sdialog->scope_combobox, _("The search scope defines how deep you would like the search to extend down the directory tree. A search scope of \"sub\" will include all entries below your search base. A search scope of \"one\" will only include the entries one level beneath your base.")); + if (lud) { + switch (lud->lud_scope) { + case LDAP_SCOPE_BASE: + sdialog->scope = ADDRESSBOOK_LDAP_SCOPE_BASE; + break; + default: + case LDAP_SCOPE_ONELEVEL: + sdialog->scope = ADDRESSBOOK_LDAP_SCOPE_ONELEVEL; + break; + case LDAP_SCOPE_SUBTREE: + sdialog->scope = ADDRESSBOOK_LDAP_SCOPE_SUBTREE; + break; + } + } + gtk_combo_box_set_active (GTK_COMBO_BOX (sdialog->scope_combobox), sdialog->scope); + g_signal_connect (sdialog->scope_combobox, "changed", G_CALLBACK(scope_combobox_changed_cb), sdialog); + + sdialog->search_filter = glade_xml_get_widget (gui, "search-filter-entry"); + gtk_entry_set_text((GtkEntry *)sdialog->search_filter, lud && lud->lud_filter ? lud->lud_filter : ""); + g_signal_connect (sdialog->search_filter, "changed", G_CALLBACK (search_filter_changed_cb), sdialog); + + g_signal_connect (glade_xml_get_widget(gui, "rootdn-button"), "clicked", + G_CALLBACK(query_for_supported_bases), sdialog); + + if (lud) + ldap_free_urldesc (lud); + + g_object_unref(gui); + + return w; +} + +static void +timeout_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) +{ + gchar *timeout; + + timeout = g_strdup_printf("%f", gtk_adjustment_get_value(((GtkRange *)sdialog->timeout_scale)->adjustment)); + e_source_set_property(sdialog->source, "timeout", timeout); + g_free(timeout); +} + +static void +limit_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) +{ + gchar limit[16]; + + sprintf(limit, "%d", gtk_spin_button_get_value_as_int((GtkSpinButton *)sdialog->limit_spinbutton)); + e_source_set_property(sdialog->source, "limit", limit); +} + +static void +canbrowse_toggled_cb (GtkWidget *toggle_button, ESource *source) +{ + if (!source || !toggle_button) + return; + + e_source_set_property (source, "can-browse", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle_button)) ? "1" : NULL); +} + +static GtkWidget * +eabc_details_limit(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + AddressbookSourceDialog *sdialog = data; + GtkWidget *w; + const gchar *tmp; + GladeXML *gui; + gchar *gladefile; + + if (!source_group_is_remote(sdialog->source_group)) + return NULL; + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + GLADE_FILE_NAME, + NULL); + gui = glade_xml_new (gladefile, item->label, NULL); + g_free (gladefile); + + w = glade_xml_get_widget(gui, item->label); + gtk_box_pack_start((GtkBox *)parent, w, FALSE, FALSE, 0); + + sdialog->timeout_scale = glade_xml_get_widget (gui, "timeout-scale"); + tmp = e_source_get_property(sdialog->source, "timeout"); + gtk_adjustment_set_value(((GtkRange *)sdialog->timeout_scale)->adjustment, tmp?g_strtod(tmp, NULL):3.0); + g_signal_connect (GTK_RANGE(sdialog->timeout_scale)->adjustment, "value_changed", G_CALLBACK (timeout_changed_cb), sdialog); + + sdialog->limit_spinbutton = glade_xml_get_widget (gui, "download-limit-spinbutton"); + tmp = e_source_get_property(sdialog->source, "limit"); + gtk_spin_button_set_value((GtkSpinButton *)sdialog->limit_spinbutton, tmp?g_strtod(tmp, NULL):100.0); + g_signal_connect (sdialog->limit_spinbutton, "value_changed", G_CALLBACK (limit_changed_cb), sdialog); + + sdialog->canbrowsecheck = glade_xml_get_widget (gui, "canbrowsecheck"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sdialog->canbrowsecheck), e_source_get_property (sdialog->source, "can-browse") && strcmp (e_source_get_property (sdialog->source, "can-browse"), "1") == 0); + g_signal_connect (sdialog->canbrowsecheck, "toggled", G_CALLBACK (canbrowse_toggled_cb), sdialog->source); + + g_object_unref(gui); + + return w; +} +#endif + +static EConfigItem eabc_items[] = { + { E_CONFIG_BOOK, (gchar *) (gchar *) "", }, + { E_CONFIG_PAGE, (gchar *) "00.general", (gchar *) N_("General") }, + { E_CONFIG_SECTION, (gchar *) "00.general/10.display", (gchar *) N_("Address Book") }, + { E_CONFIG_ITEM, (gchar *) "00.general/10.display/10.name", (gchar *) "hbox122", eabc_general_name }, + { E_CONFIG_ITEM, (gchar *) "00.general/10.display/20.offline", NULL, eabc_general_offline }, +#ifdef HAVE_LDAP + { E_CONFIG_SECTION, (gchar *) "00.general/20.server", (gchar *) N_("Server Information") }, + { E_CONFIG_ITEM, (gchar *) "00.general/20.server/00.host", (gchar *) "table31", eabc_general_host }, + { E_CONFIG_SECTION, (gchar *) "00.general/30.auth", (gchar *) N_("Authentication") }, + { E_CONFIG_ITEM, (gchar *) "00.general/30.auth/00.auth", (gchar *) "table32", eabc_general_auth }, + + { E_CONFIG_PAGE, (gchar *) "10.details", (gchar *) N_("Details") }, + { E_CONFIG_SECTION, (gchar *) "10.details/00.search", (gchar *) N_("Searching") }, + { E_CONFIG_ITEM, (gchar *) "10.details/00.search/00.search", (gchar *) "table33", eabc_details_search }, + { E_CONFIG_SECTION, (gchar *) "10.details/10.limit", (gchar *) N_("Downloading") }, + { E_CONFIG_ITEM, (gchar *) "10.details/10.limit/00.limit", (gchar *) "table34", eabc_details_limit }, +#endif + { 0 }, +}; + +/* items needed for the 'new addressbook' window */ +static EConfigItem eabc_new_items[] = { + { E_CONFIG_ITEM, (gchar *) "00.general/10.display/00.type", NULL, eabc_general_type }, + { 0 }, +}; + +static void +eabc_commit(EConfig *ec, GSList *items, gpointer data) +{ + AddressbookSourceDialog *sdialog = data; + xmlNodePtr xml; +#if d(!)0 + gchar *txt; +#endif + if (sdialog->original_source) { + d(printf("committing addressbook changes\n")); + + /* these api's kinda suck */ + xml = xmlNewNode(NULL, (const guchar *)"dummy"); + e_source_dump_to_xml_node(sdialog->source, xml); + e_source_update_from_xml_node(sdialog->original_source, xml->children, NULL); + xmlFreeNode(xml); +#if d(!)0 + txt = e_source_to_standalone_xml(sdialog->original_source); + printf("source is now:\n%s\n", txt); + g_free(txt); +#endif + } else { + d(printf("committing new source\n")); + e_source_group_add_source(sdialog->source_group, sdialog->source, -1); + e_source_list_sync(sdialog->source_list, NULL); + } + +#if d(!)0 + txt = e_source_to_standalone_xml(sdialog->source); + printf("running source is now:\n%s\n", txt); + g_free(txt); +#endif +} + +static void +eabc_free(EConfig *ec, GSList *items, gpointer data) +{ + AddressbookSourceDialog *sdialog = data; + + g_slist_free(items); + + g_object_unref(sdialog->source); + if (sdialog->original_source) + g_object_unref(sdialog->original_source); + if (sdialog->source_list) + g_object_unref(sdialog->source_list); + g_slist_free(sdialog->menu_source_groups); + + g_object_unref(sdialog->gui); + + g_free(sdialog); +} + +static gboolean +eabc_check_complete(EConfig *ec, const gchar *pageid, gpointer data) +{ + AddressbookSourceDialog *sdialog = data; + gint valid = TRUE; + const gchar *tmp; + ESource *source; + + d(printf("check complete, pageid = '%s'\n", pageid?pageid:"")); + /* have name, and unique */ + tmp = e_source_peek_name(sdialog->source); + valid = tmp && tmp[0] != 0 + && ((source = e_source_group_peek_source_by_name(sdialog->source_group, tmp)) == NULL + || source == sdialog->original_source); + +#ifdef HAVE_LDAP + if (valid && source_group_is_remote(sdialog->source_group)) { + gchar *uri = e_source_get_uri(sdialog->source); + LDAPURLDesc *lud; + + /* check host and port set */ + if (ldap_url_parse(uri, &lud) == LDAP_SUCCESS) { + valid = lud->lud_host != NULL + && lud->lud_host[0] != 0 + && lud->lud_port != 0; + ldap_free_urldesc (lud); + } else + valid = FALSE; + g_free(uri); + + /* check auth name provided if auth set */ + if (valid && (tmp = e_source_get_property(sdialog->source, "auth"))) { + switch (ldap_parse_auth(tmp)) { + case ADDRESSBOOK_LDAP_AUTH_SIMPLE_EMAIL: + tmp = e_source_get_property(sdialog->source, "email_addr"); + break; + case ADDRESSBOOK_LDAP_AUTH_SIMPLE_BINDDN: + tmp = e_source_get_property(sdialog->source, "binddn"); + break; + default: + tmp = "dummy"; + break; + } + valid = tmp && tmp[0]; + } + + /* check timeout isn't too short (why don't we just force it?) */ + if (valid) { + tmp = e_source_get_property(sdialog->source, "timeout"); + valid = tmp && g_strtod(tmp, NULL) > 0.0; + } + } +#endif + return valid; +} + +/* debug only: */ +#if d(!)0 +static void +source_changed(ESource *source, AddressbookSourceDialog *sdialog) +{ + gchar *xml; + + xml = e_source_to_standalone_xml(source); + printf("source changed:\n%s\n", xml); + g_free(xml); +} +#endif + +GtkWidget* +addressbook_config_edit_source (GtkWidget *parent, ESource *source) +{ + AddressbookSourceDialog *sdialog = g_new0 (AddressbookSourceDialog, 1); + EABConfig *ec; + gint i; + GSList *items = NULL; + EABConfigTargetSource *target; + gchar *xml; + gchar *gladefile; + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + GLADE_FILE_NAME, + NULL); + sdialog->gui = glade_xml_new (gladefile, "account-editor-notebook", NULL); + g_free (gladefile); + + if (source) { + sdialog->original_source = source; + g_object_ref(source); + sdialog->source_group = e_source_peek_group (source); + xml = e_source_to_standalone_xml(source); + sdialog->source = e_source_new_from_standalone_xml(xml); + g_free(xml); + } else { + GConfClient *gconf; + GSList *l; + + sdialog->source = e_source_new("", ""); + gconf = gconf_client_get_default(); + sdialog->source_list = e_source_list_new_for_gconf(gconf, "/apps/evolution/addressbook/sources"); + l = e_source_list_peek_groups(sdialog->source_list); + if (!l) { + g_warning ("Address Book source groups are missing! Check your GConf setup."); + g_object_unref (gconf); + g_free (sdialog); + return NULL; + } + + sdialog->menu_source_groups = g_slist_copy(l); +#ifndef HAVE_LDAP + for (;l;l = g_slist_next(l)) + if (!strncmp("ldap:", e_source_group_peek_base_uri(l->data), 5)) + sdialog->menu_source_groups = g_slist_remove (sdialog->menu_source_groups, l->data); +#endif + sdialog->source_group = (ESourceGroup *)sdialog->menu_source_groups->data; + for (i=0;eabc_new_items[i].path;i++) + items = g_slist_prepend(items, &eabc_new_items[i]); + g_object_unref(gconf); + } + + /* HACK: doesn't work if you don't do this */ + e_source_set_group(sdialog->source, sdialog->source_group); + +#if d(!)0 + xml = e_source_to_standalone_xml(sdialog->source); + printf("but working standalone xml: %s\n", xml); + g_free(xml); + g_signal_connect(sdialog->source, "changed", source_changed, sdialog); +#endif + + sdialog->config = ec = eab_config_new(E_CONFIG_BOOK, "com.novell.evolution.addressbook.config.accountEditor"); + + for (i=0;eabc_items[i].path;i++) { + if (eabc_items[i].label) + eabc_items[i].label = gettext(eabc_items[i].label); + items = g_slist_prepend(items, &eabc_items[i]); + } + + e_config_add_items((EConfig *)ec, items, eabc_commit, NULL, eabc_free, sdialog); + e_config_add_page_check((EConfig *)ec, NULL, eabc_check_complete, sdialog); + + target = eab_config_target_new_source(ec, sdialog->source); + e_config_set_target((EConfig *)ec, (EConfigTarget *)target); + + if(source) + sdialog->window = e_config_create_window((EConfig *)ec, NULL, _("Address Book Properties")); + else + sdialog->window = e_config_create_window((EConfig *)ec, NULL, _("New Address Book")); + + + /* forces initial validation */ + if (!sdialog->original_source) + e_config_target_changed((EConfig *)ec, E_CONFIG_TARGET_CHANGED_STATE); + + return sdialog->window; +} diff --git a/modules/addressbook/addressbook-config.h b/modules/addressbook/addressbook-config.h new file mode 100644 index 0000000000..26c1788e51 --- /dev/null +++ b/modules/addressbook/addressbook-config.h @@ -0,0 +1,52 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Chris Toshok + * Chris Lahey + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __ADDRESSBOOK_CONFIG_H__ +#define __ADDRESSBOOK_CONFIG_H__ + +#include +#include + +typedef enum { + ADDRESSBOOK_LDAP_AUTH_NONE, + ADDRESSBOOK_LDAP_AUTH_SIMPLE_EMAIL, + ADDRESSBOOK_LDAP_AUTH_SIMPLE_BINDDN +} AddressbookLDAPAuthType; + +typedef enum { + ADDRESSBOOK_LDAP_SCOPE_ONELEVEL, + ADDRESSBOOK_LDAP_SCOPE_SUBTREE, + ADDRESSBOOK_LDAP_SCOPE_BASE, + ADDRESSBOOK_LDAP_SCOPE_LAST +} AddressbookLDAPScopeType; + +typedef enum { + ADDRESSBOOK_LDAP_SSL_ALWAYS, + ADDRESSBOOK_LDAP_SSL_WHENEVER_POSSIBLE, + ADDRESSBOOK_LDAP_SSL_NEVER +} AddressbookLDAPSSLType; + +GtkWidget* addressbook_config_edit_source (GtkWidget *parent, ESource *source); +GtkWidget* addressbook_config_create_new_source (GtkWidget *parent); + +#endif /* __ADDRESSBOOK_CONFIG_H__ */ diff --git a/modules/addressbook/apps_evolution_addressbook.schemas.in b/modules/addressbook/apps_evolution_addressbook.schemas.in new file mode 100644 index 0000000000..4a336409df --- /dev/null +++ b/modules/addressbook/apps_evolution_addressbook.schemas.in @@ -0,0 +1,82 @@ + + + + + + + /schemas/apps/evolution/addressbook/completion/uris + /apps/evolution/addressbook/completion/uris + evolution-addressbook + string + + + EFolderList XML for the list of completion URIs + EFolderList XML for the list of completion URIs. + + + + + /schemas/apps/evolution/addressbook/completion/minimum_query_length + /apps/evolution/addressbook/completion/minimum_query_length + evolution-addressbook + int + 3 + + Autocomplete length + The number of characters that must be typed before Evolution will attempt to autocomplete. + + + + + /schemas/apps/evolution/addressbook/completion/show_address + /apps/evolution/addressbook/completion/show_address + evolution-addressbook + bool + false + + Show autocompleted name with an address + Whether force showing the mail address with the name of the autocompleted contact in the entry. + + + + + + + /schemas/apps/evolution/addressbook/select_names/last_used_uri + /apps/evolution/addressbook/select_names/last_used_uri + evolution-addressbook + string + + + URI for the folder last used in the select names dialog + URI for the folder last used in the select names dialog. + + + + + + + /schemas/apps/evolution/addressbook/display/vpane_position + /apps/evolution/addressbook/display/vpane_position + evolution-addressbook + int + + Vertical pane position + Position of the vertical pane, between the card and list views and the preview pane, in pixels. + + + + + /schemas/apps/evolution/addressbook/display/show_preview + /apps/evolution/addressbook/display/show_preview + evolution-addressbook + bool + true + + Show preview pane + Whether to show the preview pane. + + + + + diff --git a/modules/addressbook/autocompletion-config.c b/modules/addressbook/autocompletion-config.c new file mode 100644 index 0000000000..370c1a1e7e --- /dev/null +++ b/modules/addressbook/autocompletion-config.c @@ -0,0 +1,137 @@ +/* + * e-shell-config-autocompletion.h - Configuration page for addressbook autocompletion. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Chris Toshok + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "autocompletion-config.h" + +#include +#include +#include +#include +#include + +#include "widgets/misc/e-preferences-window.h" + +static void +source_selection_changed_cb (ESourceSelector *source_selector) +{ + ESourceList *source_list; + GSList *selection; + GSList *l; + GSList *groups; + + source_list = e_source_selector_get_source_list (source_selector); + + /* first we clear all the completion flags from all sources */ + for (groups = e_source_list_peek_groups (source_list); groups; groups = groups->next) { + ESourceGroup *group = E_SOURCE_GROUP (groups->data); + GSList *sources; + + for (sources = e_source_group_peek_sources (group); sources; sources = sources->next) { + ESource *source = E_SOURCE (sources->data); + + e_source_set_property (source, "completion", NULL); + } + } + + /* then we loop over the selector's selection, setting the + property on those sources */ + selection = e_source_selector_get_selection (source_selector); + for (l = selection; l; l = l->next) { + ESource *source = E_SOURCE (l->data); + + e_source_set_property (source, "completion", "true"); + } + e_source_selector_free_selection (selection); + + /* XXX we should pop up a dialog if this fails */ + e_source_list_sync (source_list, NULL); +} + +static void +initialize_selection (ESourceSelector *source_selector) +{ + ESourceList *source_list; + GSList *groups; + + source_list = e_source_selector_get_source_list (source_selector); + + for (groups = e_source_list_peek_groups (source_list); groups; groups = groups->next) { + ESourceGroup *group = E_SOURCE_GROUP (groups->data); + GSList *sources; + + for (sources = e_source_group_peek_sources (group); sources; sources = sources->next) { + ESource *source = E_SOURCE (sources->data); + const gchar *completion; + + completion = e_source_get_property (source, "completion"); + if (completion && !g_ascii_strcasecmp (completion, "true")) + e_source_selector_select_source (source_selector, source); + } + } +} + +void +autocompletion_config_init (EShell *shell) +{ + ESourceList *source_list; + GtkWidget *scrolled_window; + GtkWidget *source_selector; + GtkWidget *preferences_window; + + g_return_if_fail (E_IS_SHELL (shell)); + + source_list = e_source_list_new_for_gconf_default ( + "/apps/evolution/addressbook/sources"); + + /* XXX should we watch for the source list to change and + update it in the control? what about our local changes? */ + /* g_signal_connect (ac->source_list, "changed", G_CALLBACK (source_list_changed), ac); */ + + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN); + gtk_widget_show (scrolled_window); + + source_selector = e_source_selector_new (source_list); + g_signal_connect ( + source_selector, "selection_changed", + G_CALLBACK (source_selection_changed_cb), NULL); + gtk_container_add (GTK_CONTAINER (scrolled_window), source_selector); + gtk_widget_show (source_selector); + + initialize_selection (E_SOURCE_SELECTOR (source_selector)); + + preferences_window = e_shell_get_preferences_window (shell); + + e_preferences_window_add_page ( + E_PREFERENCES_WINDOW (preferences_window), + "autocompletion", + "preferences-autocompletion", + _("Autocompletion"), + scrolled_window, + 200); +} diff --git a/modules/addressbook/autocompletion-config.h b/modules/addressbook/autocompletion-config.h new file mode 100644 index 0000000000..5769bdce9d --- /dev/null +++ b/modules/addressbook/autocompletion-config.h @@ -0,0 +1,37 @@ +/* + * e-shell-config-autocompletion.h - Configuration page for addressbook autocompletion. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Chris Toshok + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef _AUTOCOMPLETION_CONFIG_H +#define _AUTOCOMPLETION_CONFIG_H + +#include +#include + +G_BEGIN_DECLS + +void autocompletion_config_init (EShell *shell); + +G_END_DECLS + +#endif /* _AUTOCOMPLETION_CONFIG_H */ diff --git a/modules/addressbook/e-book-shell-backend.c b/modules/addressbook/e-book-shell-backend.c new file mode 100644 index 0000000000..68af7ed03b --- /dev/null +++ b/modules/addressbook/e-book-shell-backend.c @@ -0,0 +1,576 @@ +/* + * e-book-shell-backend.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-book-shell-backend.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "shell/e-shell.h" +#include "shell/e-shell-window.h" + +#include "e-util/e-import.h" +#include "addressbook/gui/widgets/eab-gui-util.h" +#include "addressbook/gui/contact-editor/e-contact-editor.h" +#include "addressbook/gui/contact-list-editor/e-contact-list-editor.h" +#include "addressbook/importers/evolution-addressbook-importers.h" + +#include "eab-config.h" +#include "addressbook-config.h" +#include "autocompletion-config.h" + +#include "e-book-shell-migrate.h" +#include "e-book-shell-view.h" + +#ifdef ENABLE_SMIME +#include "smime/gui/component.h" +#include "smime/gui/certificate-manager.h" +#endif + +#define E_BOOK_SHELL_BACKEND_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_BOOK_SHELL_BACKEND, EBookShellBackendPrivate)) + +#define LDAP_BASE_URI "ldap://" +#define PERSONAL_RELATIVE_URI "system" + +struct _EBookShellBackendPrivate { + ESourceList *source_list; +}; + +enum { + PROP_0, + PROP_SOURCE_LIST +}; + +static gpointer parent_class; +static GType book_shell_backend_type; + +static void +book_shell_backend_ensure_sources (EShellBackend *shell_backend) +{ + /* XXX This is basically the same algorithm across all backends. + * Maybe we could somehow integrate this into EShellBackend? */ + + EBookShellBackendPrivate *priv; + ESourceGroup *on_this_computer; + ESourceGroup *on_ldap_servers; + ESource *personal; + GSList *groups, *iter; + const gchar *data_dir; + const gchar *name; + gchar *base_uri; + gchar *filename; + + on_this_computer = NULL; + on_ldap_servers = NULL; + personal = NULL; + + priv = E_BOOK_SHELL_BACKEND_GET_PRIVATE (shell_backend); + + if (!e_book_get_addressbooks (&priv->source_list, NULL)) { + g_warning ("Could not get addressbook sources from GConf!"); + return; + } + + data_dir = e_shell_backend_get_data_dir (shell_backend); + filename = g_build_filename (data_dir, "local", NULL); + base_uri = g_filename_to_uri (filename, NULL, NULL); + g_free (filename); + + groups = e_source_list_peek_groups (priv->source_list); + for (iter = groups; iter != NULL; iter = iter->next) { + ESourceGroup *source_group = iter->data; + const gchar *group_base_uri; + + group_base_uri = e_source_group_peek_base_uri (source_group); + + /* Compare only "file://" part. If the user's home + * changes, we do not want to create another group. */ + if (on_this_computer == NULL && + strncmp (base_uri, group_base_uri, 7) == 0) + on_this_computer = source_group; + + else if (on_ldap_servers == NULL && + strcmp (LDAP_BASE_URI, group_base_uri) == 0) + on_ldap_servers = source_group; + } + + name = _("On This Computer"); + + if (on_this_computer != NULL) { + GSList *sources; + const gchar *group_base_uri; + + /* Force the group name to the current locale. */ + e_source_group_set_name (on_this_computer, name); + + sources = e_source_group_peek_sources (on_this_computer); + group_base_uri = e_source_group_peek_base_uri (on_this_computer); + + /* Make sure this group includes a "Personal" source. */ + for (iter = sources; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + const gchar *relative_uri; + + relative_uri = e_source_peek_relative_uri (source); + if (relative_uri == NULL) + continue; + + if (strcmp (PERSONAL_RELATIVE_URI, relative_uri) != 0) + continue; + + personal = source; + break; + } + + /* Make sure we have the correct base URI. This can + * change when the user's home directory changes. */ + if (strcmp (base_uri, group_base_uri) != 0) { + e_source_group_set_base_uri ( + on_this_computer, base_uri); + + /* XXX We shouldn't need this sync call here as + * set_base_uri() results in synching to GConf, + * but that happens in an idle loop and too late + * to prevent the user from seeing a "Cannot + * Open ... because of invalid URI" error. */ + e_source_list_sync (priv->source_list, NULL); + } + + } else { + ESourceGroup *source_group; + + source_group = e_source_group_new (name, base_uri); + e_source_list_add_group (priv->source_list, source_group, -1); + g_object_unref (source_group); + } + + name = _("Personal"); + + if (personal == NULL) { + ESource *source; + + /* Create the default Personal address book. */ + source = e_source_new (name, PERSONAL_RELATIVE_URI); + e_source_group_add_source (on_this_computer, source, -1); + e_source_set_property (source, "completion", "true"); + g_object_unref (source); + } else { + /* Force the source name to the current locale. */ + e_source_set_name (personal, name); + } + + name = _("On LDAP Servers"); + + if (on_ldap_servers == NULL) { + ESourceGroup *source_group; + + source_group = e_source_group_new (name, LDAP_BASE_URI); + e_source_list_add_group (priv->source_list, source_group, -1); + g_object_unref (source_group); + } else { + /* Force the group name to the current locale. */ + e_source_group_set_name (on_ldap_servers, name); + } + + g_free (base_uri); +} + +static void +book_shell_backend_init_importers (void) +{ + EImportClass *import_class; + EImportImporter *importer; + + import_class = g_type_class_ref (e_import_get_type ()); + + importer = evolution_ldif_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); + + importer = evolution_vcard_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); + + importer = evolution_csv_outlook_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); + + importer = evolution_csv_mozilla_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); + + importer = evolution_csv_evolution_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); +} + +static void +book_shell_backend_book_loaded_cb (EBook *book, + EBookStatus status, + gpointer user_data) +{ + EContact *contact; + GtkAction *action; + GtkWidget *editor; + const gchar *action_name; + + /* XXX Handle errors better. */ + if (status != E_BOOK_ERROR_OK) + return; + + contact = e_contact_new (); + action = GTK_ACTION (user_data); + action_name = gtk_action_get_name (action); + + if (strcmp (action_name, "contact-new") == 0) + editor = e_contact_editor_new (book, contact, TRUE, TRUE); + + if (strcmp (action_name, "contact-new-list") == 0) + editor = e_contact_list_editor_new (book, contact, TRUE, TRUE); + + eab_editor_show (EAB_EDITOR (editor)); + + g_object_unref (contact); + g_object_unref (book); +} + +static void +action_contact_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + EShell *shell; + EBook *book = NULL; + GConfClient *client; + ESourceList *source_list; + const gchar *key; + gchar *uid; + + /* This callback is used for both contacts and contact lists. */ + + if (!e_book_get_addressbooks (&source_list, NULL)) { + g_warning ("Could not get addressbook sources from GConf!"); + return; + } + + shell = e_shell_window_get_shell (shell_window); + client = e_shell_get_gconf_client (shell); + + key = "/apps/evolution/addressbook/display/primary_addressbook"; + uid = gconf_client_get_string (client, key, NULL); + + if (uid != NULL) { + ESource *source; + + source = e_source_list_peek_source_by_uid (source_list, uid); + if (source != NULL) + book = e_book_new (source, NULL); + g_free (uid); + } + + if (book == NULL) + book = e_book_new_default_addressbook (NULL); + + e_book_async_open ( + book, FALSE, book_shell_backend_book_loaded_cb, action); +} + +static void +action_address_book_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + addressbook_config_create_new_source (NULL); +} + +static GtkActionEntry item_entries[] = { + + { "contact-new", + "contact-new", + NC_("New", "_Contact"), + "c", + N_("Create a new contact"), + G_CALLBACK (action_contact_new_cb) }, + + { "contact-new-list", + "stock_contact-list", + N_("Contact _List"), + "l", + N_("Create a new contact list"), + G_CALLBACK (action_contact_new_cb) } +}; + +static GtkActionEntry source_entries[] = { + + { "address-book-new", + "address-book-new", + NC_("New", "Address _Book"), + NULL, + N_("Create a new address book"), + G_CALLBACK (action_address_book_new_cb) } +}; + +static gboolean +book_shell_backend_handle_uri_cb (EShellBackend *shell_backend, + const gchar *uri) +{ + EUri *euri; + const gchar *cp; + gchar *source_uid = NULL; + gchar *contact_uid = NULL; + + if (!g_str_has_prefix (uri, "contacts:")) + return FALSE; + + euri = e_uri_new (uri); + cp = euri->query; + + if (cp == NULL) { + e_uri_free (euri); + return FALSE; + } + + while (*cp != '\0') { + gchar *header; + gchar *content; + gsize length; + gsize content_length; + + length = strcspn (cp, "=&"); + + /* If it's malformed, give up. */ + if (cp[length] != '=') + break; + + header = (gchar *) cp; + header[length] = '\0'; + cp += length + 1; + + content_length = strcspn (cp, "&"); + content = g_strndup (cp, content_length); + + if (g_ascii_strcasecmp (header, "source-uid") == 0) + source_uid = g_strdup (content); + + if (g_ascii_strcasecmp (header, "contact-uid") == 0) + contact_uid = g_strdup (content); + + g_free (content); + + cp += content_length; + if (*cp == '&') { + cp++; + if (strcmp (cp, "amp;")) + cp += 4; + } + } + + /* FIXME */ + /*addressbook_view_edit_contact (view, source_uid, contact_uid);*/ + + g_free (source_uid); + g_free (contact_uid); + + e_uri_free (euri); + + return TRUE; +} + +static void +book_shell_backend_window_created_cb (EShellBackend *shell_backend, + GtkWindow *window) +{ + const gchar *backend_name; + + if (!E_IS_SHELL_WINDOW (window)) + return; + + backend_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name; + + e_shell_window_register_new_item_actions ( + E_SHELL_WINDOW (window), backend_name, + item_entries, G_N_ELEMENTS (item_entries)); + + e_shell_window_register_new_source_actions ( + E_SHELL_WINDOW (window), backend_name, + source_entries, G_N_ELEMENTS (source_entries)); +} + +static void +book_shell_backend_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SOURCE_LIST: + g_value_set_object ( + value, + e_book_shell_backend_get_source_list ( + E_BOOK_SHELL_BACKEND (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +book_shell_backend_dispose (GObject *object) +{ + EBookShellBackendPrivate *priv; + + priv = E_BOOK_SHELL_BACKEND_GET_PRIVATE (object); + + if (priv->source_list != NULL) { + g_object_unref (priv->source_list); + priv->source_list = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +book_shell_backend_constructed (GObject *object) +{ + EShell *shell; + EShellBackend *shell_backend; + + shell_backend = E_SHELL_BACKEND (object); + shell = e_shell_backend_get_shell (shell_backend); + + /* XXX Why is this here? Address books aren't the only + * things that use S/MIME. Maybe put it in EShell? */ +#ifdef ENABLE_SMIME + smime_component_init (); + certificate_manager_config_init (shell); +#endif + + book_shell_backend_init_importers (); + book_shell_backend_ensure_sources (shell_backend); + + e_plugin_hook_register_type (eab_config_get_type ()); + + g_signal_connect_swapped ( + shell, "handle-uri", + G_CALLBACK (book_shell_backend_handle_uri_cb), + shell_backend); + + g_signal_connect_swapped ( + shell, "window-created", + G_CALLBACK (book_shell_backend_window_created_cb), + shell_backend); + + autocompletion_config_init (shell); +} + +static gboolean +book_shell_backend_is_busy (EShellBackend *shell_backend) +{ + return !eab_editor_request_close_all (); +} + +static gboolean +book_shell_backend_shutdown (EShellBackend *shell_backend) +{ + /* FIXME */ + return TRUE; +} + +static void +book_shell_backend_class_init (EBookShellBackendClass *class) +{ + GObjectClass *object_class; + EShellBackendClass *shell_backend_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EBookShellBackendPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->get_property = book_shell_backend_get_property; + object_class->dispose = book_shell_backend_dispose; + object_class->constructed = book_shell_backend_constructed; + + shell_backend_class = E_SHELL_BACKEND_CLASS (class); + shell_backend_class->shell_view_type = E_TYPE_BOOK_SHELL_VIEW; + shell_backend_class->name = "addressbook"; + shell_backend_class->aliases = "contacts"; + shell_backend_class->schemes = ""; + shell_backend_class->sort_order = 300; + shell_backend_class->start = NULL; + shell_backend_class->is_busy = book_shell_backend_is_busy; + shell_backend_class->shutdown = book_shell_backend_shutdown; + shell_backend_class->migrate = e_book_shell_backend_migrate; + + g_object_class_install_property ( + object_class, + PROP_SOURCE_LIST, + g_param_spec_object ( + "source-list", + _("Source List"), + _("The registry of address books"), + E_TYPE_SOURCE_LIST, + G_PARAM_READABLE)); +} + +static void +book_shell_backend_init (EBookShellBackend *book_shell_backend) +{ + book_shell_backend->priv = + E_BOOK_SHELL_BACKEND_GET_PRIVATE (book_shell_backend); +} + +GType +e_book_shell_backend_get_type (void) +{ + return book_shell_backend_type; +} + +void +e_book_shell_backend_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (EBookShellBackendClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) book_shell_backend_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EBookShellBackend), + 0, /* n_preallocs */ + (GInstanceInitFunc) book_shell_backend_init, + NULL /* value_table */ + }; + + book_shell_backend_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_BACKEND, + "EBookShellBackend", &type_info, 0); +} + +ESourceList * +e_book_shell_backend_get_source_list (EBookShellBackend *book_shell_backend) +{ + g_return_val_if_fail ( + E_IS_BOOK_SHELL_BACKEND (book_shell_backend), NULL); + + return book_shell_backend->priv->source_list; +} diff --git a/modules/addressbook/e-book-shell-backend.h b/modules/addressbook/e-book-shell-backend.h new file mode 100644 index 0000000000..c61e43b814 --- /dev/null +++ b/modules/addressbook/e-book-shell-backend.h @@ -0,0 +1,70 @@ +/* + * e-book-shell-backend.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_BOOK_SHELL_BACKEND_H +#define E_BOOK_SHELL_BACKEND_H + +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_BOOK_SHELL_BACKEND \ + (e_book_shell_backend_get_type ()) +#define E_BOOK_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_BOOK_SHELL_BACKEND, EBookShellBackend)) +#define E_BOOK_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_BOOK_SHELL_BACKEND, EBookShellBackendClass)) +#define E_IS_BOOK_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_BOOK_SHELL_BACKEND)) +#define E_IS_BOOK_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_BOOK_SHELL_BACKEND)) +#define E_BOOK_SHELL_BACKEND_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_BOOK_SHELL_BACKEND, EBookShellBackendClass)) + +G_BEGIN_DECLS + +typedef struct _EBookShellBackend EBookShellBackend; +typedef struct _EBookShellBackendClass EBookShellBackendClass; +typedef struct _EBookShellBackendPrivate EBookShellBackendPrivate; + +struct _EBookShellBackend { + EShellBackend parent; + EBookShellBackendPrivate *priv; +}; + +struct _EBookShellBackendClass { + EShellBackendClass parent_class; +}; + +GType e_book_shell_backend_get_type (void); +void e_book_shell_backend_register_type + (GTypeModule *type_module); +ESourceList * e_book_shell_backend_get_source_list + (EBookShellBackend *book_shell_backend); + +G_END_DECLS + +#endif /* E_BOOK_SHELL_BACKEND_H */ diff --git a/modules/addressbook/e-book-shell-content.c b/modules/addressbook/e-book-shell-content.c new file mode 100644 index 0000000000..cce03b1575 --- /dev/null +++ b/modules/addressbook/e-book-shell-content.c @@ -0,0 +1,492 @@ +/* + * e-book-shell-content.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-book-shell-content.h" + +#include + +#include "e-util/gconf-bridge.h" + +#define E_BOOK_SHELL_CONTENT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_BOOK_SHELL_CONTENT, EBookShellContentPrivate)) + +struct _EBookShellContentPrivate { + GtkWidget *paned; + GtkWidget *notebook; + GtkWidget *preview; +}; + +enum { + PROP_0, + PROP_CURRENT_VIEW, + PROP_PREVIEW_CONTACT, + PROP_PREVIEW_VISIBLE +}; + +static gpointer parent_class; +static GType book_shell_view_type; + +static void +book_shell_content_send_message_cb (EBookShellContent *book_shell_content, + EDestination *destination, + EABContactDisplay *display) +{ + GList node = { destination, NULL, NULL }; + + eab_send_as_to (&node); +} + +static void +book_shell_content_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CURRENT_VIEW: + e_book_shell_content_set_current_view ( + E_BOOK_SHELL_CONTENT (object), + g_value_get_object (value)); + return; + + case PROP_PREVIEW_CONTACT: + e_book_shell_content_set_preview_contact ( + E_BOOK_SHELL_CONTENT (object), + g_value_get_object (value)); + return; + + case PROP_PREVIEW_VISIBLE: + e_book_shell_content_set_preview_visible ( + E_BOOK_SHELL_CONTENT (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +book_shell_content_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CURRENT_VIEW: + g_value_set_object ( + value, e_book_shell_content_get_current_view ( + E_BOOK_SHELL_CONTENT (object))); + return; + + case PROP_PREVIEW_CONTACT: + g_value_set_object ( + value, e_book_shell_content_get_preview_contact ( + E_BOOK_SHELL_CONTENT (object))); + return; + + case PROP_PREVIEW_VISIBLE: + g_value_set_boolean ( + value, e_book_shell_content_get_preview_visible ( + E_BOOK_SHELL_CONTENT (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +book_shell_content_dispose (GObject *object) +{ + EBookShellContentPrivate *priv; + + priv = E_BOOK_SHELL_CONTENT_GET_PRIVATE (object); + + if (priv->paned != NULL) { + g_object_unref (priv->paned); + priv->paned = NULL; + } + + if (priv->notebook != NULL) { + g_object_unref (priv->notebook); + priv->notebook = NULL; + } + + if (priv->preview != NULL) { + g_object_unref (priv->preview); + priv->preview = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +book_shell_content_constructed (GObject *object) +{ + EBookShellContentPrivate *priv; + GConfBridge *bridge; + GtkWidget *container; + GtkWidget *widget; + const gchar *key; + + priv = E_BOOK_SHELL_CONTENT_GET_PRIVATE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + container = GTK_WIDGET (object); + + widget = gtk_vpaned_new (); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->paned = g_object_ref (widget); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_notebook_new (); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE); + gtk_notebook_set_show_border (GTK_NOTEBOOK (widget), FALSE); + gtk_paned_add1 (GTK_PANED (container), widget); + priv->notebook = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_paned_add2 (GTK_PANED (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = eab_contact_display_new (); + eab_contact_display_set_mode ( + EAB_CONTACT_DISPLAY (widget), + EAB_CONTACT_DISPLAY_RENDER_NORMAL); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->preview = g_object_ref (widget); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + priv->preview, "send-message", + G_CALLBACK (book_shell_content_send_message_cb), object); + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (priv->paned); + key = "/apps/evolution/addressbook/display/vpane_position"; + gconf_bridge_bind_property_delayed (bridge, key, object, "position"); +} + +static guint32 +book_shell_content_check_state (EShellContent *shell_content) +{ + EBookShellContent *book_shell_content; + ESelectionModel *selection_model; + EAddressbookModel *model; + EAddressbookView *view; + guint32 state = 0; + gint n_contacts; + gint n_selected; + + book_shell_content = E_BOOK_SHELL_CONTENT (shell_content); + view = e_book_shell_content_get_current_view (book_shell_content); + model = e_addressbook_view_get_model (view); + + selection_model = e_addressbook_view_get_selection_model (view); + n_contacts = (selection_model != NULL) ? + e_selection_model_row_count (selection_model) : 0; + n_selected = (selection_model != NULL) ? + e_selection_model_selected_count (selection_model) : 0; + + /* FIXME Finish the rest of the flags. */ + if (n_selected == 1) + state |= E_BOOK_SHELL_CONTENT_SELECTION_SINGLE; + if (n_selected > 1) + state |= E_BOOK_SHELL_CONTENT_SELECTION_MULTIPLE; + if (e_addressbook_model_can_stop (model)) + state |= E_BOOK_SHELL_CONTENT_SOURCE_IS_BUSY; + if (e_addressbook_model_get_editable (model)) + state |= E_BOOK_SHELL_CONTENT_SOURCE_IS_EDITABLE; + if (n_contacts == 0) + state |= E_BOOK_SHELL_CONTENT_SOURCE_IS_EMPTY; + + return state; +} + +static void +book_shell_content_class_init (EBookShellContentClass *class) +{ + GObjectClass *object_class; + EShellContentClass *shell_content_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EBookShellContentPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = book_shell_content_set_property; + object_class->get_property = book_shell_content_get_property; + object_class->dispose = book_shell_content_dispose; + object_class->constructed = book_shell_content_constructed; + + shell_content_class = E_SHELL_CONTENT_CLASS (class); + shell_content_class->check_state = book_shell_content_check_state; + + g_object_class_install_property ( + object_class, + PROP_CURRENT_VIEW, + g_param_spec_object ( + "current-view", + _("Current View"), + _("The currently selected address book view"), + E_TYPE_ADDRESSBOOK_VIEW, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_PREVIEW_CONTACT, + g_param_spec_object ( + "preview-contact", + _("Previewed Contact"), + _("The contact being shown in the preview pane"), + E_TYPE_CONTACT, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_PREVIEW_VISIBLE, + g_param_spec_boolean ( + "preview-visible", + _("Preview is Visible"), + _("Whether the preview pane is visible"), + TRUE, + G_PARAM_READWRITE)); +} + +static void +book_shell_content_init (EBookShellContent *book_shell_content) +{ + book_shell_content->priv = + E_BOOK_SHELL_CONTENT_GET_PRIVATE (book_shell_content); + + /* Postpone widget construction until we have a shell view. */ +} + +GType +e_book_shell_content_get_type (void) +{ + return book_shell_view_type; +} + +void +e_book_shell_content_register_type (GTypeModule *type_module) +{ + static const GTypeInfo type_info = { + sizeof (EBookShellContentClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) book_shell_content_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EBookShellContent), + 0, /* n_preallocs */ + (GInstanceInitFunc) book_shell_content_init, + NULL /* value_table */ + }; + + book_shell_view_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_CONTENT, + "EBookShellContent", &type_info, 0); +} + +GtkWidget * +e_book_shell_content_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_BOOK_SHELL_CONTENT, + "shell-view", shell_view, NULL); +} + +void +e_book_shell_content_insert_view (EBookShellContent *book_shell_content, + EAddressbookView *addressbook_view) +{ + GtkNotebook *notebook; + GtkWidget *child; + + g_return_if_fail (E_IS_BOOK_SHELL_CONTENT (book_shell_content)); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (addressbook_view)); + + notebook = GTK_NOTEBOOK (book_shell_content->priv->notebook); + child = GTK_WIDGET (addressbook_view); + gtk_notebook_append_page (notebook, child, NULL); +} + +void +e_book_shell_content_remove_view (EBookShellContent *book_shell_content, + EAddressbookView *addressbook_view) +{ + GtkNotebook *notebook; + GtkWidget *child; + gint page_num; + + g_return_if_fail (E_IS_BOOK_SHELL_CONTENT (book_shell_content)); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (addressbook_view)); + + notebook = GTK_NOTEBOOK (book_shell_content->priv->notebook); + child = GTK_WIDGET (addressbook_view); + page_num = gtk_notebook_page_num (notebook, child); + g_return_if_fail (page_num >= 0); + + gtk_notebook_remove_page (notebook, page_num); +} + +EAddressbookView * +e_book_shell_content_get_current_view (EBookShellContent *book_shell_content) +{ + GtkNotebook *notebook; + GtkWidget *widget; + gint page_num; + + g_return_val_if_fail ( + E_IS_BOOK_SHELL_CONTENT (book_shell_content), NULL); + + notebook = GTK_NOTEBOOK (book_shell_content->priv->notebook); + page_num = gtk_notebook_get_current_page (notebook); + widget = gtk_notebook_get_nth_page (notebook, page_num); + g_return_val_if_fail (widget != NULL, NULL); + + return E_ADDRESSBOOK_VIEW (widget); +} + +void +e_book_shell_content_set_current_view (EBookShellContent *book_shell_content, + EAddressbookView *addressbook_view) +{ + GtkNotebook *notebook; + GtkWidget *child; + gint page_num; + + g_return_if_fail (E_IS_BOOK_SHELL_CONTENT (book_shell_content)); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (addressbook_view)); + + notebook = GTK_NOTEBOOK (book_shell_content->priv->notebook); + child = GTK_WIDGET (addressbook_view); + page_num = gtk_notebook_page_num (notebook, child); + g_return_if_fail (page_num >= 0); + + gtk_notebook_set_current_page (notebook, page_num); + g_object_notify (G_OBJECT (book_shell_content), "current-view"); +} + +EContact * +e_book_shell_content_get_preview_contact (EBookShellContent *book_shell_content) +{ + EABContactDisplay *display; + + g_return_val_if_fail ( + E_IS_BOOK_SHELL_CONTENT (book_shell_content), NULL); + + display = EAB_CONTACT_DISPLAY (book_shell_content->priv->preview); + + return eab_contact_display_get_contact (display); +} + +void +e_book_shell_content_set_preview_contact (EBookShellContent *book_shell_content, + EContact *preview_contact) +{ + EABContactDisplay *display; + + g_return_if_fail (E_IS_BOOK_SHELL_CONTENT (book_shell_content)); + + display = EAB_CONTACT_DISPLAY (book_shell_content->priv->preview); + + eab_contact_display_set_contact (display, preview_contact); + g_object_notify (G_OBJECT (book_shell_content), "preview-contact"); +} + +gboolean +e_book_shell_content_get_preview_visible (EBookShellContent *book_shell_content) +{ + GtkPaned *paned; + GtkWidget *child; + + g_return_val_if_fail ( + E_IS_BOOK_SHELL_CONTENT (book_shell_content), FALSE); + + paned = GTK_PANED (book_shell_content->priv->paned); + child = gtk_paned_get_child2 (paned); + + return GTK_WIDGET_VISIBLE (child); +} + +void +e_book_shell_content_set_preview_visible (EBookShellContent *book_shell_content, + gboolean preview_visible) +{ + GtkPaned *paned; + GtkWidget *child; + + g_return_if_fail (E_IS_BOOK_SHELL_CONTENT (book_shell_content)); + + paned = GTK_PANED (book_shell_content->priv->paned); + child = gtk_paned_get_child2 (paned); + + if (preview_visible) + gtk_widget_show (child); + else + gtk_widget_hide (child); + + g_object_notify (G_OBJECT (book_shell_content), "preview-visible"); +} + +void +e_book_shell_content_clipboard_copy (EBookShellContent *book_shell_content) +{ + EAddressbookView *addressbook_view; + GtkHTML *html; + gchar *selection; + + g_return_if_fail (E_IS_BOOK_SHELL_CONTENT (book_shell_content)); + + html = GTK_HTML (book_shell_content->priv->preview); + addressbook_view = + e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (addressbook_view != NULL); + + if (!GTK_WIDGET_HAS_FOCUS (html)) { + e_addressbook_view_copy (addressbook_view); + return; + } + + selection = gtk_html_get_selection_html (html, NULL); + if (selection != NULL) + gtk_html_copy (html); + g_free (selection); +} diff --git a/modules/addressbook/e-book-shell-content.h b/modules/addressbook/e-book-shell-content.h new file mode 100644 index 0000000000..da78c01274 --- /dev/null +++ b/modules/addressbook/e-book-shell-content.h @@ -0,0 +1,110 @@ +/* + * e-book-shell-content.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_BOOK_SHELL_CONTENT_H +#define E_BOOK_SHELL_CONTENT_H + +#include + +#include "shell/e-shell-content.h" +#include "shell/e-shell-view.h" + +#include "addressbook/gui/widgets/e-addressbook-view.h" +#include "eab-composer-util.h" + +/* Standard GObject macros */ +#define E_TYPE_BOOK_SHELL_CONTENT \ + (e_book_shell_content_get_type ()) +#define E_BOOK_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_BOOK_SHELL_CONTENT, EBookShellContent)) +#define E_BOOK_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_BOOK_SHELL_CONTENT, EBookShellContentClass)) +#define E_IS_BOOK_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_BOOK_SHELL_CONTENT)) +#define E_IS_BOOK_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_BOOK_SHELL_CONTENT)) +#define E_BOOK_SHELL_CONTENT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_BOOK_SHELL_CONTENT, EBookShellContentClass)) + +G_BEGIN_DECLS + +typedef struct _EBookShellContent EBookShellContent; +typedef struct _EBookShellContentClass EBookShellContentClass; +typedef struct _EBookShellContentPrivate EBookShellContentPrivate; + +enum { + E_BOOK_SHELL_CONTENT_SELECTION_SINGLE = 1 << 0, + E_BOOK_SHELL_CONTENT_SELECTION_MULTIPLE = 1 << 1, + E_BOOK_SHELL_CONTENT_SELECTION_HAS_EMAIL = 1 << 2, + E_BOOK_SHELL_CONTENT_SELECTION_IS_CONTACT_LIST = 1 << 3, + E_BOOK_SHELL_CONTENT_SELECTION_HAS_HTTP_URI = 1 << 4, + E_BOOK_SHELL_CONTENT_SELECTION_HAS_MAILTO_URI = 1 << 5, + E_BOOK_SHELL_CONTENT_SOURCE_IS_BUSY = 1 << 6, + E_BOOK_SHELL_CONTENT_SOURCE_IS_EDITABLE = 1 << 7, + E_BOOK_SHELL_CONTENT_SOURCE_IS_EMPTY = 1 << 8 +}; + +struct _EBookShellContent { + EShellContent parent; + EBookShellContentPrivate *priv; +}; + +struct _EBookShellContentClass { + EShellContentClass parent_class; +}; + +GType e_book_shell_content_get_type (void); +void e_book_shell_content_register_type + (GTypeModule *type_module); +GtkWidget * e_book_shell_content_new(EShellView *shell_view); +void e_book_shell_content_insert_view + (EBookShellContent *book_shell_content, + EAddressbookView *addressbook_view); +void e_book_shell_content_remove_view + (EBookShellContent *book_shell_content, + EAddressbookView *addressbook_view); +EAddressbookView * + e_book_shell_content_get_current_view + (EBookShellContent *book_shell_content); +void e_book_shell_content_set_current_view + (EBookShellContent *book_shell_content, + EAddressbookView *addressbook_view); +EContact * e_book_shell_content_get_preview_contact + (EBookShellContent *book_shell_content); +void e_book_shell_content_set_preview_contact + (EBookShellContent *book_shell_content, + EContact *preview_contact); +gboolean e_book_shell_content_get_preview_visible + (EBookShellContent *book_shell_content); +void e_book_shell_content_set_preview_visible + (EBookShellContent *book_shell_content, + gboolean preview_visible); +void e_book_shell_content_clipboard_copy + (EBookShellContent *book_shell_content); + +G_END_DECLS + +#endif /* E_BOOK_SHELL_CONTENT_H */ diff --git a/modules/addressbook/e-book-shell-migrate.c b/modules/addressbook/e-book-shell-migrate.c new file mode 100644 index 0000000000..fce6e0a634 --- /dev/null +++ b/modules/addressbook/e-book-shell-migrate.c @@ -0,0 +1,1230 @@ +/* + * e-book-shell-backend-migrate.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Chris Toshok + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include + +#include "e-util/e-util.h" +#include "e-util/e-util-private.h" +#include "e-util/e-xml-utils.h" +#include "e-util/e-folder-map.h" + +#include "e-book-shell-migrate.h" + +/*#define SLOW_MIGRATION*/ + +typedef struct { + /* this hash table maps old folder uris to new uids. It's + build in migrate_contact_folder and it's used in + migrate_completion_folders. */ + GHashTable *folder_uid_map; + + ESourceList *source_list; + + const gchar *data_dir; + + GtkWidget *window; + GtkWidget *label; + GtkWidget *folder_label; + GtkWidget *progress; +} MigrationContext; + +static void +setup_progress_dialog (MigrationContext *context) +{ + GtkWidget *vbox, *hbox; + + context->window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (context->window), _("Migrating...")); + gtk_window_set_modal (GTK_WINDOW (context->window), TRUE); + gtk_container_set_border_width (GTK_CONTAINER (context->window), 6); + + vbox = gtk_vbox_new (FALSE, 6); + gtk_widget_show (vbox); + gtk_container_add (GTK_CONTAINER (context->window), vbox); + + context->label = gtk_label_new (""); + gtk_label_set_line_wrap (GTK_LABEL (context->label), TRUE); + gtk_widget_show (context->label); + gtk_box_pack_start (GTK_BOX (vbox), context->label, TRUE, TRUE, 0); + + hbox = gtk_hbox_new (FALSE, 6); + gtk_widget_show (hbox); + gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0); + + context->folder_label = gtk_label_new (""); + gtk_widget_show (context->folder_label); + gtk_box_pack_start (GTK_BOX (hbox), context->folder_label, TRUE, TRUE, 0); + + context->progress = gtk_progress_bar_new (); + gtk_widget_show (context->progress); + gtk_box_pack_start (GTK_BOX (hbox), context->progress, TRUE, TRUE, 0); + + gtk_widget_show (context->window); +} + +static void +dialog_close (MigrationContext *context) +{ + gtk_widget_destroy (context->window); +} + +static void +dialog_set_label (MigrationContext *context, const gchar *str) +{ + gtk_label_set_text (GTK_LABEL (context->label), str); + + while (gtk_events_pending ()) + gtk_main_iteration (); + +#ifdef SLOW_MIGRATION + sleep (1); +#endif +} + +static void +dialog_set_folder_name (MigrationContext *context, const gchar *folder_name) +{ + gchar *text; + + text = g_strdup_printf (_("Migrating '%s':"), folder_name); + gtk_label_set_text (GTK_LABEL (context->folder_label), text); + g_free (text); + + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (context->progress), 0.0); + + while (gtk_events_pending ()) + gtk_main_iteration (); + +#ifdef SLOW_MIGRATION + sleep (1); +#endif +} + +static void +dialog_set_progress (MigrationContext *context, double percent) +{ + gchar text[5]; + + snprintf (text, sizeof (text), "%d%%", (gint) (percent * 100.0f)); + + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (context->progress), percent); + gtk_progress_bar_set_text (GTK_PROGRESS_BAR (context->progress), text); + + while (gtk_events_pending ()) + gtk_main_iteration (); + +#ifdef SLOW_MIGRATION + sleep (1); +#endif +} + +static gboolean +check_for_conflict (ESourceGroup *group, gchar *name) +{ + GSList *sources; + GSList *s; + + sources = e_source_group_peek_sources (group); + + for (s = sources; s; s = s->next) { + ESource *source = E_SOURCE (s->data); + + if (!strcmp (e_source_peek_name (source), name)) + return TRUE; + } + + return FALSE; +} + +static gchar * +get_source_name (ESourceGroup *group, const gchar *path) +{ +#ifndef G_OS_WIN32 + gchar **p = g_strsplit (path, "/", 0); +#else + gchar **p = g_strsplit_set (path, "\\/", 0); +#endif + gint i, j, starting_index; + gint num_elements; + gboolean conflict; + GString *s = g_string_new (""); + + for (i = 0; p[i]; i ++); + + num_elements = i; + i--; + + /* p[i] is now the last path element */ + + /* check if it conflicts */ + starting_index = i; + do { + g_string_assign (s, ""); + for (j = starting_index; j < num_elements; j += 2) { + if (j != starting_index) + g_string_append_c (s, '_'); + g_string_append (s, p[j]); + } + + conflict = check_for_conflict (group, s->str); + + + /* if there was a conflict back up 2 levels (skipping the /subfolder/ element) */ + if (conflict) + starting_index -= 2; + + /* we always break out if we can't go any further, + regardless of whether or not we conflict. */ + if (starting_index < 0) + break; + + } while (conflict); + + g_strfreev (p); + + return g_string_free (s, FALSE); +} + +static void +migrate_contacts (MigrationContext *context, EBook *old_book, EBook *new_book) +{ + EBookQuery *query = e_book_query_any_field_contains (""); + GList *l, *contacts; + gint num_added = 0; + gint num_contacts; + + /* both books are loaded, start the actual migration */ + e_book_get_contacts (old_book, query, &contacts, NULL); + e_book_query_unref (query); + + num_contacts = g_list_length (contacts); + for (l = contacts; l; l = l->next) { + EContact *contact = l->data; + GError *e = NULL; + GList *attrs, *attr; + + /* do some last minute massaging of the contact's attributes */ + + attrs = e_vcard_get_attributes (E_VCARD (contact)); + for (attr = attrs; attr;) { + EVCardAttribute *a = attr->data; + + /* evo 1.4 used the non-standard X-EVOLUTION-OFFICE attribute, + evo 1.5 uses the third element in the ORG list attribute. */ + if (!strcmp ("X-EVOLUTION-OFFICE", e_vcard_attribute_get_name (a))) { + GList *v = e_vcard_attribute_get_values (a); + GList *next_attr; + + if (v && v->data) + e_contact_set (contact, E_CONTACT_OFFICE, v->data); + + next_attr = attr->next; + e_vcard_remove_attribute (E_VCARD (contact), a); + attr = next_attr; + } + /* evo 1.4 didn't put TYPE=VOICE in for phone numbers. + evo 1.5 does. + + so we search through the attribute params for + either TYPE=VOICE or TYPE=FAX. If we find + either we do nothing. If we find neither, we + add TYPE=VOICE. + */ + else if (!strcmp ("TEL", e_vcard_attribute_get_name (a))) { + GList *params, *param; + gboolean found = FALSE; + + params = e_vcard_attribute_get_params (a); + for (param = params; param; param = param->next) { + EVCardAttributeParam *p = param->data; + if (!strcmp (EVC_TYPE, e_vcard_attribute_param_get_name (p))) { + GList *v = e_vcard_attribute_param_get_values (p); + while (v && v->data) { + if (!strcmp ("VOICE", v->data) + || !strcmp ("FAX", v->data)) { + found = TRUE; + break; + } + v = v->next; + } + } + } + + if (!found) + e_vcard_attribute_add_param_with_value (a, + e_vcard_attribute_param_new (EVC_TYPE), + "VOICE"); + attr = attr->next; + } + /* Replace "POSTAL" (1.4) addresses with "OTHER" (1.5) */ + else if (!strcmp ("ADR", e_vcard_attribute_get_name (a))) { + GList *params, *param; + gboolean found = FALSE; + EVCardAttributeParam *p; + + params = e_vcard_attribute_get_params (a); + for (param = params; param; param = param->next) { + p = param->data; + if (!strcmp (EVC_TYPE, e_vcard_attribute_param_get_name (p))) { + GList *v = e_vcard_attribute_param_get_values (p); + while (v && v->data ) { + if (!strcmp ("POSTAL", v->data)) { + found = TRUE; + break; + } + v = v->next; + } + if (found) + break; + } + } + + if (found) { + e_vcard_attribute_param_remove_values (p); + e_vcard_attribute_param_add_value (p, "OTHER"); + } + + attr = attr->next; + } + /* this is kinda gross. The new vcard parser + needs ';'s to be escaped by \'s. but the + 1.4 vcard generator would put unescaped xml + (including entities like >) in the value + of attributes, so we need to go through and + escape those ';'s. */ + else if (!strcmp ("EMAIL", e_vcard_attribute_get_name (a))) { + GList *params; + GList *v = e_vcard_attribute_get_values (a); + + /* Add TYPE=OTHER if there is no type set */ + params = e_vcard_attribute_get_params (a); + if (!params) + e_vcard_attribute_add_param_with_value (a, + e_vcard_attribute_param_new (EVC_TYPE), + "OTHER"); + + if (v && v->data) { + if (!strncmp ((gchar *)v->data, "data); + if (v->next) + g_string_append_c (str, ';'); + v = v->next; + } + + e_vcard_attribute_remove_values (a); + e_vcard_attribute_add_value (a, str->str); + g_string_free (str, TRUE); + } + } + + attr = attr->next; + } + else { + attr = attr->next; + } + } + + if (!e_book_add_contact (new_book, + contact, + &e)) + g_warning ("contact add failed: `%s'", e->message); + + num_added ++; + + dialog_set_progress (context, (double)num_added / num_contacts); + } + + g_list_foreach (contacts, (GFunc)g_object_unref, NULL); + g_list_free (contacts); +} + +static void +migrate_contact_folder_to_source (MigrationContext *context, gchar *old_path, ESource *new_source) +{ + gchar *old_uri = g_filename_to_uri (old_path, NULL, NULL); + GError *e = NULL; + + EBook *old_book = NULL, *new_book = NULL; + ESource *old_source; + ESourceGroup *group; + + group = e_source_group_new ("", old_uri); + old_source = e_source_new ("", ""); + e_source_group_add_source (group, old_source, -1); + + dialog_set_folder_name (context, e_source_peek_name (new_source)); + + old_book = e_book_new (old_source, &e); + if (!old_book + || !e_book_open (old_book, TRUE, &e)) { + g_warning ("failed to load source book for migration: `%s'", e->message); + goto finish; + } + + new_book = e_book_new (new_source, &e); + if (!new_book + || !e_book_open (new_book, FALSE, &e)) { + g_warning ("failed to load destination book for migration: `%s'", e->message); + goto finish; + } + + migrate_contacts (context, old_book, new_book); + + finish: + g_object_unref (old_source); + g_object_unref (group); + if (old_book) + g_object_unref (old_book); + if (new_book) + g_object_unref (new_book); + g_free (old_uri); +} + +static void +migrate_contact_folder (MigrationContext *context, gchar *old_path, ESourceGroup *dest_group, gchar *source_name) +{ + ESource *new_source; + + new_source = e_source_new (source_name, source_name); + e_source_set_relative_uri (new_source, e_source_peek_uid (new_source)); + e_source_group_add_source (dest_group, new_source, -1); + + g_hash_table_insert (context->folder_uid_map, g_strdup (old_path), g_strdup (e_source_peek_uid (new_source))); + + migrate_contact_folder_to_source (context, old_path, new_source); + + g_object_unref (new_source); +} + +#define LDAP_BASE_URI "ldap://" +#define PERSONAL_RELATIVE_URI "system" + +static void +create_groups (MigrationContext *context, + ESourceGroup **on_this_computer, + ESourceGroup **on_ldap_servers, + ESource **personal_source) +{ + GSList *groups; + ESourceGroup *group; + gchar *base_uri, *base_uri_proto; + + *on_this_computer = NULL; + *on_ldap_servers = NULL; + *personal_source = NULL; + + base_uri = g_build_filename (context->data_dir, "local", NULL); + + base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL); + + groups = e_source_list_peek_groups (context->source_list); + if (groups) { + /* groups are already there, we need to search for things... */ + GSList *g; + + for (g = groups; g; g = g->next) { + + group = E_SOURCE_GROUP (g->data); + + if (!*on_this_computer && !strcmp (base_uri_proto, e_source_group_peek_base_uri (group))) + *on_this_computer = g_object_ref (group); + else if (!*on_ldap_servers && !strcmp (LDAP_BASE_URI, e_source_group_peek_base_uri (group))) + *on_ldap_servers = g_object_ref (group); + } + } + + if (*on_this_computer) { + /* make sure "Personal" shows up as a source under + this group */ + GSList *sources = e_source_group_peek_sources (*on_this_computer); + GSList *s; + for (s = sources; s; s = s->next) { + ESource *source = E_SOURCE (s->data); + const gchar *relative_uri; + + relative_uri = e_source_peek_relative_uri (source); + if (relative_uri == NULL) + continue; + if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) { + *personal_source = g_object_ref (source); + break; + } + } + } + else { + /* create the local source group */ + group = e_source_group_new (_("On This Computer"), base_uri_proto); + e_source_list_add_group (context->source_list, group, -1); + + *on_this_computer = group; + } + + if (!*personal_source) { + /* Create the default Person addressbook */ + ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); + e_source_group_add_source (*on_this_computer, source, -1); + + e_source_set_property (source, "completion", "true"); + + *personal_source = source; + } + + if (!*on_ldap_servers) { + /* Create the LDAP source group */ + group = e_source_group_new (_("On LDAP Servers"), LDAP_BASE_URI); + e_source_list_add_group (context->source_list, group, -1); + + *on_ldap_servers = group; + } + + g_free (base_uri_proto); + g_free (base_uri); +} + +static gboolean +migrate_local_folders (MigrationContext *context, ESourceGroup *on_this_computer, ESource *personal_source) +{ + gchar *old_path = NULL; + GSList *dirs, *l; + gchar *local_contact_folder = NULL; + + old_path = g_strdup_printf ("%s/evolution/local", g_get_home_dir ()); + + dirs = e_folder_map_local_folders (old_path, "contacts"); + + /* migrate the local addressbook first, to local/system */ + local_contact_folder = g_build_filename (g_get_home_dir (), + "evolution", "local", "Contacts", + NULL); + + for (l = dirs; l; l = l->next) { + gchar *source_name; + /* we handle the system folder differently */ + if (personal_source && !strcmp ((gchar *)l->data, local_contact_folder)) { + g_hash_table_insert (context->folder_uid_map, g_strdup (l->data), g_strdup (e_source_peek_uid (personal_source))); + migrate_contact_folder_to_source (context, local_contact_folder, personal_source); + continue; + } + + source_name = get_source_name (on_this_computer, (gchar *)l->data); + migrate_contact_folder (context, l->data, on_this_computer, source_name); + g_free (source_name); + } + + g_slist_foreach (dirs, (GFunc)g_free, NULL); + g_slist_free (dirs); + g_free (local_contact_folder); + g_free (old_path); + + return TRUE; +} + +static gchar * +get_string_child (xmlNode *node, + const gchar *name) +{ + xmlNode *p; + xmlChar *xml_string; + gchar *retval; + + p = e_xml_get_child_by_name (node, (xmlChar *) name); + if (p == NULL) + return NULL; + + p = e_xml_get_child_by_name (p, (xmlChar *) "text"); + if (p == NULL) /* there's no text between the tags, return the empty string */ + return g_strdup(""); + + xml_string = xmlNodeListGetString (node->doc, p, 1); + retval = g_strdup ((gchar *) xml_string); + xmlFree (xml_string); + + return retval; +} + +static gint +get_integer_child (xmlNode *node, + const gchar *name, + gint defval) +{ + xmlNode *p; + xmlChar *xml_string; + gint retval; + + p = e_xml_get_child_by_name (node, (xmlChar *) name); + if (p == NULL) + return defval; + + p = e_xml_get_child_by_name (p, (xmlChar *) "text"); + if (p == NULL) /* there's no text between the tags, return the default */ + return defval; + + xml_string = xmlNodeListGetString (node->doc, p, 1); + retval = atoi ((gchar *)xml_string); + xmlFree (xml_string); + + return retval; +} + +static gboolean +migrate_ldap_servers (MigrationContext *context, ESourceGroup *on_ldap_servers) +{ + gchar *sources_xml = g_strdup_printf ("%s/evolution/addressbook-sources.xml", + g_get_home_dir ()); + + printf ("trying to migrate from %s\n", sources_xml); + + if (g_file_test (sources_xml, G_FILE_TEST_EXISTS)) { + xmlDoc *doc = xmlParseFile (sources_xml); + xmlNode *root; + xmlNode *child; + gint num_contactservers; + gint servernum; + + if (!doc) + return FALSE; + + root = xmlDocGetRootElement (doc); + if (root == NULL || strcmp ((const gchar *)root->name, "addressbooks") != 0) { + xmlFreeDoc (doc); + return FALSE; + } + + /* count the number of servers, so we can give progress */ + num_contactservers = 0; + for (child = root->children; child; child = child->next) { + if (!strcmp ((const gchar *)child->name, "contactserver")) { + num_contactservers++; + } + } + printf ("found %d contact servers to migrate\n", num_contactservers); + + dialog_set_folder_name (context, _("LDAP Servers")); + + servernum = 0; + for (child = root->children; child; child = child->next) { + if (!strcmp ((const gchar *)child->name, "contactserver")) { + gchar *port, *host, *rootdn, *scope, *authmethod, *ssl; + gchar *emailaddr, *binddn, *limitstr; + gint limit; + gchar *name, *description; + GString *uri = g_string_new (""); + ESource *source; + + name = get_string_child (child, "name"); + description = get_string_child (child, "description"); + port = get_string_child (child, "port"); + host = get_string_child (child, "host"); + rootdn = get_string_child (child, "rootdn"); + scope = get_string_child (child, "scope"); + authmethod = get_string_child (child, "authmethod"); + ssl = get_string_child (child, "ssl"); + emailaddr = get_string_child (child, "emailaddr"); + binddn = get_string_child (child, "binddn"); + limit = get_integer_child (child, "limit", 100); + limitstr = g_strdup_printf ("%d", limit); + + g_string_append_printf (uri, + "%s:%s/%s?"/*trigraph prevention*/"?%s", + host, port, rootdn, scope); + + source = e_source_new (name, uri->str); + e_source_set_property (source, "description", description); + e_source_set_property (source, "limit", limitstr); + e_source_set_property (source, "ssl", ssl); + e_source_set_property (source, "auth", authmethod); + if (emailaddr) + e_source_set_property (source, "email_addr", emailaddr); + if (binddn) + e_source_set_property (source, "binddn", binddn); + + e_source_group_add_source (on_ldap_servers, source, -1); + + g_string_free (uri, TRUE); + g_free (port); + g_free (host); + g_free (rootdn); + g_free (scope); + g_free (authmethod); + g_free (ssl); + g_free (emailaddr); + g_free (binddn); + g_free (limitstr); + g_free (name); + g_free (description); + + servernum++; + dialog_set_progress (context, (double)servernum/num_contactservers); + } + } + + xmlFreeDoc (doc); + } + + g_free (sources_xml); + + return TRUE; +} + +static ESource* +get_source_by_name (ESourceList *source_list, const gchar *name) +{ + GSList *groups; + GSList *g; + + groups = e_source_list_peek_groups (source_list); + if (!groups) + return NULL; + + for (g = groups; g; g = g->next) { + GSList *sources; + GSList *s; + ESourceGroup *group = E_SOURCE_GROUP (g->data); + + sources = e_source_group_peek_sources (group); + if (!sources) + continue; + + for (s = sources; s; s = s->next) { + ESource *source = E_SOURCE (s->data); + const gchar *source_name = e_source_peek_name (source); + + if (!strcmp (name, source_name)) + return source; + } + } + + return NULL; +} + +static gboolean +migrate_completion_folders (MigrationContext *context) +{ + GConfClient *client; + const gchar *key; + gchar *uris_xml; + + printf ("trying to migrate completion folders\n"); + + client = gconf_client_get_default (); + key = "/apps/evolution/addressbook/completion/uris"; + uris_xml = gconf_client_get_string (client, key, NULL); + g_object_unref (client); + + if (uris_xml) { + xmlDoc *doc = xmlParseMemory (uris_xml, strlen (uris_xml)); + xmlNode *root; + xmlNode *child; + + if (!doc) + return FALSE; + + dialog_set_folder_name (context, _("Autocompletion Settings")); + + root = xmlDocGetRootElement (doc); + if (root == NULL || strcmp ((const gchar *)root->name, "EvolutionFolderList") != 0) { + xmlFreeDoc (doc); + return FALSE; + } + + for (child = root->children; child; child = child->next) { + if (!strcmp ((const gchar *)child->name, "folder")) { + gchar *physical_uri = e_xml_get_string_prop_by_name (child, (const guchar *)"physical-uri"); + ESource *source = NULL; + + /* if the physical uri is file://... + we look it up in our folder_uid_map + hashtable. If it's a folder we + converted over, we should get back + a uid we can search for. + + if the physical_uri is anything + else, we strip off the args + (anything after;) before searching + for the uri. */ + + if (!strncmp (physical_uri, "file://", 7)) { + gchar *filename = g_filename_from_uri (physical_uri, NULL, NULL); + gchar *uid = NULL; + + if (filename) + uid = g_hash_table_lookup (context->folder_uid_map, + filename); + g_free (filename); + if (uid) + source = e_source_list_peek_source_by_uid (context->source_list, uid); + } + else { + gchar *name = e_xml_get_string_prop_by_name (child, (const guchar *)"display-name"); + + source = get_source_by_name (context->source_list, name); + + g_free (name); + } + + if (source) { + e_source_set_property (source, "completion", "true"); + } + else { + g_warning ("found completion folder with uri `%s' that " + "doesn't correspond to anything we migrated.", physical_uri); + } + + g_free (physical_uri); + } + } + + g_free (uris_xml); + } + else { + g_message ("no completion folder settings to migrate"); + } + + return TRUE; +} + +static void +migrate_contact_lists_for_local_folders (MigrationContext *context, ESourceGroup *on_this_computer) +{ + GSList *sources, *s; + + sources = e_source_group_peek_sources (on_this_computer); + for (s = sources; s; s = s->next) { + ESource *source = s->data; + EBook *book; + EBookQuery *query; + GList *l, *contacts; + gint num_contacts, num_converted; + + dialog_set_folder_name (context, e_source_peek_name (source)); + + book = e_book_new (source, NULL); + if (!book + || !e_book_open (book, TRUE, NULL)) { + gchar *uri = e_source_get_uri (source); + g_warning ("failed to migrate contact lists for source %s", uri); + g_free (uri); + continue; + } + + query = e_book_query_any_field_contains (""); + e_book_get_contacts (book, query, &contacts, NULL); + e_book_query_unref (query); + + num_converted = 0; + num_contacts = g_list_length (contacts); + for (l = contacts; l; l = l->next) { + EContact *contact = l->data; + GError *e = NULL; + GList *attrs, *attr; + gboolean converted = FALSE; + + attrs = e_contact_get_attributes (contact, E_CONTACT_EMAIL); + for (attr = attrs; attr; attr = attr->next) { + EVCardAttribute *a = attr->data; + GList *v = e_vcard_attribute_get_values (a); + + if (v && v->data) { + if (!strncmp ((gchar *)v->data, "data); + + e_destination_export_to_vcard_attribute (dest, a); + + g_object_unref (dest); + + converted = TRUE; + } + } + } + + if (converted) { + e_contact_set_attributes (contact, E_CONTACT_EMAIL, attrs); + + if (!e_book_commit_contact (book, + contact, + &e)) + g_warning ("contact commit failed: `%s'", e->message); + } + + num_converted ++; + + dialog_set_progress (context, (double)num_converted / num_contacts); + } + + g_list_foreach (contacts, (GFunc)g_object_unref, NULL); + g_list_free (contacts); + + g_object_unref (book); + } +} + +static void +migrate_company_phone_for_local_folders (MigrationContext *context, ESourceGroup *on_this_computer) +{ + GSList *sources, *s; + + sources = e_source_group_peek_sources (on_this_computer); + for (s = sources; s; s = s->next) { + ESource *source = s->data; + EBook *book; + EBookQuery *query; + GList *l, *contacts; + gint num_contacts, num_converted; + + dialog_set_folder_name (context, e_source_peek_name (source)); + + book = e_book_new (source, NULL); + if (!book + || !e_book_open (book, TRUE, NULL)) { + gchar *uri = e_source_get_uri (source); + g_warning ("failed to migrate company phone numbers for source %s", uri); + g_free (uri); + continue; + } + + query = e_book_query_any_field_contains (""); + e_book_get_contacts (book, query, &contacts, NULL); + e_book_query_unref (query); + + num_converted = 0; + num_contacts = g_list_length (contacts); + for (l = contacts; l; l = l->next) { + EContact *contact = l->data; + GError *e = NULL; + GList *attrs, *attr; + gboolean converted = FALSE; + gint num_work_voice = 0; + + attrs = e_vcard_get_attributes (E_VCARD (contact)); + for (attr = attrs; attr;) { + EVCardAttribute *a = attr->data; + GList *next_attr = attr->next; + + if (!strcmp ("TEL", e_vcard_attribute_get_name (a))) { + GList *params, *param; + gboolean found_voice = FALSE; + gboolean found_work = FALSE; + + params = e_vcard_attribute_get_params (a); + for (param = params; param; param = param->next) { + EVCardAttributeParam *p = param->data; + if (!strcmp (EVC_TYPE, e_vcard_attribute_param_get_name (p))) { + GList *v = e_vcard_attribute_param_get_values (p); + while (v && v->data) { + if (!strcmp ("VOICE", v->data)) + found_voice = TRUE; + else if (!strcmp ("WORK", v->data)) + found_work = TRUE; + v = v->next; + } + } + + if (found_work && found_voice) + num_work_voice++; + + if (num_work_voice == 3) { + GList *v = e_vcard_attribute_get_values (a); + + if (v && v->data) + e_contact_set (contact, E_CONTACT_PHONE_COMPANY, v->data); + + e_vcard_remove_attribute (E_VCARD (contact), a); + + converted = TRUE; + break; + } + } + } + + attr = next_attr; + + if (converted) + break; + } + + if (converted) { + if (!e_book_commit_contact (book, + contact, + &e)) + g_warning ("contact commit failed: `%s'", e->message); + } + + num_converted ++; + + dialog_set_progress (context, (double)num_converted / num_contacts); + } + + g_list_foreach (contacts, (GFunc)g_object_unref, NULL); + g_list_free (contacts); + + g_object_unref (book); + } +} + +static void +migrate_pilot_data (const gchar *old_path, const gchar *new_path) +{ + const gchar *dent; + const gchar *ext; + gchar *filename; + GDir *dir; + + if (!(dir = g_dir_open (old_path, 0, NULL))) + return; + + while ((dent = g_dir_read_name (dir))) { + if ((!strncmp (dent, "pilot-map-", 10) && + ((ext = strrchr (dent, '.')) && !strcmp (ext, ".xml"))) || + (!strncmp (dent, "pilot-sync-evolution-addressbook-", 33) && + ((ext = strrchr (dent, '.')) && !strcmp (ext, ".db")))) { + /* src and dest file formats are identical for both map and changelog files */ + guchar inbuf[4096]; + gsize nread, nwritten; + gint fd0, fd1; + gssize n; + + filename = g_build_filename (old_path, dent, NULL); + if ((fd0 = g_open (filename, O_RDONLY | O_BINARY, 0)) == -1) { + g_free (filename); + continue; + } + + g_free (filename); + filename = g_build_filename (new_path, dent, NULL); + if ((fd1 = g_open (filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666)) == -1) { + g_free (filename); + close (fd0); + continue; + } + + do { + do { + n = read (fd0, inbuf, sizeof (inbuf)); + } while (n == -1 && errno == EINTR); + + if (n < 1) + break; + + nread = n; + nwritten = 0; + do { + do { + n = write (fd1, inbuf + nwritten, nread - nwritten); + } while (n == -1 && errno == EINTR); + + if (n > 0) + nwritten += n; + } while (nwritten < nread && n != -1); + + if (n == -1) + break; + } while (1); + + if (n != -1) + n = fsync (fd1); + + if (n == -1) { + g_warning ("Failed to migrate %s: %s", dent, g_strerror (errno)); + g_unlink (filename); + } + + close (fd0); + close (fd1); + g_free (filename); + } + } + + g_dir_close (dir); +} + +static MigrationContext * +migration_context_new (const gchar *data_dir) +{ + MigrationContext *context = g_new (MigrationContext, 1); + + /* set up the mapping from old uris to new uids */ + context->folder_uid_map = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_free); + + e_book_get_addressbooks (&context->source_list, NULL); + + context->data_dir = data_dir; + + return context; +} + +static void +migration_context_free (MigrationContext *context) +{ + e_source_list_sync (context->source_list, NULL); + + g_hash_table_destroy (context->folder_uid_map); + + g_object_unref (context->source_list); + + g_free (context); +} + +gboolean +e_book_shell_backend_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint micro, + GError **error) +{ + ESourceGroup *on_this_computer; + ESourceGroup *on_ldap_servers; + ESource *personal_source; + MigrationContext *context; + gboolean need_dialog = FALSE; + const gchar *data_dir; + + g_return_val_if_fail (E_IS_SHELL_BACKEND (shell_backend), FALSE); + + data_dir = e_shell_backend_get_data_dir (shell_backend); + context = migration_context_new (data_dir); + + /* we call this unconditionally now - create_groups either + creates the groups/sources or it finds the necessary + groups/sources. */ + create_groups (context, &on_this_computer, &on_ldap_servers, &personal_source); + + /* figure out if we need the dialog displayed */ + if (major == 1 + /* we only need the most recent upgrade point here. + further decomposition will happen below. */ + && (minor < 5 || (minor == 5 && micro <= 10))) + need_dialog = TRUE; + + if (need_dialog) + setup_progress_dialog (context); + + if (major == 1) { + + if (minor < 5 || (minor == 5 && micro <= 2)) { + /* initialize our dialog */ + dialog_set_label (context, + _("The location and hierarchy of the Evolution contact " + "folders has changed since Evolution 1.x.\n\nPlease be " + "patient while Evolution migrates your folders...")); + + if (on_this_computer) + migrate_local_folders (context, on_this_computer, personal_source); + if (on_ldap_servers) + migrate_ldap_servers (context, on_ldap_servers); + + migrate_completion_folders (context); + } + + if (minor < 5 || (minor == 5 && micro <= 7)) { + dialog_set_label (context, + _("The format of mailing list contacts has changed.\n\n" + "Please be patient while Evolution migrates your " + "folders...")); + + migrate_contact_lists_for_local_folders (context, on_this_computer); + } + + if (minor < 5 || (minor == 5 && micro <= 8)) { + dialog_set_label (context, + _("The way Evolution stores some phone numbers has changed.\n\n" + "Please be patient while Evolution migrates your " + "folders...")); + + migrate_company_phone_for_local_folders (context, on_this_computer); + } + + if (minor < 5 || (minor == 5 && micro <= 10)) { + gchar *old_path, *new_path; + + dialog_set_label (context, _("Evolution's Palm Sync changelog and map files have changed.\n\n" + "Please be patient while Evolution migrates your Pilot Sync data...")); + + old_path = g_build_filename (g_get_home_dir (), "evolution", "local", "Contacts", NULL); + new_path = g_build_filename (data_dir, "local", "system", NULL); + migrate_pilot_data (old_path, new_path); + g_free (new_path); + g_free (old_path); + } + + /* we only need to do this next step if people ran + older versions of 1.5. We need to clear out the + absolute URI's that were assigned to ESources + during one phase of development, as they take + precedent over relative uris (but aren't updated + when editing an ESource). */ + if (minor == 5 && micro <= 11) { + GSList *g; + for (g = e_source_list_peek_groups (context->source_list); g; g = g->next) { + ESourceGroup *group = g->data; + GSList *s; + + for (s = e_source_group_peek_sources (group); s; s = s->next) { + ESource *source = s->data; + e_source_set_absolute_uri (source, NULL); + } + } + } + } + + if (need_dialog) + dialog_close (context); + + if (on_this_computer) + g_object_unref (on_this_computer); + if (on_ldap_servers) + g_object_unref (on_ldap_servers); + if (personal_source) + g_object_unref (personal_source); + + + migration_context_free (context); + + return TRUE; +} diff --git a/modules/addressbook/e-book-shell-migrate.h b/modules/addressbook/e-book-shell-migrate.h new file mode 100644 index 0000000000..cb6128910a --- /dev/null +++ b/modules/addressbook/e-book-shell-migrate.h @@ -0,0 +1,41 @@ +/* + * e-book-shell-migrate.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Chris Toshok (toshok@ximian.com) + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_BOOK_SHELL_MIGRATE_H +#define E_BOOK_SHELL_MIGRATE_H + +#include +#include + +G_BEGIN_DECLS + +gboolean e_book_shell_backend_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint micro, + GError **error); + +G_END_DECLS + +#endif /* E_BOOK_SHELL_MIGRATE_H */ diff --git a/modules/addressbook/e-book-shell-sidebar.c b/modules/addressbook/e-book-shell-sidebar.c new file mode 100644 index 0000000000..fc283e28d7 --- /dev/null +++ b/modules/addressbook/e-book-shell-sidebar.c @@ -0,0 +1,232 @@ +/* + * e-book-shell-sidebar.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-book-shell-sidebar.h" + +#include +#include + +#include "e-book-shell-view.h" +#include "e-book-shell-backend.h" +#include "e-addressbook-selector.h" + +#define E_BOOK_SHELL_SIDEBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_BOOK_SHELL_SIDEBAR, EBookShellSidebarPrivate)) + +struct _EBookShellSidebarPrivate { + GtkWidget *selector; +}; + +enum { + PROP_0, + PROP_SELECTOR +}; + +static gpointer parent_class; +static GType book_shell_sidebar_type; + +static void +book_shell_sidebar_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SELECTOR: + g_value_set_object ( + value, e_book_shell_sidebar_get_selector ( + E_BOOK_SHELL_SIDEBAR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +book_shell_sidebar_dispose (GObject *object) +{ + EBookShellSidebarPrivate *priv; + + priv = E_BOOK_SHELL_SIDEBAR_GET_PRIVATE (object); + + if (priv->selector != NULL) { + g_object_unref (priv->selector); + priv->selector = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +book_shell_sidebar_constructed (GObject *object) +{ + EBookShellSidebarPrivate *priv; + EShellView *shell_view; + EShellBackend *shell_backend; + EShellSidebar *shell_sidebar; + ESourceList *source_list; + GtkContainer *container; + GtkWidget *widget; + + priv = E_BOOK_SHELL_SIDEBAR_GET_PRIVATE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_sidebar = E_SHELL_SIDEBAR (object); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + source_list = e_book_shell_backend_get_source_list ( + E_BOOK_SHELL_BACKEND (shell_backend)); + + container = GTK_CONTAINER (shell_sidebar); + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_container_add (container, widget); + gtk_widget_show (widget); + + container = GTK_CONTAINER (widget); + + widget = e_addressbook_selector_new (source_list); + e_source_selector_show_selection (E_SOURCE_SELECTOR (widget), FALSE); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->selector = g_object_ref (widget); + gtk_widget_show (widget); +} + +static guint32 +book_shell_sidebar_check_state (EShellSidebar *shell_sidebar) +{ + EBookShellSidebar *book_shell_sidebar; + ESourceSelector *selector; + ESource *source; + gboolean is_system = FALSE; + guint32 state = 0; + + book_shell_sidebar = E_BOOK_SHELL_SIDEBAR (shell_sidebar); + selector = e_book_shell_sidebar_get_selector (book_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + + if (source != NULL) { + const gchar *uri; + + uri = e_source_peek_relative_uri (source); + is_system = (uri == NULL || strcmp (uri, "system") == 0); + } + + if (source != NULL) + state |= E_BOOK_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE; + if (is_system) + state |= E_BOOK_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM; + + return state; +} + +static void +book_shell_sidebar_class_init (EBookShellSidebarClass *class) +{ + GObjectClass *object_class; + EShellSidebarClass *shell_sidebar_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EBookShellSidebarPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->get_property = book_shell_sidebar_get_property; + object_class->dispose = book_shell_sidebar_dispose; + object_class->constructed = book_shell_sidebar_constructed; + + shell_sidebar_class = E_SHELL_SIDEBAR_CLASS (class); + shell_sidebar_class->check_state = book_shell_sidebar_check_state; + + g_object_class_install_property ( + object_class, + PROP_SELECTOR, + g_param_spec_object ( + "selector", + _("Source Selector Widget"), + _("This widget displays groups of address books"), + E_TYPE_SOURCE_SELECTOR, + G_PARAM_READABLE)); +} + +static void +book_shell_sidebar_init (EBookShellSidebar *book_shell_sidebar) +{ + book_shell_sidebar->priv = + E_BOOK_SHELL_SIDEBAR_GET_PRIVATE (book_shell_sidebar); + + /* Postpone widget construction until we have a shell view. */ +} + +GType +e_book_shell_sidebar_get_type (void) +{ + return book_shell_sidebar_type; +} + +void +e_book_shell_sidebar_register_type (GTypeModule *type_module) +{ + static const GTypeInfo type_info = { + sizeof (EBookShellSidebarClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) book_shell_sidebar_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EBookShellSidebar), + 0, /* n_preallocs */ + (GInstanceInitFunc) book_shell_sidebar_init, + NULL /* value_table */ + }; + + book_shell_sidebar_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_SIDEBAR, + "EBookShellSidebar", &type_info, 0); +} + +GtkWidget * +e_book_shell_sidebar_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_BOOK_SHELL_SIDEBAR, + "shell-view", shell_view, NULL); +} + +ESourceSelector * +e_book_shell_sidebar_get_selector (EBookShellSidebar *book_shell_sidebar) +{ + g_return_val_if_fail ( + E_IS_BOOK_SHELL_SIDEBAR (book_shell_sidebar), NULL); + + return E_SOURCE_SELECTOR (book_shell_sidebar->priv->selector); +} diff --git a/modules/addressbook/e-book-shell-sidebar.h b/modules/addressbook/e-book-shell-sidebar.h new file mode 100644 index 0000000000..716523f971 --- /dev/null +++ b/modules/addressbook/e-book-shell-sidebar.h @@ -0,0 +1,79 @@ +/* + * e-book-shell-sidebar.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_BOOK_SHELL_SIDEBAR_H +#define E_BOOK_SHELL_SIDEBAR_H + +#include + +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_BOOK_SHELL_SIDEBAR \ + (e_book_shell_sidebar_get_type ()) +#define E_BOOK_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_BOOK_SHELL_SIDEBAR, EBookShellSidebar)) +#define E_BOOK_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_BOOK_SHELL_SIDEBAR, EBookShellSidebarClass)) +#define E_IS_BOOK_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_BOOK_SHELL_SIDEBAR)) +#define E_IS_BOOK_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_BOOK_SHELL_SIDEBAR)) +#define E_BOOK_SHELL_SIDEBAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_BOOK_SHELL_SIDEBAR, EBookShellSidebarClass)) + +G_BEGIN_DECLS + +typedef struct _EBookShellSidebar EBookShellSidebar; +typedef struct _EBookShellSidebarClass EBookShellSidebarClass; +typedef struct _EBookShellSidebarPrivate EBookShellSidebarPrivate; + +enum { + E_BOOK_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE = 1 << 0, + E_BOOK_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM = 1 << 1 +}; + +struct _EBookShellSidebar { + EShellSidebar parent; + EBookShellSidebarPrivate *priv; +}; + +struct _EBookShellSidebarClass { + EShellSidebarClass parent_class; +}; + +GType e_book_shell_sidebar_get_type (void); +void e_book_shell_sidebar_register_type + (GTypeModule *type_module); +GtkWidget * e_book_shell_sidebar_new(EShellView *shell_view); +ESourceSelector * + e_book_shell_sidebar_get_selector + (EBookShellSidebar *book_shell_sidebar); + +G_END_DECLS + +#endif /* E_BOOK_SHELL_SIDEBAR_H */ diff --git a/modules/addressbook/e-book-shell-view-actions.c b/modules/addressbook/e-book-shell-view-actions.c new file mode 100644 index 0000000000..773eb3fa7a --- /dev/null +++ b/modules/addressbook/e-book-shell-view-actions.c @@ -0,0 +1,1011 @@ +/* + * e-book-shell-view-actions.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-book-shell-view-private.h" + +#include +#include +#include + +#include + +static void +action_address_book_copy_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (view != NULL); + + e_addressbook_view_copy_to_folder (view, TRUE); +} + +static void +action_address_book_delete_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EBookShellBackend *book_shell_backend; + EBookShellSidebar *book_shell_sidebar; + ESource *source; + ESourceSelector *selector; + ESourceGroup *source_group; + ESourceList *source_list; + EBook *book; + gint response; + GError *error = NULL; + + shell_view = E_SHELL_VIEW (book_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + book_shell_backend = book_shell_view->priv->book_shell_backend; + source_list = e_book_shell_backend_get_source_list (book_shell_backend); + + book_shell_sidebar = book_shell_view->priv->book_shell_sidebar; + selector = e_book_shell_sidebar_get_selector (book_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (source != NULL); + + response = e_error_run ( + GTK_WINDOW (shell_window), + "addressbook:ask-delete-addressbook", + e_source_peek_name (source)); + + if (response != GTK_RESPONSE_YES) + return; + + book = e_book_new (source, &error); + if (error != NULL) { + g_warning ("Error removing addressbook: %s", error->message); + g_error_free (error); + return; + } + + if (!e_book_remove (book, NULL)) { + e_error_run ( + GTK_WINDOW (shell_window), + "addressbook:remove-addressbook", NULL); + g_object_unref (book); + return; + } + + if (e_source_selector_source_is_selected (selector, source)) + e_source_selector_unselect_source (selector, source); + + source_group = e_source_peek_group (source); + e_source_group_remove_source (source_group, source); + + e_source_list_sync (source_list, NULL); + + g_object_unref (book); +} + +static void +action_address_book_move_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (view != NULL); + + e_addressbook_view_move_to_folder (view, TRUE); +} + +static void +action_address_book_new_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + + shell_view = E_SHELL_VIEW (book_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + addressbook_config_create_new_source (GTK_WIDGET (shell_window)); +} + +static void +action_address_book_properties_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EBookShellSidebar *book_shell_sidebar; + ESource *source; + ESourceSelector *selector; + EditorUidClosure *closure; + GHashTable *uid_to_editor; + const gchar *uid; + + shell_view = E_SHELL_VIEW (book_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + book_shell_sidebar = book_shell_view->priv->book_shell_sidebar; + selector = e_book_shell_sidebar_get_selector (book_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (source != NULL); + + uid = e_source_peek_uid (source); + uid_to_editor = book_shell_view->priv->uid_to_editor; + + closure = g_hash_table_lookup (uid_to_editor, uid); + if (closure == NULL) { + GtkWidget *editor; + + editor = addressbook_config_edit_source ( + GTK_WIDGET (shell_window), source); + + closure = g_new (EditorUidClosure, 1); + closure->editor = editor; + closure->uid = g_strdup (uid); + closure->view = book_shell_view; + + g_hash_table_insert (uid_to_editor, closure->uid, closure); + + g_object_weak_ref ( + G_OBJECT (closure->editor), (GWeakNotify) + e_book_shell_view_editor_weak_notify, closure); + } + + gtk_window_present (GTK_WINDOW (closure->editor)); +} + +static void +action_address_book_rename_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellSidebar *book_shell_sidebar; + ESourceSelector *selector; + + book_shell_sidebar = book_shell_view->priv->book_shell_sidebar; + selector = e_book_shell_sidebar_get_selector (book_shell_sidebar); + + e_source_selector_edit_primary_selection (selector); +} + +static void +action_address_book_save_as_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (view != NULL); + + e_addressbook_view_save_as (view, TRUE); +} + +static void +action_address_book_stop_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (view != NULL); + + e_addressbook_view_stop (view); +} + +static void +action_contact_clipboard_copy_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + + book_shell_content = book_shell_view->priv->book_shell_content; + e_book_shell_content_clipboard_copy (book_shell_content); +} + +static void +action_contact_clipboard_cut_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (view != NULL); + + e_addressbook_view_cut (view); +} + +static void +action_contact_clipboard_paste_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (view != NULL); + + e_addressbook_view_paste (view); +} + +static void +action_contact_copy_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (view != NULL); + + e_addressbook_view_copy_to_folder (view, FALSE); +} + +static void +action_contact_delete_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (view != NULL); + + e_addressbook_view_delete_selection (view, TRUE); +} + +static void +action_contact_forward_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + GList *list, *iter; + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (view != NULL); + + list = e_addressbook_view_get_selected (view); + g_return_if_fail (list != NULL); + + /* Convert the list of contacts to a list of destinations. */ + for (iter = list; iter != NULL; iter = iter->next) { + EContact *contact = iter->data; + EDestination *destination; + + destination = e_destination_new (); + e_destination_set_contact (destination, contact, 0); + g_object_unref (contact); + + iter->data = destination; + } + + eab_send_as_attachment (list); + g_list_foreach (list, (GFunc) g_object_unref, NULL); + g_list_free (list); +} + +static void +action_contact_move_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (view != NULL); + + e_addressbook_view_move_to_folder (view, FALSE); +} + +static void +action_contact_new_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + EAddressbookModel *model; + EContact *contact; + GtkWidget *editor; + EBook *book; + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (view != NULL); + + model = e_addressbook_view_get_model (view); + book = e_addressbook_model_get_book (model); + g_return_if_fail (book != NULL); + + contact = e_contact_new (); + editor = e_contact_editor_new (book, contact, TRUE, TRUE); + eab_editor_show (EAB_EDITOR (editor)); + g_object_unref (contact); +} + +static void +action_contact_new_list_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + EAddressbookModel *model; + EContact *contact; + GtkWidget *editor; + EBook *book; + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (view != NULL); + + model = e_addressbook_view_get_model (view); + book = e_addressbook_model_get_book (model); + g_return_if_fail (book != NULL); + + contact = e_contact_new (); + editor = e_contact_list_editor_new (book, contact, TRUE, TRUE); + eab_editor_show (EAB_EDITOR (editor)); + g_object_unref (contact); +} + +static void +action_contact_open_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (view != NULL); + + e_addressbook_view_view (view); +} + +static void +action_contact_preview_cb (GtkToggleAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + gboolean visible; + + book_shell_content = book_shell_view->priv->book_shell_content; + visible = gtk_toggle_action_get_active (action); + e_book_shell_content_set_preview_visible (book_shell_content, visible); +} + +static void +action_contact_print_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + GtkPrintOperationAction print_action; + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (view != NULL); + + print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; + e_addressbook_view_print (view, print_action); +} + +static void +action_contact_print_preview_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + GtkPrintOperationAction print_action; + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (view != NULL); + + print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW; + e_addressbook_view_print (view, print_action); +} + +static void +action_contact_save_as_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (view != NULL); + + e_addressbook_view_save_as (view, FALSE); +} + +static void +action_contact_search_cb (GtkRadioAction *action, + GtkRadioAction *current, + EBookShellView *book_shell_view) +{ + EShellView *shell_view; + EShellContent *shell_content; + const gchar *search_hint; + + /* XXX Figure out a way to handle this in EShellContent + * instead of every shell view having to handle it. + * The problem is EShellContent does not know what + * the search option actions are for this view. It + * would have to dig up the popup menu and retrieve + * the action for each menu item. Seems messy. */ + + shell_view = E_SHELL_VIEW (book_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + + search_hint = gtk_action_get_label (GTK_ACTION (current)); + e_shell_content_set_search_hint (shell_content, search_hint); +} + +static void +action_contact_select_all_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (view != NULL); + + e_addressbook_view_select_all (view); +} + +static void +action_contact_send_message_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + GList *list, *iter; + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + g_return_if_fail (view != NULL); + + list = e_addressbook_view_get_selected (view); + g_return_if_fail (list != NULL); + + /* Convert the list of contacts to a list of destinations. */ + for (iter = list; iter != NULL; iter = iter->next) { + EContact *contact = iter->data; + EDestination *destination; + + destination = e_destination_new (); + e_destination_set_contact (destination, contact, 0); + g_object_unref (contact); + + iter->data = destination; + } + + eab_send_as_to (list); + g_list_foreach (list, (GFunc) g_object_unref, NULL); + g_list_free (list); +} + +static void +action_gal_save_custom_view_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EShellView *shell_view; + EAddressbookView *address_view; + GalViewInstance *view_instance; + + /* All shell views respond to the activation of this action, + * which is defined by EShellWindow. But only the currently + * active shell view proceeds with saving the custom view. */ + shell_view = E_SHELL_VIEW (book_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + book_shell_content = book_shell_view->priv->book_shell_content; + address_view = e_book_shell_content_get_current_view (book_shell_content); + view_instance = e_addressbook_view_get_view_instance (address_view); + gal_view_instance_save_as (view_instance); +} + +static void +action_search_execute_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EShellView *shell_view; + + /* All shell views respond to the activation of this action, + * which is defined by EShellWindow. But only the currently + * active shell view proceeds with executing the search. */ + shell_view = E_SHELL_VIEW (book_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + e_book_shell_view_execute_search (book_shell_view); +} + +static void +action_search_filter_cb (GtkRadioAction *action, + GtkRadioAction *current, + EBookShellView *book_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + + shell_view = E_SHELL_VIEW (book_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + gtk_action_activate (ACTION (SEARCH_EXECUTE)); +} + +static GtkActionEntry contact_entries[] = { + + { "address-book-copy", + GTK_STOCK_COPY, + N_("Co_py All Contacts To..."), + NULL, + N_("Copy the contacts of the selected address book to another"), + G_CALLBACK (action_address_book_copy_cb) }, + + { "address-book-delete", + GTK_STOCK_DELETE, + N_("Del_ete Address Book"), + NULL, + N_("Delete the selected address book"), + G_CALLBACK (action_address_book_delete_cb) }, + + { "address-book-move", + "folder-move", + N_("Mo_ve All Contacts To..."), + NULL, + N_("Move the contacts of the selected address book to another"), + G_CALLBACK (action_address_book_move_cb) }, + + { "address-book-new", + "address-book-new", + N_("_New Address Book"), + NULL, + N_("Create a new address book"), + G_CALLBACK (action_address_book_new_cb) }, + + { "address-book-properties", + GTK_STOCK_PROPERTIES, + N_("Address _Book Properties"), + NULL, + N_("Show properties of the selected address book"), + G_CALLBACK (action_address_book_properties_cb) }, + + { "address-book-rename", + NULL, + N_("_Rename..."), + "F2", + N_("Rename the selected address book"), + G_CALLBACK (action_address_book_rename_cb) }, + + { "address-book-save-as", + GTK_STOCK_SAVE_AS, + N_("S_ave Address Book as vCard"), + NULL, + N_("Save the contacts of the selected address book as a vCard"), + G_CALLBACK (action_address_book_save_as_cb) }, + + { "address-book-stop", + GTK_STOCK_STOP, + NULL, + NULL, + N_("Stop loading"), + G_CALLBACK (action_address_book_stop_cb) }, + + { "contact-clipboard-copy", + GTK_STOCK_COPY, + NULL, + NULL, + N_("Copy the selection"), + G_CALLBACK (action_contact_clipboard_copy_cb) }, + + { "contact-clipboard-cut", + GTK_STOCK_CUT, + NULL, + NULL, + N_("Cut the selection"), + G_CALLBACK (action_contact_clipboard_cut_cb) }, + + { "contact-clipboard-paste", + GTK_STOCK_PASTE, + NULL, + NULL, + N_("Paste the clipboard"), + G_CALLBACK (action_contact_clipboard_paste_cb) }, + + { "contact-copy", + NULL, + N_("_Copy Contact To..."), + "y", + N_("Copy selected contacts to another address book"), + G_CALLBACK (action_contact_copy_cb) }, + + { "contact-delete", + GTK_STOCK_DELETE, + N_("_Delete Contact"), + "d", + N_("Delete selected contacts"), + G_CALLBACK (action_contact_delete_cb) }, + + { "contact-forward", + "mail-forward", + N_("_Forward Contact..."), + NULL, + N_("Send selected contacts to another person"), + G_CALLBACK (action_contact_forward_cb) }, + + { "contact-move", + NULL, + N_("_Move Contact To..."), + "v", + N_("Move selected contacts to another address book"), + G_CALLBACK (action_contact_move_cb) }, + + { "contact-new", + "contact-new", + N_("_New Contact..."), + NULL, + N_("Create a new contact"), + G_CALLBACK (action_contact_new_cb) }, + + { "contact-new-list", + "stock_contact-list", + N_("New Contact _List..."), + NULL, + N_("Create a new contact list"), + G_CALLBACK (action_contact_new_list_cb) }, + + { "contact-open", + NULL, + N_("_Open"), + "o", + N_("View the current contact"), + G_CALLBACK (action_contact_open_cb) }, + + { "contact-save-as", + GTK_STOCK_SAVE_AS, + N_("Save as vCard..."), + NULL, + N_("Save selected contacts as a vCard"), + G_CALLBACK (action_contact_save_as_cb) }, + + { "contact-select-all", + GTK_STOCK_SELECT_ALL, + NULL, + NULL, + N_("Select all contacts"), + G_CALLBACK (action_contact_select_all_cb) }, + + { "contact-send-message", + "mail-message-new", + N_("_Send Message to Contact..."), + NULL, + N_("Send a message to the selected contacts"), + G_CALLBACK (action_contact_send_message_cb) }, + + /*** Menus ***/ + + { "actions-menu", + NULL, + N_("_Actions"), + NULL, + NULL, + NULL } +}; + +static EPopupActionEntry contact_popup_entries[] = { + + { "address-book-popup-delete", + N_("_Delete"), + "address-book-delete" }, + + { "address-book-popup-properties", + N_("_Properties"), + "address-book-properties" }, + + { "address-book-popup-rename", + NULL, + "address-book-rename" }, + + { "address-book-popup-save-as", + N_("_Save as vCard..."), + "address-book-save-as" }, + + { "contact-popup-clipboard-copy", + NULL, + "contact-clipboard-copy" }, + + { "contact-popup-clipboard-cut", + NULL, + "contact-clipboard-cut" }, + + { "contact-popup-clipboard-paste", + NULL, + "contact-clipboard-paste" }, + + { "contact-popup-copy", + NULL, + "contact-copy" }, + + { "contact-popup-delete", + NULL, + "contact-delete" }, + + { "contact-popup-forward", + NULL, + "contact-forward" }, + + { "contact-popup-move", + NULL, + "contact-move" }, + + { "contact-popup-open", + NULL, + "contact-open" }, + + { "contact-popup-save-as", + NULL, + "contact-save-as" }, + + { "contact-popup-send-message", + NULL, + "contact-send-message" }, +}; + +static GtkToggleActionEntry contact_toggle_entries[] = { + + { "contact-preview", + NULL, + N_("Contact _Preview"), + "m", + N_("Show contact preview window"), + G_CALLBACK (action_contact_preview_cb), + TRUE } +}; + +static GtkRadioActionEntry contact_filter_entries[] = { + + { "contact-filter-any-category", + NULL, + N_("Any Category"), + NULL, + NULL, + CONTACT_FILTER_ANY_CATEGORY }, + + { "contact-filter-unmatched", + NULL, + N_("Unmatched"), + NULL, + NULL, + CONTACT_FILTER_UNMATCHED } +}; + +static GtkRadioActionEntry contact_search_entries[] = { + + { "contact-search-any-field-contains", + NULL, + N_("Any field contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + CONTACT_SEARCH_ANY_FIELD_CONTAINS }, + + { "contact-search-email-begins-with", + NULL, + N_("Email begins with"), + NULL, + NULL, /* XXX Add a tooltip! */ + CONTACT_SEARCH_EMAIL_BEGINS_WITH }, + + { "contact-search-name-contains", + NULL, + N_("Name contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + CONTACT_SEARCH_NAME_CONTAINS } +}; + +static GtkActionEntry lockdown_printing_entries[] = { + + { "contact-print", + GTK_STOCK_PRINT, + NULL, + "p", + N_("Print selected contacts"), + G_CALLBACK (action_contact_print_cb) }, + + { "contact-print-preview", + GTK_STOCK_PRINT_PREVIEW, + NULL, + NULL, + N_("Preview the contacts to be printed"), + G_CALLBACK (action_contact_print_preview_cb) } +}; + +static EPopupActionEntry lockdown_printing_popup_entries[] = { + + { "contact-popup-print", + NULL, + "contact-print" } +}; + +void +e_book_shell_view_actions_init (EBookShellView *book_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkActionGroup *action_group; + GConfBridge *bridge; + GtkAction *action; + GObject *object; + const gchar *key; + + shell_view = E_SHELL_VIEW (book_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + /* Contact Actions */ + action_group = ACTION_GROUP (CONTACTS); + gtk_action_group_add_actions ( + action_group, contact_entries, + G_N_ELEMENTS (contact_entries), book_shell_view); + e_action_group_add_popup_actions ( + action_group, contact_popup_entries, + G_N_ELEMENTS (contact_popup_entries)); + gtk_action_group_add_toggle_actions ( + action_group, contact_toggle_entries, + G_N_ELEMENTS (contact_toggle_entries), book_shell_view); + gtk_action_group_add_radio_actions ( + action_group, contact_search_entries, + G_N_ELEMENTS (contact_search_entries), + CONTACT_SEARCH_NAME_CONTAINS, + G_CALLBACK (action_contact_search_cb), book_shell_view); + + /* Lockdown Printing Actions */ + action_group = ACTION_GROUP (LOCKDOWN_PRINTING); + gtk_action_group_add_actions ( + action_group, lockdown_printing_entries, + G_N_ELEMENTS (lockdown_printing_entries), book_shell_view); + e_action_group_add_popup_actions ( + action_group, lockdown_printing_popup_entries, + G_N_ELEMENTS (lockdown_printing_popup_entries)); + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (ACTION (CONTACT_PREVIEW)); + key = "/apps/evolution/addressbook/display/show_preview"; + gconf_bridge_bind_property (bridge, key, object, "active"); + + /* Fine tuning. */ + + action = ACTION (CONTACT_DELETE); + g_object_set (action, "short-label", _("Delete"), NULL); + + g_signal_connect ( + ACTION (GAL_SAVE_CUSTOM_VIEW), "activate", + G_CALLBACK (action_gal_save_custom_view_cb), book_shell_view); + + g_signal_connect ( + ACTION (SEARCH_EXECUTE), "activate", + G_CALLBACK (action_search_execute_cb), book_shell_view); +} + +void +e_book_shell_view_update_search_filter (EBookShellView *book_shell_view) +{ + EShellView *shell_view; + EShellContent *shell_content; + EShellWindow *shell_window; + GtkActionGroup *action_group; + GtkRadioAction *radio_action; + GList *list, *iter; + GSList *group; + gint ii; + + shell_view = E_SHELL_VIEW (book_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + action_group = ACTION_GROUP (CONTACTS_FILTER); + e_action_group_remove_all_actions (action_group); + + /* Add the standard filter actions. */ + gtk_action_group_add_radio_actions ( + action_group, contact_filter_entries, + G_N_ELEMENTS (contact_filter_entries), + CONTACT_FILTER_ANY_CATEGORY, + G_CALLBACK (action_search_filter_cb), + book_shell_view); + + /* Retrieve the radio group from an action we just added. */ + list = gtk_action_group_list_actions (action_group); + radio_action = GTK_RADIO_ACTION (list->data); + group = gtk_radio_action_get_group (radio_action); + g_list_free (list); + + /* Build the category actions. */ + + list = e_categories_get_list (); + for (iter = list, ii = 0; iter != NULL; iter = iter->next, ii++) { + const gchar *category_name = iter->data; + const gchar *filename; + GtkAction *action; + gchar *action_name; + + action_name = g_strdup_printf ( + "contact-filter-category-%d", ii); + radio_action = gtk_radio_action_new ( + action_name, category_name, NULL, NULL, ii); + g_free (action_name); + + /* Convert the category icon file to a themed icon name. */ + filename = e_categories_get_icon_file_for (category_name); + if (filename != NULL && *filename != '\0') { + gchar *basename; + gchar *cp; + + basename = g_path_get_basename (filename); + + /* Lose the file extension. */ + if ((cp = strrchr (basename, '.')) != NULL) + *cp = '\0'; + + g_object_set ( + radio_action, "icon-name", basename, NULL); + + g_free (basename); + } + + gtk_radio_action_set_group (radio_action, group); + group = gtk_radio_action_get_group (radio_action); + + /* The action group takes ownership of the action. */ + action = GTK_ACTION (radio_action); + gtk_action_group_add_action (action_group, action); + g_object_unref (radio_action); + } + g_list_free (list); + + /* Use any action in the group; doesn't matter which. */ + e_shell_content_set_filter_action (shell_content, radio_action); + + ii = CONTACT_FILTER_UNMATCHED; + e_shell_content_add_filter_separator_after (shell_content, ii); +} diff --git a/modules/addressbook/e-book-shell-view-actions.h b/modules/addressbook/e-book-shell-view-actions.h new file mode 100644 index 0000000000..8e3d31f7bf --- /dev/null +++ b/modules/addressbook/e-book-shell-view-actions.h @@ -0,0 +1,91 @@ +/* + * e-book-shell-view-actions.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_BOOK_SHELL_VIEW_ACTIONS_H +#define E_BOOK_SHELL_VIEW_ACTIONS_H + +#include + +/* Address Book Actions */ +#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "address-book-copy") +#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "address-book-delete") +#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_MOVE(window) \ + E_SHELL_WINDOW_ACTION ((window), "address-book-move") +#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_PROPERTIES(window) \ + E_SHELL_WINDOW_ACTION ((window), "address-book-properties") +#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_RENAME(window) \ + E_SHELL_WINDOW_ACTION ((window), "address-book-rename") +#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_SAVE_AS(window) \ + E_SHELL_WINDOW_ACTION ((window), "address-book-save-as") +#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_STOP(window) \ + E_SHELL_WINDOW_ACTION ((window), "address-book-stop") + +/* Contact Actions */ +#define E_SHELL_WINDOW_ACTION_CONTACT_CLIPBOARD_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-clipboard-copy") +#define E_SHELL_WINDOW_ACTION_CONTACT_CLIPBOARD_CUT(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-clipboard-cut") +#define E_SHELL_WINDOW_ACTION_CONTACT_CLIPBOARD_PASTE(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-clipboard-paste") +#define E_SHELL_WINDOW_ACTION_CONTACT_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-copy") +#define E_SHELL_WINDOW_ACTION_CONTACT_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-delete") +#define E_SHELL_WINDOW_ACTION_CONTACT_FORWARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-forward") +#define E_SHELL_WINDOW_ACTION_CONTACT_MOVE(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-move") +#define E_SHELL_WINDOW_ACTION_CONTACT_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-new") +#define E_SHELL_WINDOW_ACTION_CONTACT_NEW_LIST(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-new-list") +#define E_SHELL_WINDOW_ACTION_CONTACT_OPEN(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-open") +#define E_SHELL_WINDOW_ACTION_CONTACT_PREVIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-preview") +#define E_SHELL_WINDOW_ACTION_CONTACT_PRINT(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-print") +#define E_SHELL_WINDOW_ACTION_CONTACT_PRINT_PREVIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-print-preview") +#define E_SHELL_WINDOW_ACTION_CONTACT_SAVE_AS(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-save-as") +#define E_SHELL_WINDOW_ACTION_CONTACT_SELECT_ALL(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-select-all") +#define E_SHELL_WINDOW_ACTION_CONTACT_SEND_MESSAGE(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-send-message") + +/* Search Actions */ +#define E_SHELL_WINDOW_ACTION_CONTACT_SEARCH_ANY_FIELD_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-search-any-field-contains") +#define E_SHELL_WINDOW_ACTION_CONTACT_SEARCH_EMAIL_BEGINS_WITH(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-search-email-begins-with") +#define E_SHELL_WINDOW_ACTION_CONTACT_SEARCH_NAME_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-search-name-contains") + +/* Action Groups */ +#define E_SHELL_WINDOW_ACTION_GROUP_CONTACTS(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "contacts") +#define E_SHELL_WINDOW_ACTION_GROUP_CONTACTS_FILTER(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "contacts-filter") + +#endif /* E_BOOK_SHELL_VIEW_ACTIONS_H */ diff --git a/modules/addressbook/e-book-shell-view-private.c b/modules/addressbook/e-book-shell-view-private.c new file mode 100644 index 0000000000..ec3562e87a --- /dev/null +++ b/modules/addressbook/e-book-shell-view-private.c @@ -0,0 +1,621 @@ +/* + * e-book-shell-view-private.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-book-shell-view-private.h" + +#include "widgets/menus/gal-view-factory-etable.h" +#include "addressbook/gui/widgets/gal-view-factory-minicard.h" + +#include "addressbook.h" + +static void +open_contact (EBookShellView *book_shell_view, + EContact *contact, + gboolean is_new_contact, + EAddressbookView *view) +{ + EAddressbookModel *model; + GtkWidget *editor; + EBook *book; + gboolean editable; + + model = e_addressbook_view_get_model (view); + book = e_addressbook_model_get_book (model); + editable = e_addressbook_model_get_editable (model); + + if (e_contact_get (contact, E_CONTACT_IS_LIST)) + editor = e_contact_list_editor_new ( + book, contact, is_new_contact, editable); + else + editor = e_contact_editor_new ( + book, contact, is_new_contact, editable); + + eab_editor_show (EAB_EDITOR (editor)); +} + +static void +popup_event (EBookShellView *book_shell_view, + GdkEventButton *event) +{ + EShellView *shell_view; + const gchar *widget_path; + + widget_path = "/contact-popup"; + shell_view = E_SHELL_VIEW (book_shell_view); + + e_shell_view_show_popup_menu (shell_view, widget_path, event); +} + +static void +book_shell_view_selection_change_foreach (gint row, + EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *view; + EAddressbookModel *model; + EContact *contact; + + /* XXX A "foreach" function is kind of a silly way to retrieve + * the one and only selected contact, but this is the only + * means that ESelectionModel provides. */ + + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + model = e_addressbook_view_get_model (view); + contact = e_addressbook_model_get_contact (model, row); + + e_book_shell_content_set_preview_contact (book_shell_content, contact); +} + +static void +selection_change (EBookShellView *book_shell_view, + EAddressbookView *view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *current_view; + ESelectionModel *selection_model; + EShellView *shell_view; + gint n_selected; + + shell_view = E_SHELL_VIEW (book_shell_view); + book_shell_content = book_shell_view->priv->book_shell_content; + current_view = e_book_shell_content_get_current_view (book_shell_content); + + if (view != current_view) + return; + + e_shell_view_update_actions (shell_view); + + selection_model = e_addressbook_view_get_selection_model (view); + + n_selected = (selection_model != NULL) ? + e_selection_model_selected_count (selection_model) : 0; + + if (n_selected == 1) + e_selection_model_foreach ( + selection_model, (EForeachFunc) + book_shell_view_selection_change_foreach, + book_shell_view); + else + e_book_shell_content_set_preview_contact ( + book_shell_content, NULL); +} + +static void +contact_changed (EBookShellView *book_shell_view, + EContact *contact) +{ + EBookShellContent *book_shell_content; + EContact *preview_contact; + + book_shell_content = book_shell_view->priv->book_shell_content; + + preview_contact = + e_book_shell_content_get_preview_contact (book_shell_content); + + if (contact != preview_contact) + return; + + /* Re-render the same contact. */ + e_book_shell_content_set_preview_contact (book_shell_content, contact); +} + +static void +contacts_removed (EBookShellView *book_shell_view, + GArray *removed_indices, + EAddressbookModel *model) +{ + EBookShellContent *book_shell_content; + EContact *preview_contact; + + book_shell_content = book_shell_view->priv->book_shell_content; + + preview_contact = + e_book_shell_content_get_preview_contact (book_shell_content); + + if (preview_contact == NULL) + return; + + /* Is the displayed contact still in the model? */ + if (e_addressbook_model_find (model, preview_contact) < 0) + return; + + /* If not, clear the contact display. */ + e_book_shell_content_set_preview_contact (book_shell_content, NULL); +} + +static void +book_open_cb (EBook *book, + EBookStatus status, + gpointer user_data) +{ + EAddressbookView *view = user_data; + EAddressbookModel *model; + ESource *source; + + source = e_book_get_source (book); + model = e_addressbook_view_get_model (view); + + if (status == E_BOOK_ERROR_OK) { + e_addressbook_model_set_book (model, book); + e_addressbook_model_force_folder_bar_message (model); + } else if (status != E_BOOK_ERROR_CANCELLED) + eab_load_error_dialog (NULL /* XXX */, source, status); +} + +static void +book_shell_view_activate_selected_source (EBookShellView *book_shell_view, + ESourceSelector *selector) +{ + EShellView *shell_view; + EBookShellContent *book_shell_content; + EAddressbookView *view; + EAddressbookModel *model; + ESource *source; + GalViewInstance *view_instance; + GHashTable *hash_table; + GtkWidget *widget; + const gchar *uid; + gchar *view_id; + + shell_view = E_SHELL_VIEW (book_shell_view); + book_shell_content = book_shell_view->priv->book_shell_content; + source = e_source_selector_peek_primary_selection (selector); + + if (source == NULL) + return; + + uid = e_source_peek_uid (source); + hash_table = book_shell_view->priv->uid_to_view; + widget = g_hash_table_lookup (hash_table, uid); + + if (widget != NULL) { + EBook *book; + + /* There is a view for this UID. Make sure the view + * actually contains an EBook. The absence of an EBook + * suggests a previous load failed, so try again. */ + view = E_ADDRESSBOOK_VIEW (widget); + model = e_addressbook_view_get_model (view); + source = e_addressbook_view_get_source (view); + + if (e_addressbook_model_get_book (model) == NULL) { + book = e_book_new (source, NULL); + + if (book != NULL) + addressbook_load (book, book_open_cb, view); + } + + } else { + EBook *book; + + /* Create a view for this UID. */ + widget = e_addressbook_view_new (shell_view, source); + gtk_widget_show (widget); + + e_book_shell_content_insert_view ( + book_shell_content, + E_ADDRESSBOOK_VIEW (widget)); + + g_hash_table_insert ( + hash_table, g_strdup (uid), + g_object_ref (widget)); + + g_signal_connect_swapped ( + widget, "open-contact", + G_CALLBACK (open_contact), book_shell_view); + + g_signal_connect_swapped ( + widget, "popup-event", + G_CALLBACK (popup_event), book_shell_view); + + g_signal_connect_swapped ( + widget, "command-state-change", + G_CALLBACK (e_shell_view_update_actions), + book_shell_view); + + g_signal_connect_swapped ( + widget, "selection-change", + G_CALLBACK (selection_change), book_shell_view); + + book = e_book_new (source, NULL); + view = E_ADDRESSBOOK_VIEW (widget); + + if (book != NULL) + addressbook_load (book, book_open_cb, view); + + model = e_addressbook_view_get_model (view); + + g_signal_connect_swapped ( + model, "contact-changed", + G_CALLBACK (contact_changed), book_shell_view); + + g_signal_connect_swapped ( + model, "contacts-removed", + G_CALLBACK (contacts_removed), book_shell_view); + } + + e_book_shell_content_set_current_view ( + book_shell_content, E_ADDRESSBOOK_VIEW (widget)); + + /* XXX We have to keep the addressbook selector informed of the + * current view so it can move contacts via drag-and-drop. */ + e_addressbook_selector_set_current_view ( + E_ADDRESSBOOK_SELECTOR (selector), + E_ADDRESSBOOK_VIEW (widget)); + + view_instance = e_addressbook_view_get_view_instance (view); + view_id = gal_view_instance_get_current_view_id (view_instance); + e_shell_view_set_view_id (shell_view, view_id); + g_free (view_id); + + e_addressbook_model_force_folder_bar_message (model); + selection_change (book_shell_view, view); +} + +static gboolean +book_shell_view_show_popup_menu (GdkEventButton *event, + EShellView *shell_view) +{ + const gchar *widget_path; + + widget_path = "/address-book-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); + + return TRUE; +} + +static gboolean +book_shell_view_selector_button_press_event_cb (EShellView *shell_view, + GdkEventButton *event) +{ + /* XXX Use ESourceSelector's "popup-event" signal instead. */ + + if (event->button == 3 && event->type == GDK_BUTTON_PRESS) + return book_shell_view_show_popup_menu (event, shell_view); + + return FALSE; +} + +static gboolean +book_shell_view_selector_popup_menu_cb (EShellView *shell_view) +{ + /* XXX Use ESourceSelector's "popup-event" signal instead. */ + + return book_shell_view_show_popup_menu (NULL, shell_view); +} + +static gboolean +book_shell_view_selector_key_press_event_cb (EShellView *shell_view, + GdkEventKey *event) +{ + EShellWindow *shell_window; + + /* Needed for the ACTION() macro. */ + shell_window = e_shell_view_get_shell_window (shell_view); + + if (event->keyval == GDK_Delete) { + gtk_action_activate (ACTION (ADDRESS_BOOK_DELETE)); + return TRUE; + } + + return FALSE; +} + +static void +book_shell_view_load_view_collection (EShellViewClass *shell_view_class) +{ + GalViewCollection *collection; + GalViewFactory *factory; + ETableSpecification *spec; + const gchar *base_dir; + gchar *filename; + + collection = shell_view_class->view_collection; + + base_dir = EVOLUTION_ETSPECDIR; + spec = e_table_specification_new (); + filename = g_build_filename (base_dir, ETSPEC_FILENAME, NULL); + if (!e_table_specification_load_from_file (spec, filename)) + g_critical ("Unable to load ETable specification file " + "for address book"); + g_free (filename); + + factory = gal_view_factory_etable_new (spec); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + g_object_unref (spec); + + factory = gal_view_factory_minicard_new (); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + + gal_view_collection_load (collection); +} + +static void +book_shell_view_notify_view_id_cb (EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EAddressbookView *address_view; + GalViewInstance *view_instance; + const gchar *view_id; + + book_shell_content = book_shell_view->priv->book_shell_content; + address_view = e_book_shell_content_get_current_view (book_shell_content); + view_instance = e_addressbook_view_get_view_instance (address_view); + view_id = e_shell_view_get_view_id (E_SHELL_VIEW (book_shell_view)); + + /* A NULL view ID implies we're in a custom view. But you can + * only get to a custom view via the "Define Views" dialog, which + * would have already modified the view instance appropriately. + * Furthermore, there's no way to refer to a custom view by ID + * anyway, since custom views have no IDs. */ + if (view_id == NULL) + return; + + gal_view_instance_set_current_view_id (view_instance, view_id); +} + +void +e_book_shell_view_private_init (EBookShellView *book_shell_view, + EShellViewClass *shell_view_class) +{ + EBookShellViewPrivate *priv = book_shell_view->priv; + GHashTable *uid_to_view; + GHashTable *uid_to_editor; + + uid_to_view = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_object_unref); + + uid_to_editor = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_free); + + priv->uid_to_view = uid_to_view; + priv->uid_to_editor = uid_to_editor; + + if (!gal_view_collection_loaded (shell_view_class->view_collection)) + book_shell_view_load_view_collection (shell_view_class); + + g_signal_connect ( + book_shell_view, "notify::view-id", + G_CALLBACK (book_shell_view_notify_view_id_cb), NULL); +} + +void +e_book_shell_view_private_constructed (EBookShellView *book_shell_view) +{ + EBookShellViewPrivate *priv = book_shell_view->priv; + EShellContent *shell_content; + EShellSidebar *shell_sidebar; + EShellBackend *shell_backend; + EShellView *shell_view; + EShellWindow *shell_window; + ESourceSelector *selector; + + shell_view = E_SHELL_VIEW (book_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + e_shell_window_add_action_group (shell_window, "contacts"); + e_shell_window_add_action_group (shell_window, "contacts-filter"); + + /* Cache these to avoid lots of awkward casting. */ + priv->book_shell_backend = g_object_ref (shell_backend); + priv->book_shell_content = g_object_ref (shell_content); + priv->book_shell_sidebar = g_object_ref (shell_sidebar); + + selector = e_book_shell_sidebar_get_selector ( + E_BOOK_SHELL_SIDEBAR (shell_sidebar)); + + g_signal_connect_swapped ( + selector, "button-press-event", + G_CALLBACK (book_shell_view_selector_button_press_event_cb), + book_shell_view); + + g_signal_connect_swapped ( + selector, "key-press-event", + G_CALLBACK (book_shell_view_selector_key_press_event_cb), + book_shell_view); + + g_signal_connect_swapped ( + selector, "popup-menu", + G_CALLBACK (book_shell_view_selector_popup_menu_cb), + book_shell_view); + + g_signal_connect_swapped ( + selector, "primary-selection-changed", + G_CALLBACK (book_shell_view_activate_selected_source), + book_shell_view); + + e_categories_register_change_listener ( + G_CALLBACK (e_book_shell_view_update_search_filter), + book_shell_view); + + e_book_shell_view_actions_init (book_shell_view); + book_shell_view_activate_selected_source (book_shell_view, selector); + e_book_shell_view_update_search_filter (book_shell_view); +} + +void +e_book_shell_view_private_dispose (EBookShellView *book_shell_view) +{ + EBookShellViewPrivate *priv = book_shell_view->priv; + + DISPOSE (priv->book_shell_backend); + DISPOSE (priv->book_shell_content); + DISPOSE (priv->book_shell_sidebar); + + g_hash_table_remove_all (priv->uid_to_view); + g_hash_table_remove_all (priv->uid_to_editor); +} + +void +e_book_shell_view_private_finalize (EBookShellView *book_shell_view) +{ + EBookShellViewPrivate *priv = book_shell_view->priv; + + g_hash_table_destroy (priv->uid_to_view); + g_hash_table_destroy (priv->uid_to_editor); +} + +void +e_book_shell_view_execute_search (EBookShellView *book_shell_view) +{ + EBookShellContent *book_shell_content; + EShellView *shell_view; + EShellWindow *shell_window; + EShellContent *shell_content; + GtkAction *action; + GString *string; + EAddressbookView *view; + EAddressbookModel *model; + FilterRule *rule; + const gchar *format; + const gchar *text; + gchar *query; + gchar *temp; + gint value; + + shell_view = E_SHELL_VIEW (book_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + shell_content = e_shell_view_get_shell_content (shell_view); + text = e_shell_content_get_search_text (shell_content); + + shell_window = e_shell_view_get_shell_window (shell_view); + action = ACTION (CONTACT_SEARCH_ANY_FIELD_CONTAINS); + value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + + if (text == NULL || *text == '\0') { + text = ""; + value = CONTACT_SEARCH_ANY_FIELD_CONTAINS; + } + + switch (value) { + case CONTACT_SEARCH_NAME_CONTAINS: + format = "(contains \"full_name\" %s)"; + break; + + case CONTACT_SEARCH_EMAIL_BEGINS_WITH: + format = "(beginswith \"email\" %s)"; + break; + + default: + text = ""; + /* fall through */ + + case CONTACT_SEARCH_ANY_FIELD_CONTAINS: + format = "(contains \"x-evolution-any-field\" %s)"; + break; + } + + /* Build the query. */ + string = g_string_new (""); + e_sexp_encode_string (string, text); + query = g_strdup_printf (format, string->str); + g_string_free (string, TRUE); + + /* Apply selected filter. */ + value = e_shell_content_get_filter_value (shell_content); + switch (value) { + case CONTACT_FILTER_ANY_CATEGORY: + break; + + case CONTACT_FILTER_UNMATCHED: + temp = g_strdup_printf ( + "(and (not (and (exists \"CATEGORIES\") " + "(not (is \"CATEGORIES\" \"\")))) %s)", + query); + g_free (query); + query = temp; + break; + + default: + { + GList *categories; + const gchar *category_name; + + categories = e_categories_get_list (); + category_name = g_list_nth_data (categories, value); + g_list_free (categories); + + temp = g_strdup_printf ( + "(and (is \"category_list\" \"%s\") %s)", + category_name, query); + g_free (query); + query = temp; + } + } + + /* XXX This is wrong. We need to programmatically construct a + * FilterRule, tell it to build code, and pass the resulting + * expression string to EAddressbookModel. */ + rule = filter_rule_new (); + e_shell_content_set_search_rule (shell_content, rule); + g_object_unref (rule); + + /* Submit the query. */ + book_shell_content = book_shell_view->priv->book_shell_content; + view = e_book_shell_content_get_current_view (book_shell_content); + model = e_addressbook_view_get_model (view); + e_addressbook_model_set_query (model, query); + g_free (query); + + e_book_shell_content_set_preview_contact (book_shell_content, NULL); +} + +void +e_book_shell_view_editor_weak_notify (EditorUidClosure *closure, + GObject *where_the_object_was) +{ + GHashTable *hash_table; + + hash_table = closure->view->priv->uid_to_editor; + g_hash_table_remove (hash_table, closure->uid); +} diff --git a/modules/addressbook/e-book-shell-view-private.h b/modules/addressbook/e-book-shell-view-private.h new file mode 100644 index 0000000000..b4701aea81 --- /dev/null +++ b/modules/addressbook/e-book-shell-view-private.h @@ -0,0 +1,129 @@ +/* + * e-book-shell-view-private.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_BOOK_SHELL_VIEW_PRIVATE_H +#define E_BOOK_SHELL_VIEW_PRIVATE_H + +#include "e-book-shell-view.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "e-util/gconf-bridge.h" +#include "shell/e-shell-content.h" +#include "shell/e-shell-sidebar.h" +#include "misc/e-popup-action.h" + +#include "addressbook/gui/contact-editor/e-contact-editor.h" +#include "addressbook/gui/contact-list-editor/e-contact-list-editor.h" +#include "addressbook/gui/widgets/eab-gui-util.h" +#include "addressbook/gui/widgets/e-addressbook-view.h" +#include "addressbook/gui/widgets/e-addressbook-selector.h" + +#include "e-book-shell-backend.h" +#include "e-book-shell-content.h" +#include "e-book-shell-sidebar.h" +#include "e-book-shell-view-actions.h" + +#define E_BOOK_SHELL_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_BOOK_SHELL_VIEW, EBookShellViewPrivate)) + +/* Shorthand, requires a variable named "shell_window". */ +#define ACTION(name) \ + (E_SHELL_WINDOW_ACTION_##name (shell_window)) +#define ACTION_GROUP(name) \ + (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) + +/* For use in dispose() methods. */ +#define DISPOSE(obj) \ + G_STMT_START { \ + if ((obj) != NULL) { g_object_unref (obj); (obj) = NULL; } \ + } G_STMT_END + +/* ETable Specifications */ +#define ETSPEC_FILENAME "e-addressbook-view.etspec" + +G_BEGIN_DECLS + +typedef struct _EditorUidClosure EditorUidClosure; + +struct _EditorUidClosure { + GtkWidget *editor; + gchar *uid; + EBookShellView *view; +}; + +/* List these in the order to be displayed. + * Positive values are reserved for categories. */ +enum { + CONTACT_FILTER_ANY_CATEGORY = -2, + CONTACT_FILTER_UNMATCHED = -1 +}; + +/* List these in the order to be displayed. */ +enum { + CONTACT_SEARCH_NAME_CONTAINS, + CONTACT_SEARCH_EMAIL_BEGINS_WITH, + CONTACT_SEARCH_ANY_FIELD_CONTAINS +}; + +struct _EBookShellViewPrivate { + + /* These are just for convenience. */ + EBookShellBackend *book_shell_backend; + EBookShellContent *book_shell_content; + EBookShellSidebar *book_shell_sidebar; + + GHashTable *uid_to_view; + GHashTable *uid_to_editor; +}; + +void e_book_shell_view_private_init + (EBookShellView *book_shell_view, + EShellViewClass *shell_view_class); +void e_book_shell_view_private_constructed + (EBookShellView *book_shell_view); +void e_book_shell_view_private_dispose + (EBookShellView *book_shell_view); +void e_book_shell_view_private_finalize + (EBookShellView *book_shell_view); + +/* Private Utilities */ + +void e_book_shell_view_actions_init + (EBookShellView *book_shell_view); +void e_book_shell_view_execute_search + (EBookShellView *book_shell_view); +void e_book_shell_view_editor_weak_notify + (EditorUidClosure *closure, + GObject *where_the_object_was); +void e_book_shell_view_update_search_filter + (EBookShellView *book_shell_view); + +G_END_DECLS + +#endif /* E_BOOK_SHELL_VIEW_PRIVATE_H */ diff --git a/modules/addressbook/e-book-shell-view.c b/modules/addressbook/e-book-shell-view.c new file mode 100644 index 0000000000..ea48bb534c --- /dev/null +++ b/modules/addressbook/e-book-shell-view.c @@ -0,0 +1,318 @@ +/* + * e-book-shell-view.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-book-shell-view-private.h" + +static gpointer parent_class; +static GType book_shell_view_type; + +static void +book_shell_view_source_list_changed_cb (EBookShellView *book_shell_view, + ESourceList *source_list) +{ + EBookShellViewPrivate *priv = book_shell_view->priv; + EBookShellContent *book_shell_content; + EShellView *shell_view; + GList *keys, *iter; + + shell_view = E_SHELL_VIEW (book_shell_view); + book_shell_content = book_shell_view->priv->book_shell_content; + + keys = g_hash_table_get_keys (priv->uid_to_view); + for (iter = keys; iter != NULL; iter = iter->next) { + gchar *uid = iter->data; + EAddressbookView *view; + + /* If the source still exists, move on. */ + if (e_source_list_peek_source_by_uid (source_list, uid)) + continue; + + /* Remove the view for the deleted source. */ + view = g_hash_table_lookup (priv->uid_to_view, uid); + e_book_shell_content_remove_view (book_shell_content, view); + g_hash_table_remove (priv->uid_to_view, uid); + } + g_list_free (keys); + + keys = g_hash_table_get_keys (priv->uid_to_editor); + for (iter = keys; iter != NULL; iter = iter->next) { + gchar *uid = iter->data; + EditorUidClosure *closure; + + /* If the source still exists, move on. */ + if (e_source_list_peek_source_by_uid (source_list, uid)) + continue; + + /* Remove the editor for the deleted source. */ + closure = g_hash_table_lookup (priv->uid_to_editor, uid); + g_object_weak_unref ( + G_OBJECT (closure->editor), (GWeakNotify) + e_book_shell_view_editor_weak_notify, closure); + gtk_widget_destroy (closure->editor); + g_hash_table_remove (priv->uid_to_editor, uid); + } + g_list_free (keys); + + e_shell_view_update_actions (shell_view); +} + +static void +book_shell_view_dispose (GObject *object) +{ + EBookShellView *book_shell_view; + + book_shell_view = E_BOOK_SHELL_VIEW (object); + e_book_shell_view_private_dispose (book_shell_view); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +book_shell_view_finalize (GObject *object) +{ + EBookShellView *book_shell_view; + + book_shell_view = E_BOOK_SHELL_VIEW (object); + e_book_shell_view_private_finalize (book_shell_view); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +book_shell_view_constructed (GObject *object) +{ + EBookShellView *book_shell_view; + EBookShellBackend *book_shell_backend; + ESourceList *source_list; + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + book_shell_view = E_BOOK_SHELL_VIEW (object); + e_book_shell_view_private_constructed (book_shell_view); + + book_shell_backend = book_shell_view->priv->book_shell_backend; + source_list = e_book_shell_backend_get_source_list (book_shell_backend); + + g_signal_connect_swapped ( + source_list, "changed", + G_CALLBACK (book_shell_view_source_list_changed_cb), + book_shell_view); +} + +static void +book_shell_view_update_actions (EShellView *shell_view) +{ + EBookShellViewPrivate *priv; + EShellContent *shell_content; + EShellSidebar *shell_sidebar; + EShellWindow *shell_window; + GtkAction *action; + const gchar *label; + gboolean sensitive; + guint32 state; + + /* Be descriptive. */ + gboolean any_contacts_selected; + gboolean has_primary_source; + gboolean multiple_contacts_selected; + gboolean primary_source_is_system; + gboolean single_contact_selected; + gboolean selection_is_contact_list; + gboolean selection_has_email; + gboolean source_is_busy; + gboolean source_is_editable; + gboolean source_is_empty; + + priv = E_BOOK_SHELL_VIEW_GET_PRIVATE (shell_view); + + shell_window = e_shell_view_get_shell_window (shell_view); + + shell_content = e_shell_view_get_shell_content (shell_view); + state = e_shell_content_check_state (shell_content); + + single_contact_selected = + (state & E_BOOK_SHELL_CONTENT_SELECTION_SINGLE); + multiple_contacts_selected = + (state & E_BOOK_SHELL_CONTENT_SELECTION_MULTIPLE); + selection_has_email = + (state & E_BOOK_SHELL_CONTENT_SELECTION_HAS_EMAIL); + selection_is_contact_list = + (state & E_BOOK_SHELL_CONTENT_SELECTION_IS_CONTACT_LIST); + source_is_busy = + (state & E_BOOK_SHELL_CONTENT_SOURCE_IS_BUSY); + source_is_editable = + (state & E_BOOK_SHELL_CONTENT_SOURCE_IS_EDITABLE); + source_is_empty = + (state & E_BOOK_SHELL_CONTENT_SOURCE_IS_EMPTY); + + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + state = e_shell_sidebar_check_state (shell_sidebar); + + has_primary_source = + (state & E_BOOK_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE); + primary_source_is_system = + (state & E_BOOK_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM); + + any_contacts_selected = + (single_contact_selected || multiple_contacts_selected); + + action = ACTION (ADDRESS_BOOK_DELETE); + sensitive = has_primary_source && !primary_source_is_system; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (ADDRESS_BOOK_RENAME); + sensitive = has_primary_source; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (ADDRESS_BOOK_STOP); + sensitive = source_is_busy; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_CLIPBOARD_COPY); + sensitive = any_contacts_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_CLIPBOARD_CUT); + sensitive = source_is_editable && any_contacts_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_CLIPBOARD_PASTE); + sensitive = source_is_editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_COPY); + sensitive = any_contacts_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_DELETE); + sensitive = source_is_editable && any_contacts_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_FORWARD); + sensitive = any_contacts_selected; + gtk_action_set_sensitive (action, sensitive); + if (multiple_contacts_selected) + label = _("_Forward Contacts"); + else + label = _("_Forward Contact"); + g_object_set (action, "label", label, NULL); + + action = ACTION (CONTACT_MOVE); + sensitive = source_is_editable && any_contacts_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_OPEN); + sensitive = any_contacts_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_PRINT); + sensitive = any_contacts_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_PRINT_PREVIEW); + sensitive = any_contacts_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_SAVE_AS); + sensitive = any_contacts_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_SELECT_ALL); + sensitive = !(source_is_empty); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_SEND_MESSAGE); + sensitive = any_contacts_selected && selection_has_email; + gtk_action_set_sensitive (action, sensitive); + if (multiple_contacts_selected) + label = _("_Send Message to Contacts"); + else if (selection_is_contact_list) + label = _("_Send Message to List"); + else + label = _("_Send Message to Contact"); + g_object_set (action, "label", label, NULL); +} + +static void +book_shell_view_class_init (EBookShellViewClass *class) +{ + GObjectClass *object_class; + EShellViewClass *shell_view_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EBookShellViewPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->dispose = book_shell_view_dispose; + object_class->finalize = book_shell_view_finalize; + object_class->constructed = book_shell_view_constructed; + + shell_view_class = E_SHELL_VIEW_CLASS (class); + shell_view_class->label = _("Contacts"); + shell_view_class->icon_name = "x-office-address-book"; + shell_view_class->ui_definition = "evolution-contacts.ui"; + shell_view_class->ui_manager_id = "org.gnome.evolution.contacts"; + shell_view_class->search_options = "/contact-search-options"; + shell_view_class->search_rules = "addresstypes.xml"; + shell_view_class->new_shell_content = e_book_shell_content_new; + shell_view_class->new_shell_sidebar = e_book_shell_sidebar_new; + shell_view_class->update_actions = book_shell_view_update_actions; +} + +static void +book_shell_view_init (EBookShellView *book_shell_view, + EShellViewClass *shell_view_class) +{ + book_shell_view->priv = + E_BOOK_SHELL_VIEW_GET_PRIVATE (book_shell_view); + + e_book_shell_view_private_init (book_shell_view, shell_view_class); +} + +GType +e_book_shell_view_get_type (void) +{ + return book_shell_view_type; +} + +void +e_book_shell_view_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (EBookShellViewClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) book_shell_view_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EBookShellView), + 0, /* n_preallocs */ + (GInstanceInitFunc) book_shell_view_init, + NULL /* value_table */ + }; + + book_shell_view_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_VIEW, + "EBookShellView", &type_info, 0); +} diff --git a/modules/addressbook/e-book-shell-view.h b/modules/addressbook/e-book-shell-view.h new file mode 100644 index 0000000000..33a0c8a75d --- /dev/null +++ b/modules/addressbook/e-book-shell-view.h @@ -0,0 +1,66 @@ +/* + * e-book-shell-view.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_BOOK_SHELL_VIEW_H +#define E_BOOK_SHELL_VIEW_H + +#include + +/* Standard GObject macros */ +#define E_TYPE_BOOK_SHELL_VIEW \ + (e_book_shell_view_get_type ()) +#define E_BOOK_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_BOOK_SHELL_VIEW, EBookShellView)) +#define E_BOOK_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_BOOK_SHELL_VIEW, EBookShellViewClass)) +#define E_IS_BOOK_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_BOOK_SHELL_VIEW)) +#define E_IS_BOOK_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_BOOK_SHELL_VIEW)) +#define E_BOOK_SHELL_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_BOOK_SHELL_VIEW, EBookShellViewClass)) + +G_BEGIN_DECLS + +typedef struct _EBookShellView EBookShellView; +typedef struct _EBookShellViewClass EBookShellViewClass; +typedef struct _EBookShellViewPrivate EBookShellViewPrivate; + +struct _EBookShellView { + EShellView parent; + EBookShellViewPrivate *priv; +}; + +struct _EBookShellViewClass { + EShellViewClass parent_class; +}; + +GType e_book_shell_view_get_type (void); +void e_book_shell_view_register_type (GTypeModule *type_module); + +G_END_DECLS + +#endif /* E_BOOK_SHELL_VIEW_H */ diff --git a/modules/addressbook/eab-composer-util.c b/modules/addressbook/eab-composer-util.c new file mode 100644 index 0000000000..6d45f13a94 --- /dev/null +++ b/modules/addressbook/eab-composer-util.c @@ -0,0 +1,197 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "eab-composer-util.h" + +#include +#include +#include +#include + +#include "composer/e-msg-composer.h" +#include "addressbook/util/eab-book-util.h" +#include "addressbook/gui/widgets/eab-gui-util.h" + +void +eab_send_as_to (GList *destinations) +{ + EMsgComposer *composer; + EComposerHeaderTable *table; + GPtrArray *to_array; + GPtrArray *bcc_array; + + union { + gpointer *pdata; + EDestination **destinations; + } convert; + + if (destinations == NULL) + return; + + composer = e_msg_composer_new (); + table = e_msg_composer_get_header_table (composer); + + to_array = g_ptr_array_new (); + bcc_array = g_ptr_array_new (); + + /* Sort contacts into "To" and "Bcc" destinations. */ + while (destinations != NULL) { + EDestination *destination = destinations->data; + + if (e_destination_is_evolution_list (destination)) { + if (e_destination_list_show_addresses (destination)) + g_ptr_array_add (to_array, destination); + else + g_ptr_array_add (bcc_array, destination); + } else + g_ptr_array_add (to_array, destination); + + destinations = g_list_next (destinations); + } + + /* Add sentinels to each array. */ + g_ptr_array_add (to_array, NULL); + g_ptr_array_add (bcc_array, NULL); + + /* XXX Acrobatics like this make me question whether NULL-terminated + * arrays are really the best argument type for passing a list of + * destinations to the header table. */ + + /* Add "To" destinations. */ + convert.pdata = to_array->pdata; + e_composer_header_table_set_destinations_to ( + table, convert.destinations); + g_ptr_array_free (to_array, FALSE); + e_destination_freev (convert.destinations); + + /* Add "Bcc" destinations. */ + convert.pdata = bcc_array->pdata; + e_composer_header_table_set_destinations_bcc ( + table, convert.destinations); + g_ptr_array_free (bcc_array, FALSE); + e_destination_freev (convert.destinations); + + gtk_widget_show (GTK_WIDGET (composer)); +} + +static const gchar * +get_email (EContact *contact, EContactField field_id, gchar **to_free) +{ + gchar *name = NULL, *mail = NULL; + const gchar *value = e_contact_get_const (contact, field_id); + + *to_free = NULL; + + if (eab_parse_qp_email (value, &name, &mail)) { + *to_free = g_strdup_printf ("%s <%s>", name, mail); + value = *to_free; + } + + g_free (name); + g_free (mail); + + return value; +} + +void +eab_send_as_attachment (GList *destinations) +{ + EMsgComposer *composer; + EComposerHeaderTable *table; + CamelMimePart *attachment; + GList *contacts, *iter; + gchar *data; + + if (destinations == NULL) + return; + + composer = e_msg_composer_new (); + table = e_msg_composer_get_header_table (composer); + + attachment = camel_mime_part_new (); + + contacts = g_list_copy (destinations); + for (iter = contacts; iter != NULL; iter = iter->next) + iter->data = e_destination_get_contact (iter->data); + data = eab_contact_list_to_string (contacts); + g_list_free (contacts); + + camel_mime_part_set_content ( + attachment, data, strlen (data), "text/x-vcard"); + + if (destinations->next != NULL) + camel_mime_part_set_description ( + attachment, _("Multiple vCards")); + else { + EContact *contact; + const gchar *file_as; + gchar *description; + + contact = e_destination_get_contact (destinations->data); + file_as = e_contact_get_const (contact, E_CONTACT_FILE_AS); + description = g_strdup_printf (_("vCard for %s"), file_as); + camel_mime_part_set_description (attachment, description); + g_free (description); + } + + camel_mime_part_set_disposition (attachment, "attachment"); + + e_msg_composer_attach (composer, attachment); + camel_object_unref (attachment); + + if (destinations->next != NULL) + e_composer_header_table_set_subject ( + table, _("Contact information")); + else { + EContact *contact; + gchar *tempstr; + const gchar *tempstr2; + gchar *tempfree = NULL; + + contact = e_destination_get_contact (destinations->data); + tempstr2 = e_contact_get_const (contact, E_CONTACT_FILE_AS); + if (!tempstr2 || !*tempstr2) + tempstr2 = e_contact_get_const (contact, E_CONTACT_FULL_NAME); + if (!tempstr2 || !*tempstr2) + tempstr2 = e_contact_get_const (contact, E_CONTACT_ORG); + if (!tempstr2 || !*tempstr2) { + g_free (tempfree); + tempstr2 = get_email (contact, E_CONTACT_EMAIL_1, &tempfree); + } + if (!tempstr2 || !*tempstr2) { + g_free (tempfree); + tempstr2 = get_email (contact, E_CONTACT_EMAIL_2, &tempfree); + } + if (!tempstr2 || !*tempstr2) { + g_free (tempfree); + tempstr2 = get_email (contact, E_CONTACT_EMAIL_3, &tempfree); + } + + if (!tempstr2 || !*tempstr2) + tempstr = g_strdup_printf (_("Contact information")); + else + tempstr = g_strdup_printf (_("Contact information for %s"), tempstr2); + + e_composer_header_table_set_subject (table, tempstr); + + g_free (tempstr); + g_free (tempfree); + } + + gtk_widget_show (GTK_WIDGET (composer)); +} diff --git a/modules/addressbook/eab-composer-util.h b/modules/addressbook/eab-composer-util.h new file mode 100644 index 0000000000..4aec23074d --- /dev/null +++ b/modules/addressbook/eab-composer-util.h @@ -0,0 +1,31 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef EAB_COMPOSER_UTIL_H +#define EAB_COMPOSER_UTIL_H + +#include + +G_BEGIN_DECLS + +void eab_send_as_to (GList *destinations); +void eab_send_as_attachment (GList *destinations); + +G_END_DECLS + +#endif /* EAB_COMPOSER_UTIL_H */ diff --git a/modules/addressbook/evolution-module-addressbook.c b/modules/addressbook/evolution-module-addressbook.c new file mode 100644 index 0000000000..3089133e43 --- /dev/null +++ b/modules/addressbook/evolution-module-addressbook.c @@ -0,0 +1,45 @@ +/* + * evolution-module-addressbook.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-book-shell-backend.h" +#include "e-book-shell-content.h" +#include "e-book-shell-sidebar.h" +#include "e-book-shell-view.h" + +/* Module Entry Points */ +void e_module_load (GTypeModule *type_module); +void e_module_unload (GTypeModule *type_module); + +G_MODULE_EXPORT void +e_module_load (GTypeModule *type_module) +{ + /* Register dynamically loaded types. */ + + e_book_shell_backend_register_type (type_module); + e_book_shell_content_register_type (type_module); + e_book_shell_sidebar_register_type (type_module); + e_book_shell_view_register_type (type_module); +} + +G_MODULE_EXPORT void +e_module_unload (GTypeModule *type_module) +{ +} diff --git a/modules/addressbook/ldap-config.glade b/modules/addressbook/ldap-config.glade new file mode 100644 index 0000000000..f87cf84b14 --- /dev/null +++ b/modules/addressbook/ldap-config.glade @@ -0,0 +1,1454 @@ + + + + + + + True + Address Book Properties + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + False + False + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + True + -6 + + + + + + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + True + -5 + + + + + 0 + False + True + GTK_PACK_END + + + + + + 12 + True + True + True + True + GTK_POS_TOP + False + False + + + + 12 + True + False + 12 + + + + True + Display + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 6 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + _Name: + True + False + GTK_JUSTIFY_CENTER + False + False + 0 + 0.5 + 0 + 0 + account-editor-display-name-entry + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + This is the name for this server that will appear in your Evolution folder list. It is for display purposes only. + True + True + True + 0 + + True + * + False + + + 0 + True + True + + + + + 0 + False + False + + + + + + False + 12 + + + + True + Server Information + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 12 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + 3 + 2 + False + 6 + 6 + + + + True + _Port: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + _Server: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + server-name-entry + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + False + 6 + + + + True + _Use secure connection: + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + ssl-combobox + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + SSL encryption +TLS encryption +No encryption + False + True + + + 0 + True + True + + + + + 0 + 2 + 2 + 3 + expand|shrink|fill + shrink|fill + + + + + + True + This is the full name of your LDAP server. For example, "ldap.mycompany.com". + True + True + True + True + 0 + + True + * + False + + + 1 + 2 + 0 + 1 + + + + + + + True + 389 +636 +3268 + False + True + True + + + 1 + 2 + 1 + 2 + fill + fill + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + <b>Authentication</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 12 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + 2 + 2 + False + 6 + 6 + + + + True + _Login method: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Lo_gin: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + auth-entry + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + Evolution will use this email address to authenticate you with the server. + True + True + True + 0 + + True + * + False + + + 1 + 2 + 1 + 2 + + + + + + + True + Anonymously +Using email address +Using distinguished name (DN) + False + True + + + 1 + 2 + 0 + 1 + shrink|fill + shrink|fill + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + False + False + + + + + False + False + + + + + + True + General + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + 12 + False + 12 + + + + True + <b>Searching</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 12 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + 4 + 3 + False + 6 + 6 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + Search _base: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + rootdn-entry + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + expand|shrink|fill + shrink|fill + + + + + + True + _Search scope: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + expand|shrink|fill + shrink|fill + + + + + + True + The search base is the distinguished name (DN) of the entry where your searches will begin. If you leave this blank, the search will begin at the root of the directory tree. + True + True + True + True + 0 + + True + * + False + + + 1 + 3 + 0 + 1 + expand|shrink|fill + shrink|fill + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-find + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + _Find Possible Search Bases + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 1 + 2 + 1 + 2 + expand|shrink|fill + shrink|fill + + + + + + True + Search _filter: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + search-filter-entry + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 3 + 4 + expand|shrink|fill + shrink|fill + + + + + + True + True + True + True + 0 + + True + * + False + + Search Filter + Search filter is the type of object to be searched for. If this is not modified, the default search will be performed on the type "person". + + + + 1 + 3 + 3 + 4 + expand|shrink|fill + shrink|fill + + + + + + True + One +Sub + False + True + + + 1 + 3 + 2 + 3 + shrink|fill + shrink|fill + + + + + 0 + True + True + + + + + 0 + False + False + + + + + + True + <b>Downloading</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 12 + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + 3 + 3 + False + 6 + 6 + + + + True + False + 6 + + + + True + 1 + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + False + GTK_POS_TOP + 1 + GTK_UPDATE_CONTINUOUS + False + 3 1 5 0.5 1 0 + + + 0 + True + True + + + + + + True + 5 + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 1 + 2 + 0 + 1 + expand|shrink|fill + shrink|fill + + + + + + True + minutes + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 0 + 1 + shrink|fill + shrink|fill + + + + + + True + cards + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 1 + 2 + shrink|fill + shrink|fill + + + + + + True + _Timeout: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + timeout-scale + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + shrink|fill + shrink|fill + + + + + + True + _Download limit: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + download-limit-spinbutton + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + shrink|fill + shrink|fill + + + + + + True + This is the maximum number of entries to download. Setting this number to be too large will slow down your address book. + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 1000 1 10 0 + + + 1 + 2 + 1 + 2 + expand|shrink|fill + shrink|fill + + + + + + True + True + B_rowse this book until limit reached + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 3 + 2 + 3 + fill + + + + + + 0 + True + True + + + + + 0 + False + False + + + + + False + False + + + + + + True + Details + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + + + + Supported Search Bases + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + 320 + 200 + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + False + False + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + True + -6 + + + + + + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + True + -5 + + + + + 0 + False + True + GTK_PACK_END + + + + + + 12 + True + False + 0 + + + + True + supported_bases_create_table + 0 + 0 + Fri, 12 Apr 2002 20:06:45 GMT + + + 0 + True + True + + + + + 0 + True + True + + + + + + + diff --git a/modules/addressbook/openldap-extract.h b/modules/addressbook/openldap-extract.h new file mode 100644 index 0000000000..996bf370a8 --- /dev/null +++ b/modules/addressbook/openldap-extract.h @@ -0,0 +1,1427 @@ +/* This is extracted from the OpenLDAP sources. + * + * Stuff that isn't used in e-book-backend-ldap.c was dropped, like + * the LDAPSchemaExtensionItem stuff. + * + * This file basically has three parts: + * + * - some general macros from OpenLDAP that work as such on all + * implementations. + * + * - ldap_str2objectclass() + * + * - ldap_url_parse() + */ + +/* This work is part of OpenLDAP Software . + * + * Copyright 1998-2005 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file COPYING.OPENLDAP in + * the top-level directory of the distribution or, alternatively, at + * . + */ + +#include +#include + +/* from various header files */ + +#define LDAP_CONST const + +#define LDAP_PORT 389 /* ldap:/// default LDAP port */ +#define LDAPS_PORT 636 /* ldaps:/// default LDAP over TLS port */ + +#define LDAP_ROOT_DSE "" + +#define LDAP_SPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') +#define LDAP_DIGIT(c) ((c) >= '0' && (c) <= '9') + +#define LDAP_EXOP_START_TLS "1.3.6.1.4.1.1466.20037" /* RFC 2830 */ + +#define LDAP_MALLOC(n) malloc((n)) +#define LDAP_CALLOC(n,s) calloc((n),(s)) +#define LDAP_REALLOC(p,s) realloc((p),(s)) +#define LDAP_FREE(p) free((p)) +#define LDAP_VFREE(p) vfree((gpointer *)(p)) +#define LDAP_STRDUP(s) strdup((s)) + +#define LDAP_RANGE(n,x,y) (((x) <= (n)) && ((n) <= (y))) +#define LDAP_NAME_ERROR(n) LDAP_RANGE((n),0x20,0x24) /* 32-34,36 */ + +#define ldap_msgtype(lm) (lm)->lm_msgtype +#define ldap_msgid(lm) (lm)->lm_msgid + +#define LDAP_SCHERR_OUTOFMEM 1 +#define LDAP_SCHERR_UNEXPTOKEN 2 +#define LDAP_SCHERR_NOLEFTPAREN 3 +#define LDAP_SCHERR_NORIGHTPAREN 4 +#define LDAP_SCHERR_NODIGIT 5 +#define LDAP_SCHERR_BADNAME 6 +#define LDAP_SCHERR_BADDESC 7 +#define LDAP_SCHERR_BADSUP 8 +#define LDAP_SCHERR_DUPOPT 9 +#define LDAP_SCHERR_EMPTY 10 +#define LDAP_SCHERR_MISSING 11 +#define LDAP_SCHERR_OUT_OF_ORDER 12 + +#define LDAP_SCHEMA_YES 1 + +#define LDAP_SCHEMA_ABSTRACT 0 +#define LDAP_SCHEMA_STRUCTURAL 1 +#define LDAP_SCHEMA_AUXILIARY 2 + +#define LDAP_SCHEMA_ALLOW_NONE 0x00U /* Strict parsing */ +#define LDAP_SCHEMA_ALLOW_NO_OID 0x01U /* Allow missing oid */ +#define LDAP_SCHEMA_ALLOW_QUOTED 0x02U /* Allow bogus extra quotes */ +#define LDAP_SCHEMA_ALLOW_DESCR 0x04U /* Allow descr instead of OID */ +#define LDAP_SCHEMA_ALLOW_DESCR_PREFIX 0x08U /* Allow descr as OID prefix */ +#define LDAP_SCHEMA_ALLOW_OID_MACRO 0x10U /* Allow OID macros in slapd */ +#define LDAP_SCHEMA_ALLOW_OUT_OF_ORDER_FIELDS 0x20U /* Allow fields in most any order */ +#define LDAP_SCHEMA_ALLOW_ALL 0x3fU /* Be very liberal in parsing */ +#define LDAP_SCHEMA_SKIP 0x80U /* Don't malloc any result */ + +typedef struct ldap_objectclass { + gchar *oc_oid; /* REQUIRED */ + gchar **oc_names; /* OPTIONAL */ + gchar *oc_desc; /* OPTIONAL */ + gint oc_obsolete; /* 0=no, 1=yes */ + gchar **oc_sup_oids; /* OPTIONAL */ + gint oc_kind; /* 0=ABSTRACT, 1=STRUCTURAL, 2=AUXILIARY */ + gchar **oc_at_oids_must; /* OPTIONAL */ + gchar **oc_at_oids_may; /* OPTIONAL */ +} LDAPObjectClass; + + +static void +vfree(gpointer *vec) +{ + gint i; + + for (i = 0; vec[i] != NULL; i++) + free(vec[i]); +} + +/* from schema.c */ + +/* + * Now come the parsers. There is one parser for each entity type: + * objectclasses, attributetypes, etc. + * + * Each of them is written as a recursive-descent parser, except that + * none of them is really recursive. But the idea is kept: there + * is one routine per non-terminal that eithers gobbles lexical tokens + * or calls lower-level routines, etc. + * + * The scanner is implemented in the routine get_token. Actually, + * get_token is more than a scanner and will return tokens that are + * in fact non-terminals in the grammar. So you can see the whole + * approach as the combination of a low-level bottom-up recognizer + * combined with a scanner and a number of top-down parsers. Or just + * consider that the real grammars recognized by the parsers are not + * those of the standards. As a matter of fact, our parsers are more + * liberal than the spec when there is no ambiguity. + * + * The difference is pretty academic (modulo bugs or incorrect + * interpretation of the specs). + */ + +#define TK_NOENDQUOTE -2 +#define TK_OUTOFMEM -1 +#define TK_EOS 0 +#define TK_UNEXPCHAR 1 +#define TK_BAREWORD 2 +#define TK_QDSTRING 3 +#define TK_LEFTPAREN 4 +#define TK_RIGHTPAREN 5 +#define TK_DOLLAR 6 +#define TK_QDESCR TK_QDSTRING + +struct token { + gint type; + gchar *sval; +}; + +static gint +get_token( const gchar ** sp, gchar ** token_val ) +{ + gint kind; + const gchar * p; + const gchar * q; + gchar * res; + + *token_val = NULL; + switch (**sp) { + case '\0': + kind = TK_EOS; + (*sp)++; + break; + case '(': + kind = TK_LEFTPAREN; + (*sp)++; + break; + case ')': + kind = TK_RIGHTPAREN; + (*sp)++; + break; + case '$': + kind = TK_DOLLAR; + (*sp)++; + break; + case '\'': + kind = TK_QDSTRING; + (*sp)++; + p = *sp; + while ( **sp != '\'' && **sp != '\0' ) + (*sp)++; + if ( **sp == '\'' ) { + q = *sp; + res = LDAP_MALLOC(q-p+1); + if ( !res ) { + kind = TK_OUTOFMEM; + } else { + strncpy(res,p,q-p); + res[q-p] = '\0'; + *token_val = res; + } + (*sp)++; + } else { + kind = TK_NOENDQUOTE; + } + break; + default: + kind = TK_BAREWORD; + p = *sp; + while ( !LDAP_SPACE(**sp) && + **sp != '(' && + **sp != ')' && + **sp != '$' && + **sp != '\'' && + **sp != '\0' ) + (*sp)++; + q = *sp; + res = LDAP_MALLOC(q-p+1); + if ( !res ) { + kind = TK_OUTOFMEM; + } else { + strncpy(res,p,q-p); + res[q-p] = '\0'; + *token_val = res; + } + break; +/* kind = TK_UNEXPCHAR; */ +/* break; */ + } + + return kind; +} + +/* Gobble optional whitespace */ +static void +parse_whsp(const gchar **sp) +{ + while (LDAP_SPACE(**sp)) + (*sp)++; +} + +/* Parse a sequence of dot-separated decimal strings */ +static gchar * +ldap_int_parse_numericoid(const gchar **sp, gint *code, const gint flags) +{ + gchar * res = NULL; + const gchar * start = *sp; + gint len; + gint quoted = 0; + + /* Netscape puts the SYNTAX value in quotes (incorrectly) */ + if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && **sp == '\'' ) { + quoted = 1; + (*sp)++; + start++; + } + /* Each iteration of this loop gets one decimal string */ + while (**sp) { + if ( !LDAP_DIGIT(**sp) ) { + /* + * Initial gchar is not a digit or gchar after dot is + * not a digit + */ + *code = LDAP_SCHERR_NODIGIT; + return NULL; + } + (*sp)++; + while ( LDAP_DIGIT(**sp) ) + (*sp)++; + if ( **sp != '.' ) + break; + /* Otherwise, gobble the dot and loop again */ + (*sp)++; + } + /* Now *sp points at the gchar past the numericoid. Perfect. */ + len = *sp - start; + if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && quoted ) { + if ( **sp == '\'' ) { + (*sp)++; + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + return NULL; + } + } + if (flags & LDAP_SCHEMA_SKIP) { + res = (gchar *)start; + } else { + res = LDAP_MALLOC(len+1); + if (!res) { + *code = LDAP_SCHERR_OUTOFMEM; + return(NULL); + } + strncpy(res,start,len); + res[len] = '\0'; + } + return(res); +} + +/* Parse a qdescr or a list of them enclosed in () */ +static gchar ** +parse_qdescrs(const gchar **sp, gint *code) +{ + gchar ** res; + gchar ** res1; + gint kind; + gchar * sval; + gint size; + gint pos; + + parse_whsp(sp); + kind = get_token(sp,&sval); + if ( kind == TK_LEFTPAREN ) { + /* Let's presume there will be at least 2 entries */ + size = 3; + res = LDAP_CALLOC(3,sizeof(gchar *)); + if ( !res ) { + *code = LDAP_SCHERR_OUTOFMEM; + return NULL; + } + pos = 0; + while (1) { + parse_whsp(sp); + kind = get_token(sp,&sval); + if ( kind == TK_RIGHTPAREN ) + break; + if ( kind == TK_QDESCR ) { + if ( pos == size-2 ) { + size++; + res1 = LDAP_REALLOC(res,size*sizeof(gchar *)); + if ( !res1 ) { + LDAP_VFREE(res); + LDAP_FREE(sval); + *code = LDAP_SCHERR_OUTOFMEM; + return(NULL); + } + res = res1; + } + res[pos++] = sval; + res[pos] = NULL; + parse_whsp(sp); + } else { + LDAP_VFREE(res); + LDAP_FREE(sval); + *code = LDAP_SCHERR_UNEXPTOKEN; + return(NULL); + } + } + parse_whsp(sp); + return(res); + } else if ( kind == TK_QDESCR ) { + res = LDAP_CALLOC(2,sizeof(gchar *)); + if ( !res ) { + *code = LDAP_SCHERR_OUTOFMEM; + return NULL; + } + res[0] = sval; + res[1] = NULL; + parse_whsp(sp); + return res; + } else { + LDAP_FREE(sval); + *code = LDAP_SCHERR_BADNAME; + return NULL; + } +} + +/* Parse a woid or a $-separated list of them enclosed in () */ +static gchar ** +parse_oids(const gchar **sp, gint *code, const gint allow_quoted) +{ + gchar ** res; + gchar ** res1; + gint kind; + gchar * sval; + gint size; + gint pos; + + /* + * Strictly speaking, doing this here accepts whsp before the + * ( at the begining of an oidlist, but this is harmless. Also, + * we are very liberal in what we accept as an OID. Maybe + * refine later. + */ + parse_whsp(sp); + kind = get_token(sp,&sval); + if ( kind == TK_LEFTPAREN ) { + /* Let's presume there will be at least 2 entries */ + size = 3; + res = LDAP_CALLOC(3,sizeof(gchar *)); + if ( !res ) { + *code = LDAP_SCHERR_OUTOFMEM; + return NULL; + } + pos = 0; + parse_whsp(sp); + kind = get_token(sp,&sval); + if ( kind == TK_BAREWORD || + ( allow_quoted && kind == TK_QDSTRING ) ) { + res[pos++] = sval; + res[pos] = NULL; + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + LDAP_FREE(sval); + LDAP_VFREE(res); + return NULL; + } + parse_whsp(sp); + while (1) { + kind = get_token(sp,&sval); + if ( kind == TK_RIGHTPAREN ) + break; + if ( kind == TK_DOLLAR ) { + parse_whsp(sp); + kind = get_token(sp,&sval); + if ( kind == TK_BAREWORD || + ( allow_quoted && + kind == TK_QDSTRING ) ) { + if ( pos == size-2 ) { + size++; + res1 = LDAP_REALLOC(res,size*sizeof(gchar *)); + if ( !res1 ) { + LDAP_FREE(sval); + LDAP_VFREE(res); + *code = LDAP_SCHERR_OUTOFMEM; + return(NULL); + } + res = res1; + } + res[pos++] = sval; + res[pos] = NULL; + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + LDAP_FREE(sval); + LDAP_VFREE(res); + return NULL; + } + parse_whsp(sp); + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + LDAP_FREE(sval); + LDAP_VFREE(res); + return NULL; + } + } + parse_whsp(sp); + return(res); + } else if ( kind == TK_BAREWORD || + ( allow_quoted && kind == TK_QDSTRING ) ) { + res = LDAP_CALLOC(2,sizeof(gchar *)); + if ( !res ) { + LDAP_FREE(sval); + *code = LDAP_SCHERR_OUTOFMEM; + return NULL; + } + res[0] = sval; + res[1] = NULL; + parse_whsp(sp); + return res; + } else { + LDAP_FREE(sval); + *code = LDAP_SCHERR_BADNAME; + return NULL; + } +} + +static void +ldap_objectclass_free(LDAPObjectClass * oc) +{ + LDAP_FREE(oc->oc_oid); + if (oc->oc_names) LDAP_VFREE(oc->oc_names); + if (oc->oc_desc) LDAP_FREE(oc->oc_desc); + if (oc->oc_sup_oids) LDAP_VFREE(oc->oc_sup_oids); + if (oc->oc_at_oids_must) LDAP_VFREE(oc->oc_at_oids_must); + if (oc->oc_at_oids_may) LDAP_VFREE(oc->oc_at_oids_may); + LDAP_FREE(oc); +} + +static LDAPObjectClass * +ldap_str2objectclass( LDAP_CONST gchar * s, + gint * code, + LDAP_CONST gchar ** errp, + LDAP_CONST unsigned flags ) +{ + gint kind; + const gchar * ss = s; + gchar * sval; + gint seen_name = 0; + gint seen_desc = 0; + gint seen_obsolete = 0; + gint seen_sup = 0; + gint seen_kind = 0; + gint seen_must = 0; + gint seen_may = 0; + LDAPObjectClass * oc; + gchar ** ext_vals; + const gchar * savepos; + + if ( !s ) { + *code = LDAP_SCHERR_EMPTY; + *errp = ""; + return NULL; + } + + *errp = s; + oc = LDAP_CALLOC(1,sizeof(LDAPObjectClass)); + + if ( !oc ) { + *code = LDAP_SCHERR_OUTOFMEM; + return NULL; + } + oc->oc_kind = LDAP_SCHEMA_STRUCTURAL; + + kind = get_token(&ss,&sval); + if ( kind != TK_LEFTPAREN ) { + *code = LDAP_SCHERR_NOLEFTPAREN; + LDAP_FREE(sval); + ldap_objectclass_free(oc); + return NULL; + } + + /* + * Definitions MUST begin with an OID in the numericoid format. + * However, this routine is used by clients to parse the response + * from servers and very well known servers will provide an OID + * in the wrong format or even no OID at all. We do our best to + * extract info from those servers. + */ + parse_whsp(&ss); + savepos = ss; + oc->oc_oid = ldap_int_parse_numericoid(&ss,code,0); + if ( !oc->oc_oid ) { + if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) { + /* Backtracking */ + ss = savepos; + kind = get_token(&ss,&sval); + if ( kind == TK_BAREWORD ) { + if ( !strcasecmp(sval, "NAME") || + !strcasecmp(sval, "DESC") || + !strcasecmp(sval, "OBSOLETE") || + !strcasecmp(sval, "SUP") || + !strcasecmp(sval, "ABSTRACT") || + !strcasecmp(sval, "STRUCTURAL") || + !strcasecmp(sval, "AUXILIARY") || + !strcasecmp(sval, "MUST") || + !strcasecmp(sval, "MAY") || + !strncasecmp(sval, "X-", 2) ) { + /* Missing OID, backtrack */ + ss = savepos; + } else if ( flags & + LDAP_SCHEMA_ALLOW_OID_MACRO ) { + /* Non-numerical OID, ignore */ + gint len = ss-savepos; + oc->oc_oid = LDAP_MALLOC(len+1); + strncpy(oc->oc_oid, savepos, len); + oc->oc_oid[len] = 0; + } + } + LDAP_FREE(sval); + } else { + *errp = ss; + ldap_objectclass_free(oc); + return NULL; + } + } + parse_whsp(&ss); + + /* + * Beyond this point we will be liberal an accept the items + * in any order. + */ + while (1) { + kind = get_token(&ss,&sval); + switch (kind) { + case TK_EOS: + *code = LDAP_SCHERR_NORIGHTPAREN; + *errp = ss; + ldap_objectclass_free(oc); + return NULL; + case TK_RIGHTPAREN: + return oc; + case TK_BAREWORD: + if ( !strcasecmp(sval,"NAME") ) { + LDAP_FREE(sval); + if ( seen_name ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_objectclass_free(oc); + return(NULL); + } + seen_name = 1; + oc->oc_names = parse_qdescrs(&ss,code); + if ( !oc->oc_names ) { + if ( *code != LDAP_SCHERR_OUTOFMEM ) + *code = LDAP_SCHERR_BADNAME; + *errp = ss; + ldap_objectclass_free(oc); + return NULL; + } + } else if ( !strcasecmp(sval,"DESC") ) { + LDAP_FREE(sval); + if ( seen_desc ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_objectclass_free(oc); + return(NULL); + } + seen_desc = 1; + parse_whsp(&ss); + kind = get_token(&ss,&sval); + if ( kind != TK_QDSTRING ) { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_objectclass_free(oc); + return NULL; + } + oc->oc_desc = sval; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"OBSOLETE") ) { + LDAP_FREE(sval); + if ( seen_obsolete ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_objectclass_free(oc); + return(NULL); + } + seen_obsolete = 1; + oc->oc_obsolete = LDAP_SCHEMA_YES; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"SUP") ) { + LDAP_FREE(sval); + if ( seen_sup ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_objectclass_free(oc); + return(NULL); + } + seen_sup = 1; + oc->oc_sup_oids = parse_oids(&ss, + code, + flags); + if ( !oc->oc_sup_oids ) { + *errp = ss; + ldap_objectclass_free(oc); + return NULL; + } + } else if ( !strcasecmp(sval,"ABSTRACT") ) { + LDAP_FREE(sval); + if ( seen_kind ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_objectclass_free(oc); + return(NULL); + } + seen_kind = 1; + oc->oc_kind = LDAP_SCHEMA_ABSTRACT; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"STRUCTURAL") ) { + LDAP_FREE(sval); + if ( seen_kind ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_objectclass_free(oc); + return(NULL); + } + seen_kind = 1; + oc->oc_kind = LDAP_SCHEMA_STRUCTURAL; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"AUXILIARY") ) { + LDAP_FREE(sval); + if ( seen_kind ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_objectclass_free(oc); + return(NULL); + } + seen_kind = 1; + oc->oc_kind = LDAP_SCHEMA_AUXILIARY; + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"MUST") ) { + LDAP_FREE(sval); + if ( seen_must ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_objectclass_free(oc); + return(NULL); + } + seen_must = 1; + oc->oc_at_oids_must = parse_oids(&ss,code,0); + if ( !oc->oc_at_oids_must ) { + *errp = ss; + ldap_objectclass_free(oc); + return NULL; + } + parse_whsp(&ss); + } else if ( !strcasecmp(sval,"MAY") ) { + LDAP_FREE(sval); + if ( seen_may ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_objectclass_free(oc); + return(NULL); + } + seen_may = 1; + oc->oc_at_oids_may = parse_oids(&ss,code,0); + if ( !oc->oc_at_oids_may ) { + *errp = ss; + ldap_objectclass_free(oc); + return NULL; + } + parse_whsp(&ss); + } else if ( sval[0] == 'X' && sval[1] == '-' ) { + /* Should be parse_qdstrings */ + ext_vals = parse_qdescrs(&ss, code); + if ( !ext_vals ) { + *errp = ss; + ldap_objectclass_free(oc); + return NULL; + } +#if 0 + if ( add_extension(&oc->oc_extensions, + sval, ext_vals) ) { + *code = LDAP_SCHERR_OUTOFMEM; + *errp = ss; + LDAP_FREE(sval); + ldap_objectclass_free(oc); + return NULL; + } +#endif + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_objectclass_free(oc); + return NULL; + } + break; + default: + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_objectclass_free(oc); + return NULL; + } + } +} + +/* from utf-8.c */ + +#define LDAP_UTF8_NEXT(p) g_utf8_next_char((p)) +#define LDAP_UTF8_INCR(p) ((p)=LDAP_UTF8_NEXT((p))) +#define ldap_x_utf8_to_ucs4(str) g_utf8_get_char(str) + +static gchar *ldap_utf8_strchr( const gchar *str, const gchar *chr ) +{ + for(; *str != '\0'; LDAP_UTF8_INCR(str) ) { + if( ldap_x_utf8_to_ucs4( str ) == ldap_x_utf8_to_ucs4( chr ) ) { + return (gchar *) str; + } + } + + return NULL; +} + +static gsize ldap_utf8_strcspn( const gchar *str, const gchar *set ) +{ + const gchar *cstr; + const gchar *cset; + + for( cstr = str; *cstr != '\0'; LDAP_UTF8_INCR(cstr) ) { + for( cset = set; *cset != '\0'; LDAP_UTF8_INCR(cset) ) { + if( ldap_x_utf8_to_ucs4( cstr ) == ldap_x_utf8_to_ucs4( cset ) ) { + return cstr - str; + } + } + } + + return cstr - str; +} + +static gsize ldap_utf8_strspn( const gchar *str, const gchar *set ) +{ + const gchar *cstr; + const gchar *cset; + + for( cstr = str; *cstr != '\0'; LDAP_UTF8_INCR(cstr) ) { + for( cset = set; ; LDAP_UTF8_INCR(cset) ) { + if( *cset == '\0' ) { + return cstr - str; + } + + if( ldap_x_utf8_to_ucs4( cstr ) == ldap_x_utf8_to_ucs4( cset ) ) { + break; + } + } + } + + return cstr - str; +} + +static gchar *ldap_utf8_strtok(gchar *str, const gchar *sep, gchar **last) +{ + gchar *begin; + gchar *end; + + if( last == NULL ) return NULL; + + begin = str ? str : *last; + + begin += ldap_utf8_strspn( begin, sep ); + + if( *begin == '\0' ) { + *last = NULL; + return NULL; + } + + end = &begin[ ldap_utf8_strcspn( begin, sep ) ]; + + if( *end != '\0' ) { + gchar *next = LDAP_UTF8_NEXT( end ); + *end = '\0'; + end = next; + } + + *last = end; + return begin; +} + +/* from ldap.h */ + +#define LDAP_URL_SUCCESS 0x00 /* Success */ +#define LDAP_URL_ERR_MEM 0x01 /* can't allocate memory space */ +#define LDAP_URL_ERR_PARAM 0x02 /* parameter is bad */ + +#define LDAP_URL_ERR_BADSCHEME 0x03 /* URL doesn't begin with "ldap[si]://" */ +#define LDAP_URL_ERR_BADENCLOSURE 0x04 /* URL is missing trailing ">" */ +#define LDAP_URL_ERR_BADURL 0x05 /* URL is bad */ +#define LDAP_URL_ERR_BADHOST 0x06 /* host port is bad */ +#define LDAP_URL_ERR_BADATTRS 0x07 /* bad (or missing) attributes */ +#define LDAP_URL_ERR_BADSCOPE 0x08 /* scope string is invalid (or missing) */ +#define LDAP_URL_ERR_BADFILTER 0x09 /* bad or missing filter */ +#define LDAP_URL_ERR_BADEXTS 0x0a /* bad or missing extensions */ + +#define LDAP_URL_PREFIX "ldap://" +#define LDAP_URL_PREFIX_LEN (sizeof(LDAP_URL_PREFIX)-1) +#define LDAPS_URL_PREFIX "ldaps://" +#define LDAPS_URL_PREFIX_LEN (sizeof(LDAPS_URL_PREFIX)-1) +#define LDAPI_URL_PREFIX "ldapi://" +#define LDAPI_URL_PREFIX_LEN (sizeof(LDAPI_URL_PREFIX)-1) + +#define LDAP_URL_URLCOLON "URL:" +#define LDAP_URL_URLCOLON_LEN (sizeof(LDAP_URL_URLCOLON)-1) + +typedef struct ldap_url_desc { + struct ldap_url_desc *lud_next; + gchar *lud_scheme; + gchar *lud_host; + gint lud_port; + gchar *lud_dn; + gchar **lud_attrs; + gint lud_scope; + gchar *lud_filter; + gchar **lud_exts; + gint lud_crit_exts; +} LDAPURLDesc; + +/* from url.c */ + +static const gchar * +skip_url_prefix( + const gchar *url, + gint *enclosedp, + const gchar **scheme ) +{ + /* + * return non-zero if this looks like a LDAP URL; zero if not + * if non-zero returned, *urlp will be moved past "ldap://" part of URL + */ + const gchar *p; + + if ( url == NULL ) { + return( NULL ); + } + + p = url; + + /* skip leading '<' (if any) */ + if ( *p == '<' ) { + *enclosedp = 1; + ++p; + } else { + *enclosedp = 0; + } + + /* skip leading "URL:" (if any) */ + if ( strncasecmp( p, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) { + p += LDAP_URL_URLCOLON_LEN; + } + + /* check for "ldap://" prefix */ + if ( strncasecmp( p, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) == 0 ) { + /* skip over "ldap://" prefix and return success */ + p += LDAP_URL_PREFIX_LEN; + *scheme = "ldap"; + return( p ); + } + + /* check for "ldaps://" prefix */ + if ( strncasecmp( p, LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) { + /* skip over "ldaps://" prefix and return success */ + p += LDAPS_URL_PREFIX_LEN; + *scheme = "ldaps"; + return( p ); + } + + /* check for "ldapi://" prefix */ + if ( strncasecmp( p, LDAPI_URL_PREFIX, LDAPI_URL_PREFIX_LEN ) == 0 ) { + /* skip over "ldapi://" prefix and return success */ + p += LDAPI_URL_PREFIX_LEN; + *scheme = "ldapi"; + return( p ); + } + +#ifdef LDAP_CONNECTIONLESS + /* check for "cldap://" prefix */ + if ( strncasecmp( p, LDAPC_URL_PREFIX, LDAPC_URL_PREFIX_LEN ) == 0 ) { + /* skip over "cldap://" prefix and return success */ + p += LDAPC_URL_PREFIX_LEN; + *scheme = "cldap"; + return( p ); + } +#endif + + return( NULL ); +} + +static gint str2scope( const gchar *p ) +{ + if ( strcasecmp( p, "one" ) == 0 ) { + return LDAP_SCOPE_ONELEVEL; + + } else if ( strcasecmp( p, "onelevel" ) == 0 ) { + return LDAP_SCOPE_ONELEVEL; + + } else if ( strcasecmp( p, "base" ) == 0 ) { + return LDAP_SCOPE_BASE; + + } else if ( strcasecmp( p, "sub" ) == 0 ) { + return LDAP_SCOPE_SUBTREE; + + } else if ( strcasecmp( p, "subtree" ) == 0 ) { + return LDAP_SCOPE_SUBTREE; + } + + return( -1 ); +} + +static void +ldap_free_urldesc( LDAPURLDesc *ludp ) +{ + if ( ludp == NULL ) { + return; + } + + if ( ludp->lud_scheme != NULL ) { + LDAP_FREE( ludp->lud_scheme ); + } + + if ( ludp->lud_host != NULL ) { + LDAP_FREE( ludp->lud_host ); + } + + if ( ludp->lud_dn != NULL ) { + LDAP_FREE( ludp->lud_dn ); + } + + if ( ludp->lud_filter != NULL ) { + LDAP_FREE( ludp->lud_filter); + } + + if ( ludp->lud_attrs != NULL ) { + LDAP_VFREE( ludp->lud_attrs ); + } + + if ( ludp->lud_exts != NULL ) { + LDAP_VFREE( ludp->lud_exts ); + } + + LDAP_FREE( ludp ); +} + +static gint +ldap_int_unhex( gint c ) +{ + return( c >= '0' && c <= '9' ? c - '0' + : c >= 'A' && c <= 'F' ? c - 'A' + 10 + : c - 'a' + 10 ); +} + +static void +ldap_pvt_hex_unescape( gchar *s ) +{ + /* + * Remove URL hex escapes from s... done in place. The basic concept for + * this routine is borrowed from the WWW library HTUnEscape() routine. + */ + gchar *p; + + for ( p = s; *s != '\0'; ++s ) { + if ( *s == '%' ) { + if ( *++s == '\0' ) { + break; + } + *p = ldap_int_unhex( *s ) << 4; + if ( *++s == '\0' ) { + break; + } + *p++ += ldap_int_unhex( *s ); + } else { + *p++ = *s; + } + } + + *p = '\0'; +} + +static gchar ** +ldap_str2charray( const gchar *str_in, const gchar *brkstr ) +{ + gchar **res; + gchar *str, *s; + gchar *lasts; + gint i; + + /* protect the input string from strtok */ + str = LDAP_STRDUP( str_in ); + if( str == NULL ) { + return NULL; + } + + i = 1; + for ( s = str; *s; s++ ) { + if ( ldap_utf8_strchr( brkstr, s ) != NULL ) { + i++; + } + } + + res = (gchar **) LDAP_MALLOC( (i + 1) * sizeof(gchar *) ); + + if( res == NULL ) { + LDAP_FREE( str ); + return NULL; + } + + i = 0; + + for ( s = ldap_utf8_strtok( str, brkstr, &lasts ); + s != NULL; + s = ldap_utf8_strtok( NULL, brkstr, &lasts ) ) + { + res[i] = LDAP_STRDUP( s ); + + if(res[i] == NULL) { + for( --i; i >= 0; i-- ) { + LDAP_FREE( res[i] ); + } + LDAP_FREE( res ); + LDAP_FREE( str ); + return NULL; + } + + i++; + } + + res[i] = NULL; + + LDAP_FREE( str ); + return( res ); +} + +static gint +ldap_url_parse_ext( LDAP_CONST gchar *url_in, LDAPURLDesc **ludpp ) +{ +/* + * Pick apart the pieces of an LDAP URL. + */ + + LDAPURLDesc *ludp; + gchar *p, *q, *r; + gint i, enclosed; + const gchar *scheme = NULL; + const gchar *url_tmp; + gchar *url; + + if( url_in == NULL || ludpp == NULL ) { + return LDAP_URL_ERR_PARAM; + } + + *ludpp = NULL; /* pessimistic */ + + url_tmp = skip_url_prefix( url_in, &enclosed, &scheme ); + + if ( url_tmp == NULL ) { + return LDAP_URL_ERR_BADSCHEME; + } + + assert( scheme ); + + /* make working copy of the remainder of the URL */ + url = LDAP_STRDUP( url_tmp ); + if ( url == NULL ) { + return LDAP_URL_ERR_MEM; + } + + if ( enclosed ) { + p = &url[strlen(url)-1]; + + if( *p != '>' ) { + LDAP_FREE( url ); + return LDAP_URL_ERR_BADENCLOSURE; + } + + *p = '\0'; + } + + /* allocate return struct */ + ludp = (LDAPURLDesc *)LDAP_CALLOC( 1, sizeof( LDAPURLDesc )); + + if ( ludp == NULL ) { + LDAP_FREE( url ); + return LDAP_URL_ERR_MEM; + } + + ludp->lud_next = NULL; + ludp->lud_host = NULL; + ludp->lud_port = 0; + ludp->lud_dn = NULL; + ludp->lud_attrs = NULL; + ludp->lud_filter = NULL; + ludp->lud_scope = LDAP_SCOPE_DEFAULT; + ludp->lud_filter = NULL; + ludp->lud_exts = NULL; + + ludp->lud_scheme = LDAP_STRDUP( scheme ); + + if ( ludp->lud_scheme == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_MEM; + } + + /* scan forward for '/' that marks end of hostport and begin. of dn */ + p = strchr( url, '/' ); + + if( p != NULL ) { + /* terminate hostport; point to start of dn */ + *p++ = '\0'; + } + + /* IPv6 syntax with [ip address]:port */ + if ( *url == '[' ) { + r = strchr( url, ']' ); + if ( r == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADURL; + } + *r++ = '\0'; + q = strchr( r, ':' ); + } else { + q = strchr( url, ':' ); + } + + if ( q != NULL ) { + gchar *next; + + *q++ = '\0'; + ldap_pvt_hex_unescape( q ); + + if( *q == '\0' ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADURL; + } + + ludp->lud_port = strtol( q, &next, 10 ); + if ( next == NULL || next[0] != '\0' ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADURL; + } + } + + ldap_pvt_hex_unescape( url ); + + /* If [ip address]:port syntax, url is [ip and we skip the [ */ + ludp->lud_host = LDAP_STRDUP( url + ( *url == '[' ) ); + + if( ludp->lud_host == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_MEM; + } + + /* + * Kludge. ldap://111.222.333.444:389??cn=abc,o=company + * + * On early Novell releases, search references/referrals were returned + * in this format, i.e., the dn was kind of in the scope position, + * but the required slash is missing. The whole thing is illegal syntax, + * but we need to account for it. Fortunately it can't be confused with + * anything real. + */ + if( (p == NULL) && (q != NULL) && ((q = strchr( q, '?')) != NULL)) { + q++; + /* ? immediately followed by question */ + if( *q == '?') { + q++; + if( *q != '\0' ) { + /* parse dn part */ + ldap_pvt_hex_unescape( q ); + ludp->lud_dn = LDAP_STRDUP( q ); + } else { + ludp->lud_dn = LDAP_STRDUP( "" ); + } + + if( ludp->lud_dn == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_MEM; + } + } + } + + if( p == NULL ) { + LDAP_FREE( url ); + *ludpp = ludp; + return LDAP_URL_SUCCESS; + } + + /* scan forward for '?' that may marks end of dn */ + q = strchr( p, '?' ); + + if( q != NULL ) { + /* terminate dn part */ + *q++ = '\0'; + } + + if( *p != '\0' ) { + /* parse dn part */ + ldap_pvt_hex_unescape( p ); + ludp->lud_dn = LDAP_STRDUP( p ); + } else { + ludp->lud_dn = LDAP_STRDUP( "" ); + } + + if( ludp->lud_dn == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_MEM; + } + + if( q == NULL ) { + /* no more */ + LDAP_FREE( url ); + *ludpp = ludp; + return LDAP_URL_SUCCESS; + } + + /* scan forward for '?' that may marks end of attributes */ + p = q; + q = strchr( p, '?' ); + + if( q != NULL ) { + /* terminate attributes part */ + *q++ = '\0'; + } + + if( *p != '\0' ) { + /* parse attributes */ + ldap_pvt_hex_unescape( p ); + ludp->lud_attrs = ldap_str2charray( p, "," ); + + if( ludp->lud_attrs == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADATTRS; + } + } + + if ( q == NULL ) { + /* no more */ + LDAP_FREE( url ); + *ludpp = ludp; + return LDAP_URL_SUCCESS; + } + + /* scan forward for '?' that may marks end of scope */ + p = q; + q = strchr( p, '?' ); + + if( q != NULL ) { + /* terminate the scope part */ + *q++ = '\0'; + } + + if( *p != '\0' ) { + /* parse the scope */ + ldap_pvt_hex_unescape( p ); + ludp->lud_scope = str2scope( p ); + + if( ludp->lud_scope == -1 ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADSCOPE; + } + } + + if ( q == NULL ) { + /* no more */ + LDAP_FREE( url ); + *ludpp = ludp; + return LDAP_URL_SUCCESS; + } + + /* scan forward for '?' that may marks end of filter */ + p = q; + q = strchr( p, '?' ); + + if( q != NULL ) { + /* terminate the filter part */ + *q++ = '\0'; + } + + if( *p != '\0' ) { + /* parse the filter */ + ldap_pvt_hex_unescape( p ); + + if( ! *p ) { + /* missing filter */ + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADFILTER; + } + + LDAP_FREE( ludp->lud_filter ); + ludp->lud_filter = LDAP_STRDUP( p ); + + if( ludp->lud_filter == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_MEM; + } + } + + if ( q == NULL ) { + /* no more */ + LDAP_FREE( url ); + *ludpp = ludp; + return LDAP_URL_SUCCESS; + } + + /* scan forward for '?' that may marks end of extensions */ + p = q; + q = strchr( p, '?' ); + + if( q != NULL ) { + /* extra '?' */ + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADURL; + } + + /* parse the extensions */ + ludp->lud_exts = ldap_str2charray( p, "," ); + + if( ludp->lud_exts == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADEXTS; + } + + for( i=0; ludp->lud_exts[i] != NULL; i++ ) { + ldap_pvt_hex_unescape( ludp->lud_exts[i] ); + + if( *ludp->lud_exts[i] == '!' ) { + /* count the number of critical extensions */ + ludp->lud_crit_exts++; + } + } + + if( i == 0 ) { + /* must have 1 or more */ + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADEXTS; + } + + /* no more */ + *ludpp = ludp; + LDAP_FREE( url ); + return LDAP_URL_SUCCESS; +} + +static gint +ldap_url_parse( LDAP_CONST gchar *url_in, LDAPURLDesc **ludpp ) +{ + gint rc = ldap_url_parse_ext( url_in, ludpp ); + + if( rc != LDAP_URL_SUCCESS ) { + return rc; + } + + if ((*ludpp)->lud_scope == LDAP_SCOPE_DEFAULT) { + (*ludpp)->lud_scope = LDAP_SCOPE_BASE; + } + + if ((*ludpp)->lud_host != NULL && *(*ludpp)->lud_host == '\0') { + LDAP_FREE( (*ludpp)->lud_host ); + (*ludpp)->lud_host = NULL; + } + + if ((*ludpp)->lud_port == 0) { + if( strcmp((*ludpp)->lud_scheme, "ldap") == 0 ) { + (*ludpp)->lud_port = LDAP_PORT; +#ifdef LDAP_CONNECTIONLESS + } else if( strcmp((*ludpp)->lud_scheme, "cldap") == 0 ) { + (*ludpp)->lud_port = LDAP_PORT; +#endif + } else if( strcmp((*ludpp)->lud_scheme, "ldaps") == 0 ) { + (*ludpp)->lud_port = LDAPS_PORT; + } + } + + return rc; +} + diff --git a/modules/calendar/Makefile.am b/modules/calendar/Makefile.am new file mode 100644 index 0000000000..9c2d41dc38 --- /dev/null +++ b/modules/calendar/Makefile.am @@ -0,0 +1,81 @@ +INCLUDES = \ + -DG_LOG_DOMAIN=\"calendar-modules\" \ + -I$(top_srcdir) \ + -I$(top_srcdir)/widgets \ + -DEVOLUTION_ETSPECDIR=\""$(etspecdir)"\" \ + $(EVOLUTION_CALENDAR_CFLAGS) + +module_LTLIBRARIES = \ + libevolution-module-calendar.la + +libevolution_module_calendar_la_SOURCES = \ + evolution-module-calendar.c \ + e-cal-shell-backend.c \ + e-cal-shell-backend.h \ + e-cal-shell-content.c \ + e-cal-shell-content.h \ + e-cal-shell-migrate.c \ + e-cal-shell-migrate.h \ + e-cal-shell-settings.c \ + e-cal-shell-settings.h \ + e-cal-shell-sidebar.c \ + e-cal-shell-sidebar.h \ + e-cal-shell-view.c \ + e-cal-shell-view.h \ + e-cal-shell-view-actions.c \ + e-cal-shell-view-actions.h \ + e-cal-shell-view-memopad.c \ + e-cal-shell-view-private.c \ + e-cal-shell-view-private.h \ + e-cal-shell-view-taskpad.c \ + e-memo-shell-backend.c \ + e-memo-shell-backend.h \ + e-memo-shell-content.c \ + e-memo-shell-content.h \ + e-memo-shell-migrate.c \ + e-memo-shell-migrate.h \ + e-memo-shell-sidebar.c \ + e-memo-shell-sidebar.h \ + e-memo-shell-view.c \ + e-memo-shell-view.h \ + e-memo-shell-view-actions.c \ + e-memo-shell-view-actions.h \ + e-memo-shell-view-private.c \ + e-memo-shell-view-private.h \ + e-task-shell-backend.c \ + e-task-shell-backend.h \ + e-task-shell-content.c \ + e-task-shell-content.h \ + e-task-shell-migrate.c \ + e-task-shell-migrate.h \ + e-task-shell-sidebar.c \ + e-task-shell-sidebar.h \ + e-task-shell-view.c \ + e-task-shell-view.h \ + e-task-shell-view-actions.c \ + e-task-shell-view-actions.h \ + e-task-shell-view-private.c \ + e-task-shell-view-private.h + +# Removed from all three +# $(top_builddir)/a11y/calendar/libevolution-calendar-a11y.la + +libevolution_module_calendar_la_LIBADD = \ + $(top_builddir)/shell/libeshell.la \ + $(top_builddir)/calendar/gui/libcal-gui.la \ + $(top_builddir)/calendar/importers/libevolution-calendar-importers.la \ + $(top_builddir)/mail/libevolution-mail.la \ + $(top_builddir)/addressbook/gui/contact-editor/libecontacteditor.la \ + $(top_builddir)/addressbook/gui/contact-list-editor/libecontactlisteditor.la \ + $(top_builddir)/e-util/libeutil.la \ + $(top_builddir)/filter/libfilter.la \ + $(top_builddir)/widgets/menus/libmenus.la \ + $(top_builddir)/widgets/misc/libemiscwidgets.la \ + $(top_builddir)/widgets/table/libetable.la \ + $(CAMEL_LIBS) \ + $(EVOLUTION_CALENDAR_LIBS) + +libevolution_module_calendar_la_LDFLAGS = \ + -module -avoid-version $(NO_UNDEFINED) + +-include $(top_srcdir)/git.mk diff --git a/modules/calendar/e-cal-shell-backend.c b/modules/calendar/e-cal-shell-backend.c new file mode 100644 index 0000000000..675a3d4fa6 --- /dev/null +++ b/modules/calendar/e-cal-shell-backend.c @@ -0,0 +1,666 @@ +/* + * e-cal-shell-backend.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-backend.h" + +#include +#include +#include +#include +#include +#include + +#include "e-util/e-import.h" +#include "shell/e-shell.h" +#include "shell/e-shell-backend.h" +#include "shell/e-shell-window.h" +#include "widgets/misc/e-preferences-window.h" + +#include "calendar/common/authentication.h" +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/comp-util.h" +#include "calendar/gui/e-attachment-handler-calendar.h" +#include "calendar/gui/e-cal-config.h" +#include "calendar/gui/e-cal-event.h" +#include "calendar/gui/dialogs/cal-prefs-dialog.h" +#include "calendar/gui/dialogs/calendar-setup.h" +#include "calendar/gui/dialogs/event-editor.h" +#include "calendar/importers/evolution-calendar-importer.h" + +#include "e-cal-shell-migrate.h" +#include "e-cal-shell-settings.h" +#include "e-cal-shell-view.h" + +#define E_CAL_SHELL_BACKEND_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_CAL_SHELL_BACKEND, ECalShellBackendPrivate)) + +#define CONTACTS_BASE_URI "contacts://" +#define WEATHER_BASE_URI "weather://" +#define WEB_BASE_URI "webcal://" +#define PERSONAL_RELATIVE_URI "system" + +struct _ECalShellBackendPrivate { + ESourceList *source_list; +}; + +enum { + PROP_0, + PROP_SOURCE_LIST +}; + +static gpointer parent_class; +static GType cal_shell_backend_type; + +static void +cal_shell_backend_ensure_sources (EShellBackend *shell_backend) +{ + /* XXX This is basically the same algorithm across all backends. + * Maybe we could somehow integrate this into EShellBackend? */ + + ECalShellBackendPrivate *priv; + ESourceGroup *on_this_computer; + ESourceGroup *on_the_web; + ESourceGroup *contacts; + ESourceGroup *weather; + ESource *birthdays; + ESource *personal; + EShell *shell; + EShellSettings *shell_settings; + GSList *groups, *iter; + const gchar *data_dir; + const gchar *name; + gchar *base_uri; + gchar *filename; + gchar *property; + + on_this_computer = NULL; + on_the_web = NULL; + contacts = NULL; + weather = NULL; + birthdays = NULL; + personal = NULL; + + priv = E_CAL_SHELL_BACKEND_GET_PRIVATE (shell_backend); + + shell = e_shell_backend_get_shell (shell_backend); + shell_settings = e_shell_get_shell_settings (shell); + + if (!e_cal_get_sources (&priv->source_list, E_CAL_SOURCE_TYPE_EVENT, NULL)) { + g_warning ("Could not get calendar sources from GConf!"); + return; + } + + data_dir = e_shell_backend_get_data_dir (shell_backend); + filename = g_build_filename (data_dir, "local", NULL); + base_uri = g_filename_to_uri (filename, NULL, NULL); + g_free (filename); + + groups = e_source_list_peek_groups (priv->source_list); + for (iter = groups; iter != NULL; iter = iter->next) { + ESourceGroup *source_group = iter->data; + const gchar *group_base_uri; + + group_base_uri = e_source_group_peek_base_uri (source_group); + + /* Compare only "file://" part. if the user's home + * changes, we do not want to create another group. */ + if (on_this_computer == NULL && + strncmp (base_uri, group_base_uri, 7) == 0) + on_this_computer = source_group; + + else if (on_the_web == NULL && + strcmp (WEB_BASE_URI, group_base_uri) == 0) + on_the_web = source_group; + + else if (contacts == NULL && + strcmp (CONTACTS_BASE_URI, group_base_uri) == 0) + contacts = source_group; + + else if (weather == NULL && + strcmp (WEATHER_BASE_URI, group_base_uri) == 0) + weather = source_group; + } + + name = _("On This Computer"); + + if (on_this_computer != NULL) { + GSList *sources; + const gchar *group_base_uri; + + /* Force the group name to the current locale. */ + e_source_group_set_name (on_this_computer, name); + + sources = e_source_group_peek_sources (on_this_computer); + group_base_uri = e_source_group_peek_base_uri (on_this_computer); + + /* Make sure this group includes a "Personal" source. */ + for (iter = sources; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + const gchar *relative_uri; + + relative_uri = e_source_peek_relative_uri (source); + if (relative_uri == NULL) + continue; + + if (strcmp (PERSONAL_RELATIVE_URI, relative_uri) != 0) + continue; + + personal = source; + break; + } + + /* Make sure we have the correct base URI. This can + * change when the user's home directory changes. */ + if (strcmp (base_uri, group_base_uri) != 0) { + e_source_group_set_base_uri ( + on_this_computer, base_uri); + + /* XXX We shouldn't need this sync call here as + * set_base_uri() results in synching to GConf, + * but that happens in an idle loop and too late + * to prevent the user from seeing a "Cannot + * Open ... because of invalid URI" error. */ + e_source_list_sync (priv->source_list, NULL); + } + + } else { + ESourceGroup *source_group; + + source_group = e_source_group_new (name, base_uri); + e_source_list_add_group (priv->source_list, source_group, -1); + g_object_unref (source_group); + } + + name = _("Personal"); + + if (personal == NULL) { + ESource *source; + GSList *selected; + gchar *primary; + + source = e_source_new (name, PERSONAL_RELATIVE_URI); + e_source_group_add_source (on_this_computer, source, -1); + g_object_unref (source); + + primary = e_shell_settings_get_string ( + shell_settings, "cal-primary-calendar"); + + selected = calendar_config_get_calendars_selected (); + + if (primary == NULL && selected == NULL) { + const gchar *uid; + + uid = e_source_peek_uid (source); + selected = g_slist_prepend (NULL, g_strdup (uid)); + + e_shell_settings_set_string ( + shell_settings, "cal-primary-calendar", uid); + calendar_config_set_calendars_selected (selected); + } + + g_slist_foreach (selected, (GFunc) g_free, NULL); + g_slist_free (selected); + g_free (primary); + } else { + /* Force the source name to the current locale. */ + e_source_set_name (personal, name); + } + + name = _("On The Web"); + + if (on_the_web == NULL) { + ESourceGroup *source_group; + + source_group = e_source_group_new (name, WEB_BASE_URI); + e_source_list_add_group (priv->source_list, source_group, -1); + g_object_unref (source_group); + } else { + /* Force the group name to the current locale. */ + e_source_group_set_name (on_the_web, name); + } + + name = _("Contacts"); + + if (contacts != NULL) { + GSList *sources; + + /* Force the group name to the current locale. */ + e_source_group_set_name (contacts, name); + + sources = e_source_group_peek_sources (contacts); + + if (sources != NULL) { + GSList *trash; + + /* There is only one source under Contacts. */ + birthdays = E_SOURCE (sources->data); + sources = g_slist_next (sources); + + /* Delete any other sources in this group. + * Earlier versions allowed you to create + * additional sources under Contacts. */ + trash = g_slist_copy (sources); + while (trash != NULL) { + ESource *source = trash->data; + e_source_group_remove_source (contacts, source); + trash = g_slist_delete_link (trash, trash); + } + + } + } else { + ESourceGroup *source_group; + + source_group = e_source_group_new (name, CONTACTS_BASE_URI); + e_source_list_add_group (priv->source_list, source_group, -1); + g_object_unref (source_group); + + /* This is now a borrowed reference. */ + contacts = source_group; + } + + /* XXX e_source_group_get_property() returns a newly-allocated + * string when it could just as easily return a const string. + * Unfortunately, fixing that would break the API. */ + property = e_source_group_get_property (contacts, "create_source"); + if (property == NULL) + e_source_group_set_property (contacts, "create_source", "no"); + g_free (property); + + name = _("Birthdays & Anniversaries"); + + if (birthdays == NULL) { + ESource *source; + const gchar *name; + + name = _("Birthdays & Anniversaries"); + source = e_source_new (name, "/"); + e_source_group_add_source (contacts, source, -1); + g_object_unref (source); + + /* This is now a borrowed reference. */ + birthdays = source; + } else { + /* Force the source name to the current locale. */ + e_source_set_name (birthdays, name); + } + + if (e_source_get_property (birthdays, "delete") == NULL) + e_source_set_property (birthdays, "delete", "no"); + + if (e_source_peek_color_spec (birthdays) == NULL) + e_source_set_color_spec (birthdays, "#DDBECE"); + + name = _("Weather"); + + if (weather == NULL) { + ESourceGroup *source_group; + + source_group = e_source_group_new (name, WEATHER_BASE_URI); + e_source_list_add_group (priv->source_list, source_group, -1); + g_object_unref (source_group); + } else { + /* Force the group name to the current locale. */ + e_source_group_set_name (weather, name); + } + + g_free (base_uri); +} + +static void +cal_shell_backend_cal_opened_cb (ECal *cal, + ECalendarStatus status, + GtkAction *action) +{ + EShell *shell; + ECalComponent *comp; + CompEditor *editor; + CompEditorFlags flags = 0; + const gchar *action_name; + gboolean all_day; + + /* FIXME Pass this in. */ + shell = e_shell_get_default (); + + /* XXX Handle errors better. */ + if (status != E_CALENDAR_STATUS_OK) + return; + + action_name = gtk_action_get_name (action); + + flags |= COMP_EDITOR_NEW_ITEM; + flags |= COMP_EDITOR_USER_ORG; + if (strcmp (action_name, "event-meeting-new") == 0) + flags |= COMP_EDITOR_MEETING; + + all_day = (strcmp (action_name, "event-all-day-new") == 0); + + editor = event_editor_new (cal, shell, flags); + comp = cal_comp_event_new_with_current_time (cal, all_day); + comp_editor_edit_comp (editor, comp); + + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (comp); + g_object_unref (cal); +} + +static void +action_event_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + ECal *cal = NULL; + ECalSourceType source_type; + ESourceList *source_list; + EShellSettings *shell_settings; + EShell *shell; + gchar *uid; + + /* This callback is used for both appointments and meetings. */ + + source_type = E_CAL_SOURCE_TYPE_EVENT; + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + if (!e_cal_get_sources (&source_list, source_type, NULL)) { + g_warning ("Could not get calendar sources from GConf!"); + return; + } + + uid = e_shell_settings_get_string ( + shell_settings, "cal-primary-calendar"); + + if (uid != NULL) { + ESource *source; + + source = e_source_list_peek_source_by_uid (source_list, uid); + if (source != NULL) + cal = auth_new_cal_from_source (source, source_type); + g_free (uid); + } + + if (cal == NULL) + cal = auth_new_cal_from_default (source_type); + + g_return_if_fail (cal != NULL); + + g_signal_connect ( + cal, "cal-opened", + G_CALLBACK (cal_shell_backend_cal_opened_cb), action); + + e_cal_open_async (cal, FALSE); +} + +static void +action_calendar_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + calendar_setup_new_calendar (GTK_WINDOW (shell_window)); +} + +static GtkActionEntry item_entries[] = { + + { "event-new", + "appointment-new", + NC_("New", "_Appointment"), + "a", + N_("Create a new appointment"), + G_CALLBACK (action_event_new_cb) }, + + { "event-all-day-new", + "stock_new-24h-appointment", + NC_("New", "All Day A_ppointment"), + NULL, + N_("Create a new all-day appointment"), + G_CALLBACK (action_event_new_cb) }, + + { "event-meeting-new", + "stock_new-meeting", + NC_("New", "M_eeting"), + "e", + N_("Create a new meeting request"), + G_CALLBACK (action_event_new_cb) } +}; + +static GtkActionEntry source_entries[] = { + + { "calendar-new", + "x-office-calendar", + NC_("New", "Cale_ndar"), + NULL, + N_("Create a new calendar"), + G_CALLBACK (action_calendar_new_cb) } +}; + +static void +cal_shell_backend_init_hooks (void) +{ + e_plugin_hook_register_type (e_cal_config_hook_get_type ()); + e_plugin_hook_register_type (e_cal_event_hook_get_type ()); +} + +static void +cal_shell_backend_init_importers (void) +{ + EImportClass *import_class; + EImportImporter *importer; + + import_class = g_type_class_ref (e_import_get_type ()); + + importer = gnome_calendar_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); + + importer = ical_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); + + importer = vcal_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); +} + +static void +cal_shell_backend_init_preferences (EShell *shell) +{ + GtkWidget *preferences_window; + + preferences_window = e_shell_get_preferences_window (shell); + + e_preferences_window_add_page ( + E_PREFERENCES_WINDOW (preferences_window), + "calendar-and-tasks", + "preferences-calendar-and-tasks", + _("Calendar and Tasks"), + calendar_prefs_dialog_new (shell), + 600); +} + +static gboolean +cal_shell_backend_handle_uri_cb (EShellBackend *shell_backend, + const gchar *uri) +{ + /* FIXME */ + return FALSE; +} + +static void +cal_shell_backend_window_created_cb (EShellBackend *shell_backend, + GtkWindow *window) +{ + const gchar *backend_name; + + if (!E_IS_SHELL_WINDOW (window)) + return; + + backend_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name; + + e_shell_window_register_new_item_actions ( + E_SHELL_WINDOW (window), backend_name, + item_entries, G_N_ELEMENTS (item_entries)); + + e_shell_window_register_new_source_actions ( + E_SHELL_WINDOW (window), backend_name, + source_entries, G_N_ELEMENTS (source_entries)); +} + +static void +cal_shell_backend_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SOURCE_LIST: + g_value_set_object ( + value, + e_cal_shell_backend_get_source_list ( + E_CAL_SHELL_BACKEND (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +cal_shell_backend_dispose (GObject *object) +{ + ECalShellBackendPrivate *priv; + + priv = E_CAL_SHELL_BACKEND_GET_PRIVATE (object); + + if (priv->source_list != NULL) { + g_object_unref (priv->source_list); + priv->source_list = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +cal_shell_backend_constructed (GObject *object) +{ + EShell *shell; + EShellBackend *shell_backend; + + shell_backend = E_SHELL_BACKEND (object); + shell = e_shell_backend_get_shell (shell_backend); + + cal_shell_backend_ensure_sources (shell_backend); + + g_signal_connect_swapped ( + shell, "handle-uri", + G_CALLBACK (cal_shell_backend_handle_uri_cb), + shell_backend); + + g_signal_connect_swapped ( + shell, "window-created", + G_CALLBACK (cal_shell_backend_window_created_cb), + shell_backend); + + cal_shell_backend_init_hooks (); + cal_shell_backend_init_importers (); + + /* Initialize settings before initializing preferences, + * since the preferences bind to the shell settings. */ + e_cal_shell_backend_init_settings (shell); + cal_shell_backend_init_preferences (shell); + + e_attachment_handler_calendar_get_type (); +} + +static void +cal_shell_backend_class_init (ECalShellBackendClass *class) +{ + GObjectClass *object_class; + EShellBackendClass *shell_backend_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ECalShellBackendPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->get_property = cal_shell_backend_get_property; + object_class->dispose = cal_shell_backend_dispose; + object_class->constructed = cal_shell_backend_constructed; + + shell_backend_class = E_SHELL_BACKEND_CLASS (class); + shell_backend_class->shell_view_type = E_TYPE_CAL_SHELL_VIEW; + shell_backend_class->name = "calendar"; + shell_backend_class->aliases = ""; + shell_backend_class->schemes = "calendar"; + shell_backend_class->sort_order = 400; + shell_backend_class->start = NULL; + shell_backend_class->is_busy = NULL; + shell_backend_class->shutdown = NULL; + shell_backend_class->migrate = e_cal_shell_backend_migrate; + + g_object_class_install_property ( + object_class, + PROP_SOURCE_LIST, + g_param_spec_object ( + "source-list", + _("Source List"), + _("The registry of calendars"), + E_TYPE_SOURCE_LIST, + G_PARAM_READABLE)); +} + +static void +cal_shell_backend_init (ECalShellBackend *cal_shell_backend) +{ + cal_shell_backend->priv = + E_CAL_SHELL_BACKEND_GET_PRIVATE (cal_shell_backend); +} + +GType +e_cal_shell_backend_get_type (void) +{ + return cal_shell_backend_type; +} + +void +e_cal_shell_backend_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (ECalShellBackendClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) cal_shell_backend_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ECalShellBackend), + 0, /* n_preallocs */ + (GInstanceInitFunc) cal_shell_backend_init, + NULL /* value_table */ + }; + + cal_shell_backend_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_BACKEND, + "ECalShellBackend", &type_info, 0); +} + +ESourceList * +e_cal_shell_backend_get_source_list (ECalShellBackend *cal_shell_backend) +{ + g_return_val_if_fail ( + E_IS_CAL_SHELL_BACKEND (cal_shell_backend), NULL); + + return cal_shell_backend->priv->source_list; +} diff --git a/modules/calendar/e-cal-shell-backend.h b/modules/calendar/e-cal-shell-backend.h new file mode 100644 index 0000000000..497e200490 --- /dev/null +++ b/modules/calendar/e-cal-shell-backend.h @@ -0,0 +1,70 @@ +/* + * e-cal-shell-backend.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_SHELL_BACKEND_H +#define E_CAL_SHELL_BACKEND_H + +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_CAL_SHELL_BACKEND \ + (e_cal_shell_backend_get_type ()) +#define E_CAL_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_CAL_SHELL_BACKEND, ECalShellBackend)) +#define E_CAL_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_CAL_SHELL_BACKEND, ECalShellBackendClass)) +#define E_IS_CAL_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_CAL_SHELL_BACKEND)) +#define E_IS_CAL_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_CAL_SHELL_BACKEND)) +#define E_CAL_SHELL_BACKEND_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_CAL_SHELL_BACKEND, ECalShellBackendClass)) + +G_BEGIN_DECLS + +typedef struct _ECalShellBackend ECalShellBackend; +typedef struct _ECalShellBackendClass ECalShellBackendClass; +typedef struct _ECalShellBackendPrivate ECalShellBackendPrivate; + +struct _ECalShellBackend { + EShellBackend parent; + ECalShellBackendPrivate *priv; +}; + +struct _ECalShellBackendClass { + EShellBackendClass parent_class; +}; + +GType e_cal_shell_backend_get_type (void); +void e_cal_shell_backend_register_type + (GTypeModule *type_module); +ESourceList * e_cal_shell_backend_get_source_list + (ECalShellBackend *cal_shell_backend); + +G_END_DECLS + +#endif /* E_CAL_SHELL_BACKEND_H */ diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c new file mode 100644 index 0000000000..6afb40dce7 --- /dev/null +++ b/modules/calendar/e-cal-shell-content.c @@ -0,0 +1,827 @@ +/* + * e-cal-shell-content.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-content.h" + +#include +#include + +#include "e-util/gconf-bridge.h" + +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/e-cal-list-view-config.h" +#include "calendar/gui/e-cal-model-calendar.h" +#include "calendar/gui/e-calendar-table.h" +#include "calendar/gui/e-calendar-table-config.h" +#include "calendar/gui/e-day-view-config.h" +#include "calendar/gui/e-memo-table-config.h" +#include "calendar/gui/e-week-view-config.h" + +#include "widgets/menus/gal-view-etable.h" + +#define E_CAL_SHELL_CONTENT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_CAL_SHELL_CONTENT, ECalShellContentPrivate)) + +struct _ECalShellContentPrivate { + GtkWidget *hpaned; + GtkWidget *notebook; + GtkWidget *vpaned; + + GtkWidget *day_view; + GtkWidget *work_week_view; + GtkWidget *week_view; + GtkWidget *month_view; + GtkWidget *list_view; + GtkWidget *task_table; + GtkWidget *memo_table; + + EDayViewConfig *day_view_config; + EDayViewConfig *work_week_view_config; + EWeekViewConfig *week_view_config; + EWeekViewConfig *month_view_config; + ECalListViewConfig *list_view_config; + ECalendarTableConfig *task_table_config; + EMemoTableConfig *memo_table_config; + + GalViewInstance *view_instance; + + guint paned_binding_id; +}; + +enum { + PROP_0 +}; + +/* Used to indicate who has the focus within the calendar view. */ +typedef enum { + FOCUS_CALENDAR, + FOCUS_MEMO_TABLE, + FOCUS_TASK_TABLE, + FOCUS_OTHER +} FocusLocation; + +static gpointer parent_class; +static GType cal_shell_content_type; + +static void +cal_shell_content_display_view_cb (ECalShellContent *cal_shell_content, + GalView *gal_view) +{ + /* FIXME */ +} + +static void +cal_shell_content_notify_view_id_cb (ECalShellContent *cal_shell_content) +{ + EShellContent *shell_content; + EShellView *shell_view; + GConfBridge *bridge; + GtkWidget *paned; + guint binding_id; + const gchar *key; + const gchar *view_id; + + bridge = gconf_bridge_get (); + paned = cal_shell_content->priv->hpaned; + binding_id = cal_shell_content->priv->paned_binding_id; + + shell_content = E_SHELL_CONTENT (cal_shell_content); + shell_view = e_shell_content_get_shell_view (shell_content); + view_id = e_shell_view_get_view_id (shell_view); + + if (binding_id > 0) + gconf_bridge_unbind (bridge, binding_id); + + if (view_id != NULL && strcmp (view_id, "Month_View") == 0) + key = "/apps/evolution/calendar/display/month_hpane_position"; + else + key = "/apps/evolution/calendar/display/hpane_position"; + + binding_id = gconf_bridge_bind_property_delayed ( + bridge, key, G_OBJECT (paned), "position"); + + cal_shell_content->priv->paned_binding_id = binding_id; +} + +static FocusLocation +cal_shell_content_get_focus_location (ECalShellContent *cal_shell_content) +{ + return FOCUS_OTHER; +#if 0 /* TEMPORARILY DISABLED */ + GtkWidget *widget; + GnomeCalendar *calendar; + ECalendarTable *task_table; + EMemoTable *memo_table; + ETable *table; + ECalendarView *calendar_view; + + calendar = GNOME_CALENDAR (cal_shell_content->priv->calendar); + widget = gnome_calendar_get_current_view_widget (calendar); + + memo_table = E_MEMO_TABLE (cal_shell_content->priv->memo_table); + task_table = E_CALENDAR_TABLE (cal_shell_content->priv->task_table); + + table = e_memo_table_get_table (memo_table); + if (GTK_WIDGET_HAS_FOCUS (table->table_canvas)) + return FOCUS_MEMO_TABLE; + + table = e_calendar_table_get_table (task_table); + if (GTK_WIDGET_HAS_FOCUS (table->table_canvas)) + return FOCUS_TASK_TABLE; + + if (E_IS_DAY_VIEW (widget)) { + EDayView *view = E_DAY_VIEW (widget); + + if (GTK_WIDGET_HAS_FOCUS (view->top_canvas)) + return FOCUS_CALENDAR; + + if (GNOME_CANVAS (view->top_canvas)->focused_item != NULL) + return FOCUS_CALENDAR; + + if (GTK_WIDGET_HAS_FOCUS (view->main_canvas)) + return FOCUS_CALENDAR; + + if (GNOME_CANVAS (view->main_canvas)->focused_item != NULL) + return FOCUS_CALENDAR; + + } else if (E_IS_WEEK_VIEW (widget)) { + EWeekView *view = E_WEEK_VIEW (widget); + + if (GTK_WIDGET_HAS_FOCUS (view->main_canvas)) + return FOCUS_CALENDAR; + + if (GNOME_CANVAS (view->main_canvas)->focused_item != NULL) + return FOCUS_CALENDAR; + + } else if (E_IS_CAL_LIST_VIEW (widget)) { + ECalListView *view = E_CAL_LIST_VIEW (widget); + + table = e_table_scrolled_get_table (view->table_scrolled); + if (GTK_WIDGET_HAS_FOCUS (table)) + return FOCUS_CALENDAR; + } + + return FOCUS_OTHER; +#endif +} + +static void +cal_shell_content_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +cal_shell_content_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +cal_shell_content_dispose (GObject *object) +{ + ECalShellContentPrivate *priv; + + priv = E_CAL_SHELL_CONTENT_GET_PRIVATE (object); + + if (priv->hpaned != NULL) { + g_object_unref (priv->hpaned); + priv->hpaned = NULL; + } + + if (priv->notebook != NULL) { + g_object_unref (priv->notebook); + priv->notebook = NULL; + } + + if (priv->vpaned != NULL) { + g_object_unref (priv->vpaned); + priv->vpaned = NULL; + } + + if (priv->day_view != NULL) { + g_object_unref (priv->day_view); + priv->day_view = NULL; + } + + if (priv->work_week_view != NULL) { + g_object_unref (priv->work_week_view); + priv->work_week_view = NULL; + } + + if (priv->week_view != NULL) { + g_object_unref (priv->week_view); + priv->week_view = NULL; + } + + if (priv->month_view != NULL) { + g_object_unref (priv->month_view); + priv->month_view = NULL; + } + + if (priv->list_view != NULL) { + g_object_unref (priv->list_view); + priv->list_view = NULL; + } + + if (priv->task_table != NULL) { + g_object_unref (priv->task_table); + priv->task_table = NULL; + } + + if (priv->memo_table != NULL) { + g_object_unref (priv->memo_table); + priv->memo_table = NULL; + } + + if (priv->day_view_config != NULL) { + g_object_unref (priv->day_view_config); + priv->day_view_config = NULL; + } + + if (priv->work_week_view_config != NULL) { + g_object_unref (priv->work_week_view_config); + priv->work_week_view_config = NULL; + } + + if (priv->week_view_config != NULL) { + g_object_unref (priv->week_view_config); + priv->week_view_config = NULL; + } + + if (priv->month_view_config != NULL) { + g_object_unref (priv->month_view_config); + priv->month_view_config = NULL; + } + + if (priv->list_view_config != NULL) { + g_object_unref (priv->list_view_config); + priv->list_view_config = NULL; + } + + if (priv->task_table_config != NULL) { + g_object_unref (priv->task_table_config); + priv->task_table_config = NULL; + } + + if (priv->memo_table_config != NULL) { + g_object_unref (priv->memo_table_config); + priv->memo_table_config = NULL; + } + + if (priv->view_instance != NULL) { + g_object_unref (priv->view_instance); + priv->view_instance = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +cal_shell_content_finalize (GObject *object) +{ + ECalShellContentPrivate *priv; + + priv = E_CAL_SHELL_CONTENT_GET_PRIVATE (object); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +cal_shell_content_constructed (GObject *object) +{ + ECalShellContentPrivate *priv; + ECalModelCalendar *cal_model; + ECalModel *memo_model; + ECalModel *task_model; + EShellContent *shell_content; + EShellBackend *shell_backend; + EShellView *shell_view; + EShellWindow *shell_window; + EShellContent *foreign_content; + EShellView *foreign_view; + GalViewInstance *view_instance; + GConfBridge *bridge; + GtkWidget *container; + GtkWidget *widget; + const gchar *config_dir; + const gchar *key; + gchar *filename; + gchar *markup; + gint page_num; + + priv = E_CAL_SHELL_CONTENT_GET_PRIVATE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_content = E_SHELL_CONTENT (object); + shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + + shell_backend = e_shell_view_get_shell_backend (shell_view); + config_dir = e_shell_backend_get_config_dir (shell_backend); + + /* Calendar model for the views. */ + cal_model = e_cal_model_calendar_new (); + e_cal_model_set_flags ( + E_CAL_MODEL (cal_model), + E_CAL_MODEL_FLAGS_EXPAND_RECURRENCES); + + /* We borrow the memopad and taskpad models from the memo + * and task views, loading the views if necessary. */ + + foreign_view = e_shell_window_get_shell_view (shell_window, "memos"); + foreign_content = e_shell_view_get_shell_content (foreign_view); + g_object_get (foreign_content, "model", &memo_model, NULL); + + foreign_view = e_shell_window_get_shell_view (shell_window, "tasks"); + foreign_content = e_shell_view_get_shell_content (foreign_view); + g_object_get (foreign_content, "model", &task_model, NULL); + + /* Build content widgets. */ + + container = GTK_WIDGET (object); + + /* FIXME Need to deal with saving and restoring the position. + * Month view has its own position. */ + widget = gtk_hpaned_new (); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->hpaned = g_object_ref (widget); + gtk_widget_show (widget); + + container = priv->hpaned; + + widget = gtk_notebook_new (); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE); + gtk_notebook_set_show_border (GTK_NOTEBOOK (widget), FALSE); + gtk_paned_pack1 (GTK_PANED (container), widget, FALSE, TRUE); + priv->notebook = g_object_ref (widget); + gtk_widget_show (widget); + + /* FIXME Need to deal with saving and restoring the position. + * Month view has its own position. */ + widget = gtk_vpaned_new (); + gtk_paned_pack2 (GTK_PANED (container), widget, TRUE, TRUE); + priv->vpaned = g_object_ref (widget); + gtk_widget_show (widget); + + container = priv->notebook; + + /* Add views in the order defined by GnomeCalendarViewType, such + * that the notebook page number corresponds to the view type. + * The assertions below ensure that stays true. */ + +#if 0 /* Not so fast... get the memo/task pads working first. */ + /* FIXME Need to establish a calendar and timezone first. */ + widget = e_day_view_new (E_CAL_MODEL (cal_model)); + e_calendar_view_set_calendar ( + E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); + e_calendar_view_set_timezone ( + E_CALENDAR_VIEW (widget), priv->timezone); + page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); + gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); + g_return_if_fail (page_num == GNOME_CAL_DAY_VIEW); + priv->day_view = g_object_ref (widget); + gtk_widget_show (widget); + + /* FIXME Need to establish a calendar and timezone first. */ + widget = e_day_view_new (E_CAL_MODEL (cal_model)); + e_day_view_set_work_week_view (E_DAY_VIEW (widget), TRUE); + e_day_view_set_days_shown (E_DAY_VIEW (widget), 5); + e_calendar_view_set_calendar ( + E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); + e_calendar_view_set_timezone ( + E_CALENDAR_VIEW (widget), priv->timezone); + page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); + gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); + g_return_if_fail (page_num == GNOME_CAL_WORK_WEEK_VIEW); + priv->work_week_view = g_object_ref (widget); + gtk_widget_show (widget); + + /* FIXME Need to establish a calendar and timezone first. */ + widget = e_week_view_new (E_CAL_MODEL (cal_model)); + e_calendar_view_set_calendar ( + E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); + e_calendar_view_set_timezone ( + E_CALENDAR_VIEW (widget), priv->timezone); + page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); + gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); + g_return_if_fail (page_num == GNOME_CAL_WEEK_VIEW); + priv->week_view = g_object_ref (widget); + gtk_widget_show (widget); + + /* FIXME Need to establish a calendar and timezone first. */ + widget = e_week_view_new (E_CAL_MODEL (cal_model)); + e_week_view_set_multi_week_view (E_WEEK_VIEW (widget), TRUE); + e_week_view_set_weeks_shown (E_WEEK_VIEW (widget), 6); + e_calendar_view_set_calendar ( + E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); + e_calendar_view_set_timezone ( + E_CALENDAR_VIEW (widget), priv->timezone); + page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); + gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); + g_return_if_fail (page_num == GNOME_CAL_MONTH_VIEW); + priv->month_view = g_object_ref (widget); + gtk_widget_show (widget); + + /* FIXME Need to establish a calendar and timezone first. */ + widget = e_cal_list_view_new (E_CAL_MODEL (cal_model)); + e_calendar_view_set_calendar ( + E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); + e_calendar_view_set_timezone ( + E_CALENDAR_VIEW (widget), priv->timezone); + page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); + gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); + g_return_if_fail (page_num == GNOME_CAL_LIST_VIEW); + priv->list_view = g_object_ref (widget); + gtk_widget_show (widget); +#endif + + container = priv->vpaned; + + widget = gtk_vbox_new (FALSE, 0); + gtk_paned_pack1 (GTK_PANED (container), widget, FALSE, FALSE); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_hseparator_new (); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, TRUE, 0); + gtk_widget_show (widget); + + widget = gtk_label_new (NULL); + markup = g_strdup_printf ("%s", _("Tasks")); + gtk_label_set_markup (GTK_LABEL (widget), markup); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, TRUE, 0); + gtk_widget_show (widget); + g_free (markup); + + widget = e_calendar_table_new (shell_view, task_model); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + priv->task_table = g_object_ref (widget); + gtk_widget_show (widget); + + filename = g_build_filename (config_dir, "TaskPad", NULL); + e_calendar_table_load_state (E_CALENDAR_TABLE (widget), filename); + g_free (filename); + + container = priv->vpaned; + + widget = gtk_vbox_new (FALSE, 0); + gtk_paned_pack2 (GTK_PANED (container), widget, TRUE, FALSE); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_label_new (NULL); + markup = g_strdup_printf ("%s", _("Memos")); + gtk_label_set_markup (GTK_LABEL (widget), markup); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, TRUE, 0); + gtk_widget_show (widget); + g_free (markup); + + widget = e_memo_table_new (shell_view, memo_model); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + priv->memo_table = g_object_ref (widget); + gtk_widget_show (widget); + + filename = g_build_filename (config_dir, "MemoPad", NULL); + e_memo_table_load_state (E_MEMO_TABLE (widget), filename); + g_free (filename); + + /* Configuration managers for views and tables. */ + priv->day_view_config = e_day_view_config_new ( + E_DAY_VIEW (priv->day_view)); + priv->work_week_view_config = e_day_view_config_new ( + E_DAY_VIEW (priv->work_week_view)); + priv->week_view_config = e_week_view_config_new ( + E_WEEK_VIEW (priv->week_view)); + priv->month_view_config = e_week_view_config_new ( + E_WEEK_VIEW (priv->month_view)); + priv->list_view_config = e_cal_list_view_config_new ( + E_CAL_LIST_VIEW (priv->list_view)); + priv->task_table_config = e_calendar_table_config_new ( + E_CALENDAR_TABLE (priv->task_table)); + priv->memo_table_config = e_memo_table_config_new ( + E_MEMO_TABLE (priv->memo_table)); + + /* Load the view instance. */ + + view_instance = e_shell_view_new_view_instance (shell_view, NULL); + g_signal_connect_swapped ( + view_instance, "display-view", + G_CALLBACK (cal_shell_content_display_view_cb), + object); + gal_view_instance_load (view_instance); + priv->view_instance = view_instance; + + g_signal_connect_swapped ( + shell_view, "notify::view-id", + G_CALLBACK (cal_shell_content_notify_view_id_cb), + object); + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (priv->vpaned); + key = "/apps/evolution/calendar/display/vpane_position"; + gconf_bridge_bind_property_delayed (bridge, key, object, "position"); + + g_object_unref (memo_model); + g_object_unref (task_model); +} + +static void +cal_shell_content_class_init (ECalShellContentClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ECalShellContentPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = cal_shell_content_set_property; + object_class->get_property = cal_shell_content_get_property; + object_class->dispose = cal_shell_content_dispose; + object_class->finalize = cal_shell_content_finalize; + object_class->constructed = cal_shell_content_constructed; +} + +static void +cal_shell_content_init (ECalShellContent *cal_shell_content) +{ + cal_shell_content->priv = + E_CAL_SHELL_CONTENT_GET_PRIVATE (cal_shell_content); + + /* Postpone widget construction until we have a shell view. */ +} + +GType +e_cal_shell_content_get_type (void) +{ + return cal_shell_content_type; +} + +void +e_cal_shell_content_register_type (GTypeModule *type_module) +{ + static const GTypeInfo type_info = { + sizeof (ECalShellContentClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) cal_shell_content_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ECalShellContent), + 0, /* n_preallocs */ + (GInstanceInitFunc) cal_shell_content_init, + NULL /* value_table */ + }; + + cal_shell_content_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_CONTENT, + "ECalShellContent", &type_info, 0); +} + +GtkWidget * +e_cal_shell_content_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_CAL_SHELL_CONTENT, + "shell-view", shell_view, NULL); +} + +GnomeCalendar * +e_cal_shell_content_get_calendar (ECalShellContent *cal_shell_content) +{ + g_return_val_if_fail ( + E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL); + + /* FIXME */ + /*return GNOME_CALENDAR (cal_shell_content->priv->calendar);*/ + return NULL; +} + +EMemoTable * +e_cal_shell_content_get_memo_table (ECalShellContent *cal_shell_content) +{ + g_return_val_if_fail ( + E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL); + + return E_MEMO_TABLE (cal_shell_content->priv->memo_table); +} + +ECalendarTable * +e_cal_shell_content_get_task_table (ECalShellContent *cal_shell_content) +{ + g_return_val_if_fail ( + E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL); + + return E_CALENDAR_TABLE (cal_shell_content->priv->task_table); +} + +icaltimezone * +e_cal_shell_content_get_timezone (ECalShellContent *cal_shell_content) +{ + g_return_val_if_fail ( + E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL); + + /* FIXME */ + /*return cal_shell_content->priv->timezone;*/ + return NULL; +} + +GalViewInstance * +e_cal_shell_content_get_view_instance (ECalShellContent *cal_shell_content) +{ + g_return_val_if_fail ( + E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL); + + return cal_shell_content->priv->view_instance; +} + +void +e_cal_shell_content_copy_clipboard (ECalShellContent *cal_shell_content) +{ +#if 0 + GnomeCalendar *calendar; + EMemoTable *memo_table; + ECalendarTable *task_table; + + g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); + + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + switch (cal_shell_content_get_focus_location (cal_shell_content)) { + case FOCUS_CALENDAR: + gnome_calendar_copy_clipboard (calendar); + break; + + case FOCUS_MEMO_TABLE: + e_memo_table_copy_clipboard (memo_table); + break; + + case FOCUS_TASK_TABLE: + e_calendar_table_copy_clipboard (task_table); + break; + + default: + g_return_if_reached (); + } +#endif +} + +void +e_cal_shell_content_cut_clipboard (ECalShellContent *cal_shell_content) +{ +#if 0 + GnomeCalendar *calendar; + EMemoTable *memo_table; + ECalendarTable *task_table; + + g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); + + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + switch (cal_shell_content_get_focus_location (cal_shell_content)) { + case FOCUS_CALENDAR: + gnome_calendar_cut_clipboard (calendar); + break; + + case FOCUS_MEMO_TABLE: + e_memo_table_copy_clipboard (memo_table); + break; + + case FOCUS_TASK_TABLE: + e_calendar_table_copy_clipboard (task_table); + break; + + default: + g_return_if_reached (); + } +#endif +} + +void +e_cal_shell_content_paste_clipboard (ECalShellContent *cal_shell_content) +{ +#if 0 + GnomeCalendar *calendar; + EMemoTable *memo_table; + ECalendarTable *task_table; + + g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); + + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + switch (cal_shell_content_get_focus_location (cal_shell_content)) { + case FOCUS_CALENDAR: + gnome_calendar_paste_clipboard (calendar); + break; + + case FOCUS_MEMO_TABLE: + e_memo_table_copy_clipboard (memo_table); + break; + + case FOCUS_TASK_TABLE: + e_calendar_table_copy_clipboard (task_table); + break; + + default: + g_return_if_reached (); + } +#endif +} + +void +e_cal_shell_content_delete_selection (ECalShellContent *cal_shell_content) +{ +#if 0 + GnomeCalendar *calendar; + EMemoTable *memo_table; + ECalendarTable *task_table; + + g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); + + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + switch (cal_shell_content_get_focus_location (cal_shell_content)) { + case FOCUS_CALENDAR: + gnome_calendar_delete_selection (calendar); + break; + + case FOCUS_MEMO_TABLE: + e_memo_table_delete_selected (memo_table); + break; + + case FOCUS_TASK_TABLE: + e_calendar_table_delete_selected (task_table); + break; + + default: + g_return_if_reached (); + } +#endif +} + +void +e_cal_shell_content_delete_selected_occurrence (ECalShellContent *cal_shell_content) +{ +#if 0 + GnomeCalendar *calendar; + FocusLocation focus; + + g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); + + focus = cal_shell_content_get_focus_location (cal_shell_content); + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + + if (focus == FOCUS_CALENDAR) + gnome_calendar_delete_selected_occurrence (calendar); +#endif +} diff --git a/modules/calendar/e-cal-shell-content.h b/modules/calendar/e-cal-shell-content.h new file mode 100644 index 0000000000..44e13f733c --- /dev/null +++ b/modules/calendar/e-cal-shell-content.h @@ -0,0 +1,108 @@ +/* + * e-cal-shell-content.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_SHELL_CONTENT_H +#define E_CAL_SHELL_CONTENT_H + +#include +#include + +#include +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_CAL_SHELL_CONTENT \ + (e_cal_shell_content_get_type ()) +#define E_CAL_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_CAL_SHELL_CONTENT, ECalShellContent)) +#define E_CAL_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_CAL_SHELL_CONTENT, ECalShellContentClass)) +#define E_IS_CAL_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_CAL_SHELL_CONTENT)) +#define E_IS_CAL_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_CAL_SHELL_CONTENT)) +#define E_CAL_SHELL_CONTENT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_CAL_SHELL_CONTENT, ECalShellContentClass)) + +G_BEGIN_DECLS + +typedef struct _ECalShellContent ECalShellContent; +typedef struct _ECalShellContentClass ECalShellContentClass; +typedef struct _ECalShellContentPrivate ECalShellContentPrivate; + +enum { + E_CAL_SHELL_CONTENT_SELECTION_SINGLE = 1 << 0, + E_CAL_SHELL_CONTENT_SELECTION_MULTIPLE = 1 << 1, + E_CAL_SHELL_CONTENT_SELECTION_IS_ASSIGNABLE = 1 << 2, + E_CAL_SHELL_CONTENT_SELECTION_IS_COMPLETE = 1 << 3, + E_CAL_SHELL_CONTENT_SELECTION_IS_EDITABLE = 1 << 4, + E_CAL_SHELL_CONTENT_SELECTION_IS_MEETING = 1 << 5, + E_CAL_SHELL_CONTENT_SELECTION_IS_ORGANIZER = 1 << 6, + E_CAL_SHELL_CONTENT_SELECTION_IS_RECURRING = 1 << 7, + E_CAL_SHELL_CONTENT_SELECTION_CAN_ACCEPT = 1 << 8, + E_CAL_SHELL_CONTENT_SELECTION_CAN_DELEGATE = 1 << 9, + E_CAL_SHELL_CONTENT_SELECTION_CAN_SAVE = 1 << 10 +}; + +struct _ECalShellContent { + EShellContent parent; + ECalShellContentPrivate *priv; +}; + +struct _ECalShellContentClass { + EShellContentClass parent_class; +}; + +GType e_cal_shell_content_get_type (void); +void e_cal_shell_content_register_type + (GTypeModule *type_module); +GtkWidget * e_cal_shell_content_new (EShellView *shell_view); +GnomeCalendar * e_cal_shell_content_get_calendar + (ECalShellContent *cal_shell_content); +EMemoTable * e_cal_shell_content_get_memo_table + (ECalShellContent *cal_shell_content); +ECalendarTable *e_cal_shell_content_get_task_table + (ECalShellContent *cal_shell_content); +icaltimezone * e_cal_shell_content_get_timezone + (ECalShellContent *cal_shell_content); +GalViewInstance * + e_cal_shell_content_get_view_instance + (ECalShellContent *cal_shell_content); +void e_cal_shell_content_copy_clipboard + (ECalShellContent *cal_shell_content); +void e_cal_shell_content_cut_clipboard + (ECalShellContent *cal_shell_content); +void e_cal_shell_content_paste_clipboard + (ECalShellContent *cal_shell_content); +void e_cal_shell_content_delete_selection + (ECalShellContent *cal_shell_content); +void e_cal_shell_content_delete_selected_occurrence + (ECalShellContent *cal_shell_content); + +G_END_DECLS + +#endif /* E_CAL_SHELL_CONTENT_H */ diff --git a/modules/calendar/e-cal-shell-migrate.c b/modules/calendar/e-cal-shell-migrate.c new file mode 100644 index 0000000000..9887a5332c --- /dev/null +++ b/modules/calendar/e-cal-shell-migrate.c @@ -0,0 +1,796 @@ +/* + * e-cal-shell-backend-migrate.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-migrate.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "e-util/e-bconf-map.h" +#include "e-util/e-folder-map.h" +#include "e-util/e-util-private.h" +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/calendar-config-keys.h" +#include "calendar/gui/e-cal-event.h" +#include "shell/e-shell.h" + +#define WEBCAL_BASE_URI "webcal://" +#define CONTACTS_BASE_URI "contacts://" +#define BAD_CONTACTS_BASE_URI "contact://" +#define PERSONAL_RELATIVE_URI "system" + +static e_gconf_map_t calendar_display_map[] = { + /* /Calendar/Display */ + { "Timezone", "calendar/display/timezone", E_GCONF_MAP_STRING }, + { "Use24HourFormat", "calendar/display/use_24hour_format", E_GCONF_MAP_BOOL }, + { "WeekStartDay", "calendar/display/week_start_day", E_GCONF_MAP_INT }, + { "DayStartHour", "calendar/display/day_start_hour", E_GCONF_MAP_INT }, + { "DayStartMinute", "calendar/display/day_start_minute", E_GCONF_MAP_INT }, + { "DayEndHour", "calendar/display/day_end_hour", E_GCONF_MAP_INT }, + { "DayEndMinute", "calendar/display/day_end_minute", E_GCONF_MAP_INT }, + { "TimeDivisions", "calendar/display/time_divisions", E_GCONF_MAP_INT }, + { "View", "calendar/display/default_view", E_GCONF_MAP_INT }, + { "HPanePosition", "calendar/display/hpane_position", E_GCONF_MAP_FLOAT }, + { "VPanePosition", "calendar/display/vpane_position", E_GCONF_MAP_FLOAT }, + { "MonthHPanePosition", "calendar/display/month_hpane_position", E_GCONF_MAP_FLOAT }, + { "MonthVPanePosition", "calendar/display/month_vpane_position", E_GCONF_MAP_FLOAT }, + { "CompressWeekend", "calendar/display/compress_weekend", E_GCONF_MAP_BOOL }, + { "ShowEventEndTime", "calendar/display/show_event_end", E_GCONF_MAP_BOOL }, + { "WorkingDays", "calendar/display/working_days", E_GCONF_MAP_INT }, + { NULL }, +}; + +static e_gconf_map_t calendar_other_map[] = { + /* /Calendar/Other */ + { "ConfirmDelete", "calendar/prompts/confirm_delete", E_GCONF_MAP_BOOL }, + { "ConfirmExpunge", "calendar/prompts/confirm_purge", E_GCONF_MAP_BOOL }, + { "UseDefaultReminder", "calendar/other/use_default_reminder", E_GCONF_MAP_BOOL }, + { "DefaultReminderInterval", "calendar/other/default_reminder_interval", E_GCONF_MAP_INT }, + { "DefaultReminderUnits", "calendar/other/default_reminder_units", E_GCONF_MAP_STRING }, + { NULL }, +}; + +static e_gconf_map_t calendar_datenavigator_map[] = { + /* /Calendar/DateNavigator */ + { "ShowWeekNumbers", "calendar/date_navigator/show_week_numbers", E_GCONF_MAP_BOOL }, + { NULL }, +}; + +static e_gconf_map_t calendar_alarmnotify_map[] = { + /* /Calendar/AlarmNotify */ + { "LastNotificationTime", "calendar/notify/last_notification_time", E_GCONF_MAP_INT }, + { "CalendarToLoad%i", "calendar/notify/calendars", E_GCONF_MAP_STRING|E_GCONF_MAP_LIST }, + { "BlessedProgram%i", "calendar/notify/programs", E_GCONF_MAP_STRING|E_GCONF_MAP_LIST }, + { NULL }, +}; + +static e_gconf_map_list_t calendar_remap_list[] = { + + { "/Calendar/Display", calendar_display_map }, + { "/Calendar/Other/Map", calendar_other_map }, + { "/Calendar/DateNavigator", calendar_datenavigator_map }, + { "/Calendar/AlarmNotify", calendar_alarmnotify_map }, + + { NULL }, +}; + +static GtkWidget *window; +static GtkLabel *label; +static GtkProgressBar *progress; + +#ifndef G_OS_WIN32 + +/* No previous versions have been available on Win32, so don't + * bother with upgrade support from 1.x on Win32. + */ + +static void +setup_progress_dialog (void) +{ + GtkWidget *vbox, *hbox, *w; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title ((GtkWindow *) window, _("Migrating...")); + gtk_window_set_modal ((GtkWindow *) window, TRUE); + gtk_container_set_border_width ((GtkContainer *) window, 6); + + vbox = gtk_vbox_new (FALSE, 6); + gtk_widget_show (vbox); + gtk_container_add ((GtkContainer *) window, vbox); + + w = gtk_label_new (_("The location and hierarchy of the Evolution calendar " + "folders has changed since Evolution 1.x.\n\nPlease be " + "patient while Evolution migrates your folders...")); + + gtk_label_set_line_wrap ((GtkLabel *) w, TRUE); + gtk_widget_show (w); + gtk_box_pack_start_defaults ((GtkBox *) vbox, w); + + hbox = gtk_hbox_new (FALSE, 6); + gtk_widget_show (hbox); + gtk_box_pack_start_defaults ((GtkBox *) vbox, hbox); + + label = (GtkLabel *) gtk_label_new (""); + gtk_widget_show ((GtkWidget *) label); + gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) label); + + progress = (GtkProgressBar *) gtk_progress_bar_new (); + gtk_widget_show ((GtkWidget *) progress); + gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) progress); + + gtk_widget_show (window); +} + +static void +dialog_close (void) +{ + gtk_widget_destroy ((GtkWidget *) window); +} + +static void +dialog_set_folder_name (const gchar *folder_name) +{ + gchar *text; + + text = g_strdup_printf (_("Migrating '%s':"), folder_name); + gtk_label_set_text (label, text); + g_free (text); + + gtk_progress_bar_set_fraction (progress, 0.0); + + while (gtk_events_pending ()) + gtk_main_iteration (); +} + +static void +dialog_set_progress (double percent) +{ + gchar text[5]; + + snprintf (text, sizeof (text), "%d%%", (gint) (percent * 100.0f)); + + gtk_progress_bar_set_fraction (progress, percent); + gtk_progress_bar_set_text (progress, text); + + while (gtk_events_pending ()) + gtk_main_iteration (); +} + +static gboolean +check_for_conflict (ESourceGroup *group, gchar *name) +{ + GSList *sources; + GSList *s; + + sources = e_source_group_peek_sources (group); + + for (s = sources; s; s = s->next) { + ESource *source = E_SOURCE (s->data); + + if (!strcmp (e_source_peek_name (source), name)) + return TRUE; + } + + return FALSE; +} + +static gchar * +get_source_name (ESourceGroup *group, const gchar *path) +{ + gchar **p = g_strsplit (path, "/", 0); + gint i, j, starting_index; + gint num_elements; + gboolean conflict; + GString *s = g_string_new (NULL); + + for (i = 0; p[i]; i ++); + + num_elements = i; + i--; + + /* p[i] is now the last path element */ + + /* check if it conflicts */ + starting_index = i; + do { + for (j = starting_index; j < num_elements; j += 2) { + if (j != starting_index) + g_string_append_c (s, '_'); + g_string_append (s, p[j]); + } + + conflict = check_for_conflict (group, s->str); + + + /* if there was a conflict back up 2 levels (skipping the /subfolder/ element) */ + if (conflict) + starting_index -= 2; + + /* we always break out if we can't go any further, + regardless of whether or not we conflict. */ + if (starting_index < 0) + break; + + } while (conflict); + g_strfreev (p); + + return g_string_free (s, FALSE); +} + +static gboolean +migrate_ical (ECal *old_ecal, ECal *new_ecal) +{ + GList *l, *objects; + gint num_added = 0; + gint num_objects; + gboolean retval = TRUE; + + /* both ecals are loaded, start the actual migration */ + if (!e_cal_get_object_list (old_ecal, "#t", &objects, NULL)) + return FALSE; + + num_objects = g_list_length (objects); + for (l = objects; l; l = l->next) { + icalcomponent *ical_comp = l->data; + GError *error = NULL; + + if (!e_cal_create_object (new_ecal, ical_comp, NULL, &error)) { + g_warning ("Migration of object failed: %s", error->message); + retval = FALSE; + } + + g_clear_error (&error); + + num_added ++; + dialog_set_progress ((double)num_added / num_objects); + } + + g_list_foreach (objects, (GFunc) icalcomponent_free, NULL); + g_list_free (objects); + + return retval; +} + +static gboolean +migrate_ical_folder_to_source (gchar *old_path, ESource *new_source, ECalSourceType type) +{ + ECal *old_ecal = NULL, *new_ecal = NULL; + ESource *old_source; + ESourceGroup *group; + gchar *old_uri = g_strdup_printf ("file://%s", old_path); + GError *error = NULL; + gboolean retval = FALSE; + + group = e_source_group_new ("", old_uri); + old_source = e_source_new ("", ""); + e_source_group_add_source (group, old_source, -1); + + dialog_set_folder_name (e_source_peek_name (new_source)); + + if (!(old_ecal = e_cal_new (old_source, type))) { + g_warning ("could not find a backend for '%s'", e_source_get_uri (old_source)); + goto finish; + } + if (!e_cal_open (old_ecal, FALSE, &error)) { + g_warning ("failed to load source ecal for migration: '%s' (%s)", error->message, + e_source_get_uri (old_source)); + goto finish; + } + + if (!(new_ecal = e_cal_new (new_source, type))) { + g_warning ("could not find a backend for '%s'", e_source_get_uri (new_source)); + goto finish; + } + if (!e_cal_open (new_ecal, FALSE, &error)) { + g_warning ("failed to load destination ecal for migration: '%s' (%s)", error->message, + e_source_get_uri (new_source)); + goto finish; + } + + retval = migrate_ical (old_ecal, new_ecal); + +finish: + g_clear_error (&error); + if (old_ecal) + g_object_unref (old_ecal); + g_object_unref (group); + if (new_ecal) + g_object_unref (new_ecal); + g_free (old_uri); + + return retval; +} + +static gboolean +migrate_ical_folder (gchar *old_path, ESourceGroup *dest_group, gchar *source_name, ECalSourceType type) +{ + ESource *new_source; + gboolean retval; + + new_source = e_source_new (source_name, source_name); + e_source_set_relative_uri (new_source, e_source_peek_uid (new_source)); + e_source_group_add_source (dest_group, new_source, -1); + + retval = migrate_ical_folder_to_source (old_path, new_source, type); + + g_object_unref (new_source); + + return retval; +} + +#endif /* !G_OS_WIN32 */ + +#ifndef G_OS_WIN32 + +static void +migrate_pilot_db_key (const gchar *key, gpointer user_data) +{ + EXmlHash *xmlhash = user_data; + + e_xmlhash_add (xmlhash, key, ""); +} + +static void +migrate_pilot_data (const gchar *component, const gchar *conduit, const gchar *old_path, const gchar *new_path) +{ + gchar *changelog, *map; + const gchar *dent; + const gchar *ext; + gchar *filename; + GDir *dir; + + if (!(dir = g_dir_open (old_path, 0, NULL))) + return; + + map = g_alloca (12 + strlen (conduit)); + sprintf (map, "pilot-map-%s-", conduit); + + changelog = g_alloca (24 + strlen (conduit)); + sprintf (changelog, "pilot-sync-evolution-%s-", conduit); + + while ((dent = g_dir_read_name (dir))) { + if (!strncmp (dent, map, strlen (map)) && + ((ext = strrchr (dent, '.')) && !strcmp (ext, ".xml"))) { + /* pilot map file - src and dest file formats are identical */ + guchar inbuf[4096]; + gsize nread, nwritten; + gint fd0, fd1; + gssize n; + + filename = g_build_filename (old_path, dent, NULL); + if ((fd0 = g_open (filename, O_RDONLY|O_BINARY, 0)) == -1) { + g_free (filename); + continue; + } + + g_free (filename); + filename = g_build_filename (new_path, dent, NULL); + if ((fd1 = g_open (filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666)) == -1) { + g_free (filename); + close (fd0); + continue; + } + + do { + do { + n = read (fd0, inbuf, sizeof (inbuf)); + } while (n == -1 && errno == EINTR); + + if (n < 1) + break; + + nread = n; + nwritten = 0; + do { + do { + n = write (fd1, inbuf + nwritten, nread - nwritten); + } while (n == -1 && errno == EINTR); + + if (n > 0) + nwritten += n; + } while (nwritten < nread && n != -1); + + if (n == -1) + break; + } while (1); + + if (n != -1) + n = fsync (fd1); + + if (n == -1) { + g_warning ("Failed to migrate %s: %s", dent, strerror (errno)); + g_unlink (filename); + } + + close (fd0); + close (fd1); + g_free (filename); + } else if (!strncmp (dent, changelog, strlen (changelog)) && + ((ext = strrchr (dent, '.')) && !strcmp (ext, ".db"))) { + /* src and dest formats differ, src format is db3 while dest format is xml */ + EXmlHash *xmlhash; + EDbHash *dbhash; + struct stat st; + + filename = g_build_filename (old_path, dent, NULL); + if (g_stat (filename, &st) == -1) { + g_free (filename); + continue; + } + + dbhash = e_dbhash_new (filename); + g_free (filename); + + filename = g_strdup_printf ("%s/%s.ics-%s", new_path, component, dent); + if (g_stat (filename, &st) != -1) + g_unlink (filename); + xmlhash = e_xmlhash_new (filename); + g_free (filename); + + e_dbhash_foreach_key (dbhash, migrate_pilot_db_key, xmlhash); + + e_dbhash_destroy (dbhash); + + e_xmlhash_write (xmlhash); + e_xmlhash_destroy (xmlhash); + } + } + + g_dir_close (dir); +} + +#endif + +static ESourceGroup * +create_calendar_contact_source (ESourceList *source_list) +{ + ESourceGroup *group; + ESource *source; + + /* Create the contacts group */ + group = e_source_group_new (_("Contacts"), CONTACTS_BASE_URI); + e_source_list_add_group (source_list, group, -1); + + source = e_source_new (_("Birthdays & Anniversaries"), "/"); + e_source_group_add_source (group, source, -1); + g_object_unref (source); + + e_source_set_color_spec (source, "#FED4D3"); + e_source_group_set_readonly (group, TRUE); + + return group; +} + +static void +create_calendar_sources (EShellBackend *shell_backend, + ESourceList *source_list, + ESourceGroup **on_this_computer, + ESource **personal_source, + ESourceGroup **on_the_web, + ESourceGroup **contacts) +{ + EShell *shell; + EShellSettings *shell_settings; + GSList *groups; + ESourceGroup *group; + gchar *base_uri, *base_uri_proto; + const gchar *base_dir; + + *on_this_computer = NULL; + *on_the_web = NULL; + *contacts = NULL; + *personal_source = NULL; + + shell = e_shell_backend_get_shell (shell_backend); + shell_settings = e_shell_get_shell_settings (shell); + + base_dir = e_shell_backend_get_config_dir (shell_backend); + base_uri = g_build_filename (base_dir, "local", NULL); + + base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL); + + groups = e_source_list_peek_groups (source_list); + if (groups) { + /* groups are already there, we need to search for things... */ + GSList *g; + + for (g = groups; g; g = g->next) { + + group = E_SOURCE_GROUP (g->data); + + if (!strcmp (BAD_CONTACTS_BASE_URI, e_source_group_peek_base_uri (group))) + e_source_group_set_base_uri (group, CONTACTS_BASE_URI); + + if (!strcmp (base_uri, e_source_group_peek_base_uri (group))) + e_source_group_set_base_uri (group, base_uri_proto); + + if (!*on_this_computer && !strcmp (base_uri_proto, e_source_group_peek_base_uri (group))) + *on_this_computer = g_object_ref (group); + else if (!*on_the_web && !strcmp (WEBCAL_BASE_URI, e_source_group_peek_base_uri (group))) + *on_the_web = g_object_ref (group); + else if (!*contacts && !strcmp (CONTACTS_BASE_URI, e_source_group_peek_base_uri (group))) + *contacts = g_object_ref (group); + } + } + + if (*on_this_computer) { + /* make sure "Personal" shows up as a source under + this group */ + GSList *sources = e_source_group_peek_sources (*on_this_computer); + GSList *s; + for (s = sources; s; s = s->next) { + ESource *source = E_SOURCE (s->data); + const gchar *relative_uri; + + relative_uri = e_source_peek_relative_uri (source); + if (relative_uri == NULL) + continue; + if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) { + *personal_source = g_object_ref (source); + break; + } + } + } else { + /* create the local source group */ + group = e_source_group_new (_("On This Computer"), base_uri_proto); + e_source_list_add_group (source_list, group, -1); + + *on_this_computer = group; + } + + if (!*personal_source) { + gchar *primary_calendar; + + /* Create the default Person calendar */ + ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); + e_source_group_add_source (*on_this_computer, source, -1); + + primary_calendar = e_shell_settings_get_string ( + shell_settings, "cal-primary-calendar"); + + if (!primary_calendar && !calendar_config_get_calendars_selected ()) { + GSList selected; + + e_shell_settings_set_string ( + shell_settings, "cal-primary-calendar", + e_source_peek_uid (source)); + + selected.data = (gpointer)e_source_peek_uid (source); + selected.next = NULL; + calendar_config_set_calendars_selected (&selected); + } + + g_free (primary_calendar); + e_source_set_color_spec (source, "#BECEDD"); + *personal_source = source; + } + + if (!*on_the_web) { + /* Create the Webcal source group */ + group = e_source_group_new (_("On The Web"), WEBCAL_BASE_URI); + e_source_list_add_group (source_list, group, -1); + + *on_the_web = group; + } + + if (!*contacts) { + group = create_calendar_contact_source (source_list); + + *contacts = group; + } + + g_free (base_uri_proto); + g_free (base_uri); +} + +gboolean +e_cal_shell_backend_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint micro, + GError **error) +{ + ESourceGroup *on_this_computer = NULL, *on_the_web = NULL, *contacts = NULL; + ESource *personal_source = NULL; + ESourceList *source_list; + ECalEvent *ece; + ECalEventTargetModule *target; + gboolean retval = FALSE; + + source_list = g_object_get_data ( + G_OBJECT (shell_backend), "source-list"); + + /* we call this unconditionally now - create_groups either + creates the groups/sources or it finds the necessary + groups/sources. */ + create_calendar_sources ( + shell_backend, source_list, &on_this_computer, + &personal_source, &on_the_web, &contacts); + +#ifndef G_OS_WIN32 + if (major == 1) { + xmlDocPtr config_doc = NULL; + gchar *conf_file; + struct stat st; + + conf_file = g_build_filename (g_get_home_dir (), "evolution", "config.xmldb", NULL); + if (lstat (conf_file, &st) == 0 && S_ISREG (st.st_mode)) + config_doc = xmlParseFile (conf_file); + g_free (conf_file); + + if (config_doc && minor <= 2) { + GConfClient *gconf; + gint res = 0; + + /* move bonobo config to gconf */ + gconf = gconf_client_get_default (); + + res = e_bconf_import (gconf, config_doc, calendar_remap_list); + + g_object_unref (gconf); + + xmlFreeDoc(config_doc); + + if (res != 0) { + /* FIXME: set proper domain/code */ + g_set_error(error, 0, 0, _("Unable to migrate old settings from evolution/config.xmldb")); + goto fail; + } + } + + if (minor <= 4) { + GSList *migration_dirs, *l; + gchar *path, *local_cal_folder; + + setup_progress_dialog (); + + path = g_build_filename (g_get_home_dir (), "evolution", "local", NULL); + migration_dirs = e_folder_map_local_folders (path, "calendar"); + local_cal_folder = g_build_filename (path, "Calendar", NULL); + g_free (path); + + if (personal_source) + migrate_ical_folder_to_source (local_cal_folder, personal_source, E_CAL_SOURCE_TYPE_EVENT); + + for (l = migration_dirs; l; l = l->next) { + gchar *source_name; + + if (personal_source && !strcmp ((gchar *)l->data, local_cal_folder)) + continue; + + source_name = get_source_name (on_this_computer, (gchar *)l->data); + + if (!migrate_ical_folder (l->data, on_this_computer, source_name, E_CAL_SOURCE_TYPE_EVENT)) { + /* FIXME: domain/code */ + g_set_error(error, 0, 0, _("Unable to migrate calendar `%s'"), source_name); + g_free(source_name); + goto fail; + } + + g_free (source_name); + } + + g_free (local_cal_folder); + + dialog_close (); + } + + if (minor <= 4 || (minor == 5 && micro < 5)) { + GConfClient *gconf; + GConfValue *gconf_val; + gint i; + const gchar *keys[] = { + CALENDAR_CONFIG_HPANE_POS, + CALENDAR_CONFIG_VPANE_POS, + CALENDAR_CONFIG_MONTH_HPANE_POS, + CALENDAR_CONFIG_MONTH_VPANE_POS, + NULL + }; + + gconf = gconf_client_get_default (); + + for (i = 0; keys[i]; i++) { + gconf_val = gconf_client_get (gconf, keys[i], NULL); + if (gconf_val) { + if (gconf_val->type != GCONF_VALUE_INT) + gconf_client_unset (gconf, keys[i], NULL); + gconf_value_free (gconf_val); + } + } + + g_object_unref (gconf); + } + + if (minor < 5 || (minor == 5 && micro <= 10)) { + gchar *old_path, *new_path; + + old_path = g_build_filename (g_get_home_dir (), "evolution", "local", "Calendar", NULL); + new_path = g_build_filename (e_shell_backend_get_config_dir (shell_backend), + "local", "system", NULL); + migrate_pilot_data ("calendar", "calendar", old_path, new_path); + g_free (new_path); + g_free (old_path); + } + + /* we only need to do this next step if people ran + older versions of 1.5. We need to clear out the + absolute URI's that were assigned to ESources + during one phase of development, as they take + precedent over relative uris (but aren't updated + when editing an ESource). */ + if (minor == 5 && micro <= 11) { + GSList *g; + for (g = e_source_list_peek_groups (source_list); g; g = g->next) { + ESourceGroup *group = g->data; + GSList *s; + + for (s = e_source_group_peek_sources (group); s; s = s->next) { + ESource *source = s->data; + e_source_set_absolute_uri (source, NULL); + } + } + } + + } +#endif /* !G_OS_WIN32 */ + + e_source_list_sync (source_list, NULL); + + /** @Event: component.migration + * @Title: Migration step in component initialization + * @Target: ECalEventTargetComponent + * + * component.migration is emitted during the calendar component + * initialization process. This allows new calendar backend types + * to be distributed as an e-d-s backend and a plugin without + * reaching their grubby little fingers into migration.c + */ + /* Fire off migration event */ + ece = e_cal_event_peek (); + target = e_cal_event_target_new_module (ece, shell_backend, 0); + e_event_emit ((EEvent *) ece, "module.migration", (EEventTarget *) target); + + retval = TRUE; +fail: + if (on_this_computer) + g_object_unref (on_this_computer); + if (on_the_web) + g_object_unref (on_the_web); + if (contacts) + g_object_unref (contacts); + if (personal_source) + g_object_unref (personal_source); + + return retval; +} + diff --git a/modules/calendar/e-cal-shell-migrate.h b/modules/calendar/e-cal-shell-migrate.h new file mode 100644 index 0000000000..359ca5ea22 --- /dev/null +++ b/modules/calendar/e-cal-shell-migrate.h @@ -0,0 +1,38 @@ +/* + * e-cal-shell-backend-migrate.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_SHELL_BACKEND_MIGRATE_H +#define E_CAL_SHELL_BACKEND_MIGRATE_H + +#include +#include + +G_BEGIN_DECLS + +gboolean e_cal_shell_backend_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint micro, + GError **error); + +G_END_DECLS + +#endif /* E_CAL_SHELL_BACKEND_MIGRATE_H */ diff --git a/modules/calendar/e-cal-shell-settings.c b/modules/calendar/e-cal-shell-settings.c new file mode 100644 index 0000000000..03af4aeebc --- /dev/null +++ b/modules/calendar/e-cal-shell-settings.c @@ -0,0 +1,59 @@ +/* + * e-cal-shell-backend-settings.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-settings.h" + +#include + +void +e_cal_shell_backend_init_settings (EShell *shell) +{ + EShellSettings *shell_settings; + + shell_settings = e_shell_get_shell_settings (shell); + + /* XXX Default values should match the GConf schema. + * Yes it's redundant, but we're stuck with GConf. */ + + e_shell_settings_install_property ( + g_param_spec_string ( + "cal-primary-calendar", + NULL, + NULL, + NULL, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "cal-primary-calendar", + "/apps/evolution/calendar/display/primary_calendar"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "cal-use-system-timezone", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "cal-use-system-timezone", + "/apps/evolution/calendar/display/use_system_timezone"); +} diff --git a/modules/calendar/e-cal-shell-settings.h b/modules/calendar/e-cal-shell-settings.h new file mode 100644 index 0000000000..de8b22888b --- /dev/null +++ b/modules/calendar/e-cal-shell-settings.h @@ -0,0 +1,33 @@ +/* + * e-cal-shell-backend-settings.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_SHELL_BACKEND_SETTINGS_H +#define E_CAL_SHELL_BACKEND_SETTINGS_H + +#include + +G_BEGIN_DECLS + +void e_cal_shell_backend_init_settings (EShell *shell); + +G_END_DECLS + +#endif /* E_CAL_SHELL_BACKEND_SETTINGS_H */ diff --git a/modules/calendar/e-cal-shell-sidebar.c b/modules/calendar/e-cal-shell-sidebar.c new file mode 100644 index 0000000000..dc7df596d6 --- /dev/null +++ b/modules/calendar/e-cal-shell-sidebar.c @@ -0,0 +1,759 @@ +/* + * e-cal-shell-sidebar.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-sidebar.h" + +#include +#include + +#include "e-util/e-error.h" +#include "e-util/gconf-bridge.h" +#include "calendar/common/authentication.h" +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/e-calendar-selector.h" +#include "calendar/gui/e-mini-calendar-config.h" +#include "calendar/gui/misc.h" + +#include "e-cal-shell-backend.h" +#include "e-cal-shell-view.h" + +#define E_CAL_SHELL_SIDEBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_CAL_SHELL_SIDEBAR, ECalShellSidebarPrivate)) + +struct _ECalShellSidebarPrivate { + GtkWidget *paned; + GtkWidget *selector; + GtkWidget *mini_calendar; + + /* UID -> Client */ + GHashTable *client_table; + + EMiniCalendarConfig *mini_calendar_config; +}; + +enum { + PROP_0, + PROP_MINI_CALENDAR, + PROP_SELECTOR +}; + +enum { + CLIENT_ADDED, + CLIENT_REMOVED, + STATUS_MESSAGE, + LAST_SIGNAL +}; + +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; +static GType cal_shell_sidebar_type; + +static void +cal_shell_sidebar_emit_client_added (ECalShellSidebar *cal_shell_sidebar, + ECal *client) +{ + guint signal_id = signals[CLIENT_ADDED]; + + g_signal_emit (cal_shell_sidebar, signal_id, 0, client); +} + +static void +cal_shell_sidebar_emit_client_removed (ECalShellSidebar *cal_shell_sidebar, + ECal *client) +{ + guint signal_id = signals[CLIENT_REMOVED]; + + g_signal_emit (cal_shell_sidebar, signal_id, 0, client); +} + +static void +cal_shell_sidebar_emit_status_message (ECalShellSidebar *cal_shell_sidebar, + const gchar *status_message) +{ + guint signal_id = signals[STATUS_MESSAGE]; + + g_signal_emit (cal_shell_sidebar, signal_id, 0, status_message); +} + +static void +cal_shell_sidebar_backend_died_cb (ECalShellSidebar *cal_shell_sidebar, + ECal *client) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + GHashTable *client_table; + ESource *source; + const gchar *uid; + + client_table = cal_shell_sidebar->priv->client_table; + + shell_sidebar = E_SHELL_SIDEBAR (cal_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + source = e_cal_get_source (client); + uid = e_source_peek_uid (source); + + g_object_ref (source); + + g_hash_table_remove (client_table, uid); + cal_shell_sidebar_emit_status_message (cal_shell_sidebar, NULL); + + e_error_run ( + GTK_WINDOW (shell_window), + "calendar:calendar-crashed", NULL); + + g_object_unref (source); +} + +static void +cal_shell_sidebar_backend_error_cb (ECalShellSidebar *cal_shell_sidebar, + const gchar *message, + ECal *client) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + GtkWidget *dialog; + const gchar *uri; + gchar *uri_no_passwd; + + shell_sidebar = E_SHELL_SIDEBAR (cal_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + uri = e_cal_get_uri (client); + uri_no_passwd = get_uri_without_password (uri); + + dialog = gtk_message_dialog_new ( + GTK_WINDOW (shell_window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, + _("Error on %s\n%s"), + uri_no_passwd, message); + + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + + g_free (uri_no_passwd); +} + +static void +cal_shell_sidebar_client_opened_cb (ECalShellSidebar *cal_shell_sidebar, + ECalendarStatus status, + ECal *client) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + ESource *source; + + source = e_cal_get_source (client); + + shell_sidebar = E_SHELL_SIDEBAR (cal_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + if (status == E_CALENDAR_STATUS_AUTHENTICATION_FAILED || + status == E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED) + auth_cal_forget_password (client); + + switch (status) { + case E_CALENDAR_STATUS_OK: + g_signal_handlers_disconnect_matched ( + client, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, + cal_shell_sidebar_client_opened_cb, NULL); + + cal_shell_sidebar_emit_status_message ( + cal_shell_sidebar, _("Loading calendars")); + cal_shell_sidebar_emit_client_added ( + cal_shell_sidebar, client); + cal_shell_sidebar_emit_status_message ( + cal_shell_sidebar, NULL); + break; + + case E_CALENDAR_STATUS_AUTHENTICATION_FAILED: + e_cal_open_async (client, FALSE); + break; + + case E_CALENDAR_STATUS_BUSY: + break; + + case E_CALENDAR_STATUS_REPOSITORY_OFFLINE: + e_error_run ( + GTK_WINDOW (shell_window), + "calendar:prompt-no-contents-offline-calendar", + NULL); + break; + + default: + cal_shell_sidebar_emit_client_removed ( + cal_shell_sidebar, client); + break; + } +} + +static void +cal_shell_sidebar_row_changed_cb (ECalShellSidebar *cal_shell_sidebar, + GtkTreePath *tree_path, + GtkTreeIter *tree_iter, + GtkTreeModel *tree_model) +{ + ESourceSelector *selector; + ESource *source; + + /* XXX ESourceSelector's underlying tree store has only one + * column: ESource objects. While we're not supposed to + * know this, listening for "row-changed" signals from + * the model is easier to deal with than the selector's + * "selection-changed" signal, which doesn't tell you + * _which_ row changed. */ + + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + gtk_tree_model_get (tree_model, tree_iter, 0, &source, -1); + + /* XXX This signal gets emitted a lot while the model is being + * rebuilt, during which time we won't get a valid ESource. + * ESourceSelector should probably block this signal while + * rebuilding the model, but we'll be forgiving and not + * emit a warning. */ + if (!E_IS_SOURCE (source)) + return; + + if (e_source_selector_source_is_selected (selector, source)) + e_cal_shell_sidebar_add_source (cal_shell_sidebar, source); + else + e_cal_shell_sidebar_remove_source (cal_shell_sidebar, source); +} + +static void +cal_shell_sidebar_selection_changed_cb (ECalShellSidebar *cal_shell_sidebar, + ESourceSelector *selector) +{ + GSList *list, *iter; + + /* This signal is emitted less frequently than "row-changed", + * especially when the model is being rebuilt. So we'll take + * it easy on poor GConf. */ + + list = e_source_selector_get_selection (selector); + + for (iter = list; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + + iter->data = (gpointer) e_source_peek_uid (source); + g_object_unref (source); + } + + calendar_config_set_calendars_selected (list); + + g_slist_free (list); +} + +static void +cal_shell_sidebar_primary_selection_changed_cb (ECalShellSidebar *cal_shell_sidebar, + ESourceSelector *selector) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + EShellSettings *shell_settings; + ESource *source; + + /* XXX ESourceSelector needs a "primary-selection-uid" property + * so we can just bind the property with GConfBridge. */ + + source = e_source_selector_peek_primary_selection (selector); + if (source == NULL) + return; + + shell_sidebar = E_SHELL_SIDEBAR (cal_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + e_shell_settings_set_string ( + shell_settings, "cal-primary-calendar", + e_source_peek_uid (source)); +} + +static void +cal_shell_sidebar_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_MINI_CALENDAR: + g_value_set_object ( + value, e_cal_shell_sidebar_get_mini_calendar ( + E_CAL_SHELL_SIDEBAR (object))); + return; + + case PROP_SELECTOR: + g_value_set_object ( + value, e_cal_shell_sidebar_get_selector ( + E_CAL_SHELL_SIDEBAR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +cal_shell_sidebar_dispose (GObject *object) +{ + ECalShellSidebarPrivate *priv; + + priv = E_CAL_SHELL_SIDEBAR_GET_PRIVATE (object); + + if (priv->paned != NULL) { + g_object_unref (priv->paned); + priv->paned = NULL; + } + + if (priv->selector != NULL) { + g_object_unref (priv->selector); + priv->selector = NULL; + } + + if (priv->mini_calendar != NULL) { + g_object_unref (priv->mini_calendar); + priv->mini_calendar = NULL; + } + + g_hash_table_remove_all (priv->client_table); + + if (priv->mini_calendar_config != NULL) { + g_object_unref (priv->mini_calendar_config); + priv->mini_calendar = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +cal_shell_sidebar_finalize (GObject *object) +{ + ECalShellSidebarPrivate *priv; + + priv = E_CAL_SHELL_SIDEBAR_GET_PRIVATE (object); + + g_hash_table_destroy (priv->client_table); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +cal_shell_sidebar_constructed (GObject *object) +{ + ECalShellSidebarPrivate *priv; + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + EShellBackend *shell_backend; + EShellSidebar *shell_sidebar; + EShellSettings *shell_settings; + ESourceSelector *selector; + ESourceList *source_list; + ESource *source; + ECalendarItem *calitem; + GConfBridge *bridge; + GtkTreeModel *model; + GtkWidget *container; + GtkWidget *widget; + AtkObject *a11y; + GSList *list, *iter; + const gchar *key; + gchar *uid; + + priv = E_CAL_SHELL_SIDEBAR_GET_PRIVATE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_sidebar = E_SHELL_SIDEBAR (object); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_backend = e_shell_view_get_shell_backend (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + source_list = e_cal_shell_backend_get_source_list ( + E_CAL_SHELL_BACKEND (shell_backend)); + + container = GTK_WIDGET (shell_sidebar); + + widget = gtk_vpaned_new (); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->paned = g_object_ref (widget); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_paned_add1 (GTK_PANED (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = e_calendar_selector_new (source_list); + e_source_selector_set_select_new (E_SOURCE_SELECTOR (widget), TRUE); + gtk_container_add (GTK_CONTAINER (container), widget); + a11y = gtk_widget_get_accessible (widget); + atk_object_set_name (a11y, _("Calendar Selector")); + priv->selector = g_object_ref (widget); + gtk_widget_show (widget); + + container = priv->paned; + + widget = e_calendar_new (); + calitem = E_CALENDAR (widget)->calitem; + e_calendar_item_set_days_start_week_sel (calitem, 9); + e_calendar_item_set_max_days_sel (calitem, 42); + gtk_paned_add2 (GTK_PANED (container), widget); + priv->mini_calendar = g_object_ref (widget); + gtk_widget_show (widget); + + priv->mini_calendar_config = + e_mini_calendar_config_new (E_CALENDAR (widget)); + + /* Restore the selector state from the last session. */ + + selector = E_SOURCE_SELECTOR (priv->selector); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (selector)); + + g_signal_connect_swapped ( + model, "row-changed", + G_CALLBACK (cal_shell_sidebar_row_changed_cb), + object); + + source = NULL; + uid = e_shell_settings_get_string ( + shell_settings, "cal-primary-calendar"); + if (uid != NULL) + source = e_source_list_peek_source_by_uid (source_list, uid); + if (source == NULL) + source = e_source_list_peek_source_any (source_list); + if (source != NULL) + e_source_selector_set_primary_selection (selector, source); + g_free (uid); + + list = calendar_config_get_calendars_selected (); + for (iter = list; iter != NULL; iter = iter->next) { + uid = iter->data; + source = e_source_list_peek_source_by_uid (source_list, uid); + g_free (uid); + + if (source == NULL) + continue; + + e_source_selector_select_source (selector, source); + } + g_slist_free (list); + + /* Listen for subsequent changes to the selector. */ + + g_signal_connect_swapped ( + selector, "selection-changed", + G_CALLBACK (cal_shell_sidebar_selection_changed_cb), + object); + + g_signal_connect_swapped ( + selector, "primary-selection-changed", + G_CALLBACK (cal_shell_sidebar_primary_selection_changed_cb), + object); + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (priv->paned); + key = "/apps/evolution/calendar/display/date_navigator_vpane_position"; + gconf_bridge_bind_property_delayed (bridge, key, object, "position"); +} + +static void +cal_shell_sidebar_client_removed (ECalShellSidebar *cal_shell_sidebar, + ECal *client) +{ + ESourceSelector *selector; + GHashTable *client_table; + ESource *source; + const gchar *uid; + + client_table = cal_shell_sidebar->priv->client_table; + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + + g_signal_handlers_disconnect_matched ( + client, G_SIGNAL_MATCH_DATA, 0, 0, + NULL, NULL, cal_shell_sidebar); + + source = e_cal_get_source (client); + e_source_selector_unselect_source (selector, source); + + uid = e_source_peek_uid (source); + g_hash_table_remove (client_table, uid); + + cal_shell_sidebar_emit_status_message (cal_shell_sidebar, NULL); +} + +static void +cal_shell_sidebar_class_init (ECalShellSidebarClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ECalShellSidebarPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->get_property = cal_shell_sidebar_get_property; + object_class->dispose = cal_shell_sidebar_dispose; + object_class->finalize = cal_shell_sidebar_finalize; + object_class->constructed = cal_shell_sidebar_constructed; + + class->client_removed = cal_shell_sidebar_client_removed; + + g_object_class_install_property ( + object_class, + PROP_MINI_CALENDAR, + g_param_spec_object ( + "mini-calendar", + _("Mini-Calendar Widget"), + _("This widget displays a miniature calendar"), + E_TYPE_CALENDAR, + G_PARAM_READABLE)); + + g_object_class_install_property ( + object_class, + PROP_SELECTOR, + g_param_spec_object ( + "selector", + _("Source Selector Widget"), + _("This widget displays groups of calendars"), + E_TYPE_SOURCE_SELECTOR, + G_PARAM_READABLE)); + + signals[CLIENT_ADDED] = g_signal_new ( + "client-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ECalShellSidebarClass, client_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CAL); + + signals[CLIENT_REMOVED] = g_signal_new ( + "client-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ECalShellSidebarClass, client_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CAL); + + signals[STATUS_MESSAGE] = g_signal_new ( + "status-message", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (ECalShellSidebarClass, status_message), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); +} + +static void +cal_shell_sidebar_init (ECalShellSidebar *cal_shell_sidebar) +{ + GHashTable *client_table; + + client_table = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_object_unref); + + cal_shell_sidebar->priv = + E_CAL_SHELL_SIDEBAR_GET_PRIVATE (cal_shell_sidebar); + + cal_shell_sidebar->priv->client_table = client_table; + + /* Postpone widget construction until we have a shell view. */ +} + +GType +e_cal_shell_sidebar_get_type (void) +{ + return cal_shell_sidebar_type; +} + +void +e_cal_shell_sidebar_register_type (GTypeModule *type_module) +{ + static const GTypeInfo type_info = { + sizeof (ECalShellSidebarClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) cal_shell_sidebar_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ECalShellSidebar), + 0, /* n_preallocs */ + (GInstanceInitFunc) cal_shell_sidebar_init, + NULL /* value_table */ + }; + + cal_shell_sidebar_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_SIDEBAR, + "ECalShellSidebar", &type_info, 0); +} + +GtkWidget * +e_cal_shell_sidebar_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_CAL_SHELL_SIDEBAR, + "shell-view", shell_view, NULL); +} + +GList * +e_cal_shell_sidebar_get_clients (ECalShellSidebar *cal_shell_sidebar) +{ + GHashTable *client_table; + + g_return_val_if_fail ( + E_IS_CAL_SHELL_SIDEBAR (cal_shell_sidebar), NULL); + + client_table = cal_shell_sidebar->priv->client_table; + + return g_hash_table_get_values (client_table); +} + +ECalendar * +e_cal_shell_sidebar_get_mini_calendar (ECalShellSidebar *cal_shell_sidebar) +{ + g_return_val_if_fail ( + E_IS_CAL_SHELL_SIDEBAR (cal_shell_sidebar), NULL); + + return E_CALENDAR (cal_shell_sidebar->priv->mini_calendar); +} + +ESourceSelector * +e_cal_shell_sidebar_get_selector (ECalShellSidebar *cal_shell_sidebar) +{ + g_return_val_if_fail ( + E_IS_CAL_SHELL_SIDEBAR (cal_shell_sidebar), NULL); + + return E_SOURCE_SELECTOR (cal_shell_sidebar->priv->selector); +} + +void +e_cal_shell_sidebar_add_source (ECalShellSidebar *cal_shell_sidebar, + ESource *source) +{ + ESourceSelector *selector; + GHashTable *client_table; + ECal *client; + const gchar *uid; + const gchar *uri; + gchar *message; + + g_return_if_fail (E_IS_CAL_SHELL_SIDEBAR (cal_shell_sidebar)); + g_return_if_fail (E_IS_SOURCE (source)); + + client_table = cal_shell_sidebar->priv->client_table; + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + + uid = e_source_peek_uid (source); + client = g_hash_table_lookup (client_table, uid); + + if (client != NULL) + return; + + client = auth_new_cal_from_source (source, E_CAL_SOURCE_TYPE_EVENT); + g_return_if_fail (client != NULL); + + g_signal_connect_swapped ( + client, "backend-died", + G_CALLBACK (cal_shell_sidebar_backend_died_cb), + cal_shell_sidebar); + + g_signal_connect_swapped ( + client, "backend-error", + G_CALLBACK (cal_shell_sidebar_backend_error_cb), + cal_shell_sidebar); + + g_hash_table_insert (client_table, g_strdup (uid), client); + e_source_selector_select_source (selector, source); + + uri = e_cal_get_uri (client); + message = g_strdup_printf (_("Opening calendar at %s"), uri); + cal_shell_sidebar_emit_status_message (cal_shell_sidebar, message); + g_free (message); + + g_signal_connect_swapped ( + client, "cal-opened", + G_CALLBACK (cal_shell_sidebar_client_opened_cb), + cal_shell_sidebar); + + e_cal_open_async (client, FALSE); +} + +void +e_cal_shell_sidebar_remove_source (ECalShellSidebar *cal_shell_sidebar, + ESource *source) +{ + ESourceSelector *selector; + GHashTable *client_table; + ECal *client; + const gchar *uid; + + g_return_if_fail (E_IS_CAL_SHELL_SIDEBAR (cal_shell_sidebar)); + g_return_if_fail (E_IS_SOURCE (source)); + + client_table = cal_shell_sidebar->priv->client_table; + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + + uid = e_source_peek_uid (source); + client = g_hash_table_lookup (client_table, uid); + + if (client == NULL) + return; + + cal_shell_sidebar_emit_client_removed (cal_shell_sidebar, client); +} diff --git a/modules/calendar/e-cal-shell-sidebar.h b/modules/calendar/e-cal-shell-sidebar.h new file mode 100644 index 0000000000..c555537abf --- /dev/null +++ b/modules/calendar/e-cal-shell-sidebar.h @@ -0,0 +1,101 @@ +/* + * e-cal-shell-sidebar.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_SHELL_SIDEBAR_H +#define E_CAL_SHELL_SIDEBAR_H + +#include +#include + +#include +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_CAL_SHELL_SIDEBAR \ + (e_cal_shell_sidebar_get_type ()) +#define E_CAL_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_CAL_SHELL_SIDEBAR, ECalShellSidebar)) +#define E_CAL_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_CAL_SHELL_SIDEBAR, ECalShellSidebarClass)) +#define E_IS_CAL_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_CAL_SHELL_SIDEBAR)) +#define E_IS_CAL_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_CAL_SHELL_SIDEBAR)) +#define E_CAL_SHELL_SIDEBAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_CAL_SHELL_SIDEBAR, ECalShellSidebarClass)) + +G_BEGIN_DECLS + +typedef struct _ECalShellSidebar ECalShellSidebar; +typedef struct _ECalShellSidebarClass ECalShellSidebarClass; +typedef struct _ECalShellSidebarPrivate ECalShellSidebarPrivate; + +enum { + E_CAL_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE = 1 << 0, + E_CAL_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_EMPTY = 1 << 1, + E_CAL_SHELL_SIDEBAR_SOURCE_CAN_GO_OFFLINE = 1 << 2, + E_CAL_SHELL_SIDEBAR_SOURCE_CAN_DELETE = 1 << 3 +}; + +struct _ECalShellSidebar { + EShellSidebar parent; + ECalShellSidebarPrivate *priv; +}; + +struct _ECalShellSidebarClass { + EShellSidebarClass parent_class; + + /* Signals */ + void (*client_added) (ECalShellSidebar *cal_shell_sidebar, + ECal *client); + void (*client_removed) (ECalShellSidebar *cal_shell_sidebar, + ECal *client); + void (*status_message) (ECalShellSidebar *cal_shell_sidebar, + const gchar *status_message); +}; + +GType e_cal_shell_sidebar_get_type (void); +void e_cal_shell_sidebar_register_type + (GTypeModule *type_module); +GtkWidget * e_cal_shell_sidebar_new (EShellView *shell_view); +GList * e_cal_shell_sidebar_get_clients + (ECalShellSidebar *cal_shell_sidebar); +ECalendar * e_cal_shell_sidebar_get_mini_calendar + (ECalShellSidebar *cal_shell_sidebar); +ESourceSelector * + e_cal_shell_sidebar_get_selector + (ECalShellSidebar *cal_shell_sidebar); +void e_cal_shell_sidebar_add_source + (ECalShellSidebar *cal_shell_sidebar, + ESource *source); +void e_cal_shell_sidebar_remove_source + (ECalShellSidebar *cal_shell_sidebar, + ESource *source); + +G_END_DECLS + +#endif /* E_CAL_SHELL_SIDEBAR_H */ diff --git a/modules/calendar/e-cal-shell-view-actions.c b/modules/calendar/e-cal-shell-view-actions.c new file mode 100644 index 0000000000..02b7af609e --- /dev/null +++ b/modules/calendar/e-cal-shell-view-actions.c @@ -0,0 +1,1202 @@ +/* + * e-cal-shell-view-actions.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-view-private.h" + +static void +action_calendar_copy_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellSidebar *cal_shell_sidebar; + EShellWindow *shell_window; + EShellView *shell_view; + ESourceSelector *selector; + ESource *source; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (E_IS_SOURCE (source)); + + copy_source_dialog ( + GTK_WINDOW (shell_window), + source, E_CAL_SOURCE_TYPE_EVENT); +} + +static void +action_calendar_delete_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellContent *cal_shell_content; + ECalShellSidebar *cal_shell_sidebar; + EShellWindow *shell_window; + EShellView *shell_view; + ECalendarView *calendar_view; + GnomeCalendarViewType view_type; + ECalModel *model; + ESourceSelector *selector; + ESourceGroup *source_group; + ESourceList *source_list; + ESource *source; + gint response; + gchar *uri; + GError *error = NULL; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_content = cal_shell_content->priv->cal_shell_content; + view_type = e_cal_shell_content_get_current_view (cal_shell_content); + calendar_view = e_cal_shell_content_get_calendar_view ( + cal_shell_content, view_type); + model = e_calendar_view_get_model (calendar_view); + + cal_shell_sidebar = cal_shell_sidebar->priv->cal_shell_sidebar; + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (E_IS_SOURCE (source)); + + /* Ask for confirmation. */ + response = e_error_run ( + GTK_WINDOW (shell_window), + "calendar:prompt-delete-calendar", + e_source_peek_name (source)); + if (response != GTK_RESPONSE_YES) + return; + + uri = e_source_get_uri (source); + client = e_cal_model_get_client_for_uri (model, uri); + if (client == NULL) + client = e_cal_new_from_uri (uri, E_CAL_SOURCE_TYPE_EVENT); + g_free (uri); + + g_return_if_fail (client != NULL); + + if (!e_cal_remove (client, &error)) { + g_warning ("%s", error->message); + g_error_free (error); + return; + } + + if (e_source_selector_source_is_selected (selector, source)) { + e_cal_shell_sidebar_remove_source ( + cal_shell_sidebar, source); + e_source_selector_unselect_source (selector, source); + } + + source_group = e_source_peek_group (source); + e_source_group_remove_source (source_group, source); + + source_list = cal_shell_view->priv->source_list; + if (!e_source_list_sync (source_list, &error)) { + g_warning ("%s", error->message); + g_error_free (error); + } +#endif +} + +static void +action_calendar_go_back_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + + gnome_calendar_previous (calendar); +#endif +} + +static void +action_calendar_go_forward_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + + gnome_calendar_next (calendar); +#endif +} + +static void +action_calendar_go_today_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + + gnome_calendar_goto_today (calendar); +#endif +} + +static void +action_calendar_jump_to_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + + goto_dialog (calendar); +#endif +} + +static void +action_calendar_new_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + EShellView *shell_view; + EShellWindow *shell_window; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + calendar_setup_new_calendar (GTK_WINDOW (shell_window)); +#endif +} + +static void +action_calendar_print_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + GtkPrintOperationAction print_action; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; + + if (gnome_calendar_get_view (calendar) == GNOME_CAL_LIST_VIEW) { + ECalListView *list_view; + GtkWidget *widget; + ETable *table; + + widget = gnome_calendar_get_current_view_widget (calendar); + list_view = E_CAL_LIST_VIEW (widget); + table = e_table_scrolled_get_table (list_view->table_scrolled); + print_table (table, _("Print"), _("Calendar"), action); + } else { + time_t start; + + gnome_calendar_get_current_time_range (calendar, &start, NULL); + print_calendar (calendar, action, start); + } +#endif +} + +static void +action_calendar_print_preview_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + GtkPrintOperationAction print_action; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW; + + if (gnome_calendar_get_view (calendar) == GNOME_CAL_LIST_VIEW) { + ECalListView *list_view; + GtkWidget *widget; + ETable *table; + + widget = gnome_calendar_get_current_view_widget (calendar); + list_view = E_CAL_LIST_VIEW (widget); + table = e_table_scrolled_get_table (list_view->table_scrolled); + print_table (table, _("Print"), _("Calendar"), action); + } else { + time_t start; + + gnome_calendar_get_current_time_range (calendar, &start, NULL); + print_calendar (calendar, action, start); + } +#endif +} + +static void +action_calendar_properties_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellSidebar *cal_shell_sidebar; + EShellView *shell_view; + EShellWindow *shell_window; + ESource *source; + ESourceSelector *selector; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (E_IS_SOURCE (source)); + + calendar_setup_edit_calendar (GTK_WINDOW (shell_window), source); +#endif +} + +static void +action_calendar_purge_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_calendar_rename_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellSidebar *cal_shell_sidebar; + ESourceSelector *selector; + + cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + + e_source_selector_edit_primary_selection (selector); +} + +static void +action_calendar_search_cb (GtkRadioAction *action, + GtkRadioAction *current, + ECalShellView *cal_shell_view) +{ + EShellView *shell_view; + EShellContent *shell_content; + const gchar *search_hint; + + /* XXX Figure out a way to handle this in EShellContent + * instead of every shell view having to handle it. + * The problem is EShellContent does not know what + * the search option actions are for this view. It + * would have to dig up the popup menu and retrieve + * the action for each menu item. Seems messy. */ + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + + search_hint = gtk_action_get_label (GTK_ACTION (current)); + e_shell_content_set_search_hint (shell_content, search_hint); +} + +static void +action_calendar_select_one_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellSidebar *cal_shell_sidebar; + ESourceSelector *selector; + ESource *primary; + GSList *list, *iter; + + /* XXX ESourceSelector should provide a function for this. */ + + cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + primary = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (primary != NULL); + + list = e_source_selector_get_selection (selector); + for (iter = list; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + + if (source == primary) + continue; + + e_source_selector_unselect_source (selector, source); + } + e_source_selector_free_selection (list); + + e_source_selector_select_source (selector, primary); +} + +static void +action_calendar_view_cb (GtkRadioAction *action, + GtkRadioAction *current, + ECalShellView *cal_shell_view) +{ + EShellView *shell_view; + GnomeCalendarViewType view_type; + const gchar *view_id; + + shell_view = E_SHELL_VIEW (cal_shell_view); + view_type = gtk_radio_action_get_current_value (action); + + switch (view_type) { + case GNOME_CAL_DAY_VIEW: + view_id = "Day_View"; + break; + + case GNOME_CAL_WORK_WEEK_VIEW: + view_id = "Work_Week_View"; + break; + + case GNOME_CAL_WEEK_VIEW: + view_id = "Week_View"; + break; + + case GNOME_CAL_MONTH_VIEW: + view_id = "Month_View"; + break; + + case GNOME_CAL_LIST_VIEW: + view_id = "List_View"; + break; + + default: + g_return_if_reached (); + } + + e_shell_view_set_view_id (shell_view, view_id); +} + +static void +action_event_all_day_new_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_clipboard_copy_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + e_cal_shell_content_copy_clipboard (cal_shell_content); +} + +static void +action_event_clipboard_cut_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + e_cal_shell_content_cut_clipboard (cal_shell_content); +} + +static void +action_event_clipboard_paste_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + e_cal_shell_content_paste_clipboard (cal_shell_content); +} + +static void +action_event_copy_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_delegate_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_delete_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + e_cal_shell_content_delete_selection (cal_shell_content); +} + +static void +action_event_delete_occurrence_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + e_cal_shell_content_delete_selected_occurrence (cal_shell_content); +} + +static void +action_event_delete_occurrence_all_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + + /* XXX Same as "event-delete". */ + cal_shell_content = cal_shell_view->priv->cal_shell_content; + e_cal_shell_content_delete_selection (cal_shell_content); +} + +static void +action_event_forward_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_meeting_new_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_move_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_new_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_occurrence_movable_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_open_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + GtkWidget *widget; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + widget = gnome_calendar_get_current_view_widget (calendar); + + e_calendar_view_open_event (E_CALENDAR_VIEW (widget)); +#endif +} + +static void +action_event_print_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_reply_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_reply_all_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_save_as_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_schedule_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_gal_save_custom_view_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EShellView *shell_view; + GalViewInstance *view_instance; + + /* All shell views respond to the activation of this action, + * which is defined by EShellWindow. But only the currently + * active shell view proceeds with saving the custom view. */ + shell_view = E_SHELL_VIEW (cal_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + view_instance = e_cal_shell_content_get_view_instance (cal_shell_content); + gal_view_instance_save_as (view_instance); +} + +static void +action_search_execute_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + EShellView *shell_view; + + /* All shell views respond to the activation of this action, + * which is defined by EShellWindow. But only the currently + * active shell view proceeds with executing the search. */ + shell_view = E_SHELL_VIEW (cal_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + e_cal_shell_view_execute_search (cal_shell_view); +} + +static void +action_search_filter_cb (GtkRadioAction *action, + GtkRadioAction *current, + ECalShellView *cal_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + gtk_action_activate (ACTION (SEARCH_EXECUTE)); +} + +static GtkActionEntry calendar_entries[] = { + + { "calendar-copy", + GTK_STOCK_COPY, + N_("_Copy..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_copy_cb) }, + + { "calendar-delete", + GTK_STOCK_DELETE, + NULL, + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_delete_cb) }, + + { "calendar-go-back", + GTK_STOCK_GO_BACK, + N_("Previous"), + NULL, + N_("Go Back"), + G_CALLBACK (action_calendar_go_back_cb) }, + + { "calendar-go-forward", + GTK_STOCK_GO_FORWARD, + N_("Next"), + NULL, + N_("Go Forward"), + G_CALLBACK (action_calendar_go_forward_cb) }, + + { "calendar-go-today", + "go-today", + N_("Select _Today"), + "t", + N_("Select today"), + G_CALLBACK (action_calendar_go_today_cb) }, + + { "calendar-jump-to", + GTK_STOCK_JUMP_TO, + N_("Select _Date"), + "g", + N_("Select a specific date"), + G_CALLBACK (action_calendar_jump_to_cb) }, + + { "calendar-new", + "x-office-calendar", + N_("_New Calendar"), + NULL, + N_("Create a new calendar"), + G_CALLBACK (action_calendar_new_cb) }, + + { "calendar-properties", + GTK_STOCK_PROPERTIES, + NULL, + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_properties_cb) }, + + { "calendar-purge", + NULL, + N_("Purg_e"), + "e", + N_("Purge old appointments and meetings"), + G_CALLBACK (action_calendar_purge_cb) }, + + { "calendar-rename", + NULL, + N_("_Rename..."), + "F2", + N_("Rename the selected calendar"), + G_CALLBACK (action_calendar_rename_cb) }, + + { "calendar-select-one", + "stock_check-filled", + N_("Show _Only This Calendar"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_select_one_cb) }, + + { "event-clipboard-copy", + GTK_STOCK_COPY, + NULL, + NULL, + N_("Copy the selection"), + G_CALLBACK (action_event_clipboard_copy_cb) }, + + { "event-clipboard-cut", + GTK_STOCK_CUT, + NULL, + NULL, + N_("Cut the selection"), + G_CALLBACK (action_event_clipboard_cut_cb) }, + + { "event-clipboard-paste", + GTK_STOCK_PASTE, + NULL, + NULL, + N_("Paste the clipboard"), + G_CALLBACK (action_event_clipboard_paste_cb) }, + + { "event-copy", + NULL, + N_("Cop_y to Calendar..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_copy_cb) }, + + { "event-delegate", + NULL, + N_("_Delegate Meeting..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_delegate_cb) }, + + { "event-delete", + GTK_STOCK_DELETE, + NULL, + NULL, + N_("Delete the appointment"), + G_CALLBACK (action_event_delete_cb) }, + + { "event-delete-occurrence", + GTK_STOCK_DELETE, + N_("Delete This _Occurrence"), + NULL, + N_("Delete this occurrence"), + G_CALLBACK (action_event_delete_occurrence_cb) }, + + { "event-delete-occurrence-all", + GTK_STOCK_DELETE, + N_("Delete _All Occurrences"), + NULL, + N_("Delete all occurrences"), + G_CALLBACK (action_event_delete_occurrence_all_cb) }, + + { "event-all-day-new", + NULL, + N_("New All Day _Event..."), + NULL, + N_("Create a new all day event"), + G_CALLBACK (action_event_all_day_new_cb) }, + + { "event-forward", + "mail-forward", + N_("_Forward as iCalendar..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_forward_cb) }, + + { "event-meeting-new", + NULL, + N_("New _Meeting..."), + NULL, + N_("Create a new meeting"), + G_CALLBACK (action_event_meeting_new_cb) }, + + { "event-move", + NULL, + N_("Mo_ve to Calendar..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_move_cb) }, + + { "event-new", + NULL, + N_("New _Appointment..."), + NULL, + N_("Create a new appointment"), + G_CALLBACK (action_event_new_cb) }, + + { "event-occurrence-movable", + NULL, + N_("Make this Occurrence _Movable"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_occurrence_movable_cb) }, + + { "event-open", + NULL, + N_("_Open Appointment"), + "o", + N_("View the current appointment"), + G_CALLBACK (action_event_open_cb) }, + + { "event-reply", + "mail-reply-sender", + N_("_Reply"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_reply_cb) }, + + { "event-reply-all", + "mail-reply-all", + N_("Reply to _All"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_reply_all_cb) }, + + { "event-save-as", + GTK_STOCK_SAVE_AS, + NULL, + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_save_as_cb) }, + + { "event-schedule", + NULL, + N_("_Schedule Meeting..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_schedule_cb) }, + + /*** Menus ***/ + + { "calendar-actions-menu", + NULL, + N_("_Actions"), + NULL, + NULL, + NULL } +}; + +static EPopupActionEntry calendar_popup_entries[] = { + + /* FIXME No equivalent main menu items for the any of the calendar + * popup menu items and for many of the event popup menu items. + * This is an accessibility issue. */ + + { "calendar-popup-copy", + NULL, + "calendar-copy" }, + + { "calendar-popup-delete", + NULL, + "calendar-delete" }, + + { "calendar-popup-go-today", + NULL, + "calendar-go-today" }, + + { "calendar-popup-jump-to", + NULL, + "calendar-jump-to" }, + + { "calendar-popup-properties", + NULL, + "calendar-properties" }, + + { "calendar-popup-rename", + NULL, + "calendar-rename" }, + + { "calendar-popup-select-one", + NULL, + "calendar-select-one" }, + + { "event-popup-clipboard-copy", + NULL, + "event-clipboard-copy" }, + + { "event-popup-clipboard-cut", + NULL, + "event-clipboard-cut" }, + + { "event-popup-clipboard-paste", + NULL, + "event-clipboard-paste" }, + + { "event-popup-copy", + NULL, + "event-copy" }, + + { "event-popup-delegate", + NULL, + "event-delegate" }, + + { "event-popup-delete", + NULL, + "event-delete" }, + + { "event-popup-delete-occurrence", + NULL, + "event-delete-occurrence" }, + + { "event-popup-delete-occurrence-all", + NULL, + "event-delete-occurrence-all" }, + + { "event-popup-forward", + NULL, + "event-forward" }, + + { "event-popup-move", + NULL, + "event-move" }, + + { "event-popup-occurrence-movable", + NULL, + "event-occurrence-movable" }, + + { "event-popup-open", + NULL, + "event-open" }, + + { "event-popup-reply", + NULL, + "event-reply" }, + + { "event-popup-reply-all", + NULL, + "event-reply-all" }, + + { "event-popup-save-as", + NULL, + "event-save-as" }, + + { "event-popup-schedule", + NULL, + "event-schedule" } +}; + +static GtkRadioActionEntry calendar_view_entries[] = { + + { "calendar-view-day", + "view-calendar-day", + N_("Day"), + NULL, + N_("Show one day"), + GNOME_CAL_DAY_VIEW }, + + { "calendar-view-list", + "view-calendar-list", + N_("List"), + NULL, + N_("Show as list"), + GNOME_CAL_LIST_VIEW }, + + { "calendar-view-month", + "view-calendar-month", + N_("Month"), + NULL, + N_("Show one month"), + GNOME_CAL_MONTH_VIEW }, + + { "calendar-view-week", + "view-calendar-week", + N_("Week"), + NULL, + N_("Show one week"), + GNOME_CAL_WEEK_VIEW }, + + { "calendar-view-workweek", + "view-calendar-workweek", + N_("Work Week"), + NULL, + N_("Show one work week"), + GNOME_CAL_WORK_WEEK_VIEW } +}; + +static GtkRadioActionEntry calendar_filter_entries[] = { + + { "calendar-filter-active-appointments", + NULL, + N_("Active Appointements"), + NULL, + NULL, /* XXX Add a tooltip! */ + CALENDAR_FILTER_ACTIVE_APPOINTMENTS }, + + { "calendar-filter-any-category", + NULL, + N_("Any Category"), + NULL, + NULL, /* XXX Add a tooltip! */ + CALENDAR_FILTER_ANY_CATEGORY }, + + { "calendar-filter-next-7-days-appointments", + NULL, + N_("Next 7 Days' Appointments"), + NULL, + NULL, /* XXX Add a tooltip! */ + CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS }, + + { "calendar-filter-unmatched", + NULL, + N_("Unmatched"), + NULL, + NULL, /* XXX Add a tooltip! */ + CALENDAR_FILTER_UNMATCHED } +}; + +static GtkRadioActionEntry calendar_search_entries[] = { + + { "calendar-search-any-field-contains", + NULL, + N_("Any field contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + CALENDAR_SEARCH_ANY_FIELD_CONTAINS }, + + { "calendar-search-description-contains", + NULL, + N_("Description contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + CALENDAR_SEARCH_DESCRIPTION_CONTAINS }, + + { "calendar-search-summary-contains", + NULL, + N_("Summary contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + CALENDAR_SEARCH_SUMMARY_CONTAINS } +}; + +static GtkActionEntry lockdown_printing_entries[] = { + + { "calendar-print", + GTK_STOCK_PRINT, + NULL, + "p", + N_("Print this calendar"), + G_CALLBACK (action_calendar_print_cb) }, + + { "calendar-print-preview", + GTK_STOCK_PRINT_PREVIEW, + NULL, + NULL, + N_("Preview the calendar to be printed"), + G_CALLBACK (action_calendar_print_preview_cb) }, + + { "event-print", + GTK_STOCK_PRINT, + NULL, + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_print_cb) } +}; + +static EPopupActionEntry lockdown_printing_popup_entries[] = { + + { "event-popup-print", + NULL, + "event-print" } +}; + +void +e_cal_shell_view_actions_init (ECalShellView *cal_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkActionGroup *action_group; + GtkAction *action; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + /* Calendar Actions */ + action_group = ACTION_GROUP (CALENDAR); + gtk_action_group_add_actions ( + action_group, calendar_entries, + G_N_ELEMENTS (calendar_entries), cal_shell_view); + e_action_group_add_popup_actions ( + action_group, calendar_popup_entries, + G_N_ELEMENTS (calendar_popup_entries)); + gtk_action_group_add_radio_actions ( + action_group, calendar_view_entries, + G_N_ELEMENTS (calendar_view_entries), GNOME_CAL_DAY_VIEW, + G_CALLBACK (action_calendar_view_cb), cal_shell_view); + gtk_action_group_add_radio_actions ( + action_group, calendar_search_entries, + G_N_ELEMENTS (calendar_search_entries), + CALENDAR_SEARCH_SUMMARY_CONTAINS, + G_CALLBACK (action_calendar_search_cb), cal_shell_view); + + /* Lockdown Printing Actions */ + action_group = ACTION_GROUP (LOCKDOWN_PRINTING); + gtk_action_group_add_actions ( + action_group, lockdown_printing_entries, + G_N_ELEMENTS (lockdown_printing_entries), cal_shell_view); + e_action_group_add_popup_actions ( + action_group, lockdown_printing_popup_entries, + G_N_ELEMENTS (lockdown_printing_popup_entries)); + + /* Fine tuning. */ + + action = ACTION (CALENDAR_GO_TODAY); + g_object_set (action, "short-label", _("Today"), NULL); + + action = ACTION (CALENDAR_JUMP_TO); + g_object_set (action, "short-label", _("Go To"), NULL); + + action = ACTION (EVENT_DELETE); + g_object_set (action, "short-label", _("Delete"), NULL); + + g_signal_connect ( + ACTION (GAL_SAVE_CUSTOM_VIEW), "activate", + G_CALLBACK (action_gal_save_custom_view_cb), cal_shell_view); + + g_signal_connect ( + ACTION (SEARCH_EXECUTE), "activate", + G_CALLBACK (action_search_execute_cb), cal_shell_view); + + /* Initialize the memo and task pad actions. */ + e_cal_shell_view_memopad_actions_init (cal_shell_view); + e_cal_shell_view_taskpad_actions_init (cal_shell_view); +} + +void +e_cal_shell_view_update_search_filter (ECalShellView *cal_shell_view) +{ + EShellContent *shell_content; + EShellWindow *shell_window; + EShellView *shell_view; + GtkActionGroup *action_group; + GtkRadioAction *radio_action; + GList *list, *iter; + GSList *group; + gint ii; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + action_group = ACTION_GROUP (CALENDAR_FILTER); + e_action_group_remove_all_actions (action_group); + + /* Add the standard filter actions. */ + gtk_action_group_add_radio_actions ( + action_group, calendar_filter_entries, + G_N_ELEMENTS (calendar_filter_entries), + CALENDAR_FILTER_ANY_CATEGORY, + G_CALLBACK (action_search_filter_cb), + cal_shell_view); + + /* Retrieve the radio group from an action we just added. */ + list = gtk_action_group_list_actions (action_group); + radio_action = GTK_RADIO_ACTION (list->data); + group = gtk_radio_action_get_group (radio_action); + g_list_free (list); + + /* Build the category actions. */ + + list = e_categories_get_list (); + for (iter = list, ii = 0; iter != NULL; iter = iter->next, ii++) { + const gchar *category_name = iter->data; + const gchar *filename; + GtkAction *action; + gchar *action_name; + + action_name = g_strdup_printf ( + "calendar-filter-category-%d", ii); + radio_action = gtk_radio_action_new ( + action_name, category_name, NULL, NULL, ii); + g_free (action_name); + + /* Convert the category icon file to a themed icon name. */ + filename = e_categories_get_icon_file_for (category_name); + if (filename != NULL && *filename != '\0') { + gchar *basename; + gchar *cp; + + basename = g_path_get_basename (filename); + + /* Lose the file extension. */ + if ((cp = strrchr (basename, '.')) != NULL) + *cp = '\0'; + + g_object_set ( + radio_action, "icon-name", basename, NULL); + + g_free (basename); + } + + gtk_radio_action_set_group (radio_action, group); + group = gtk_radio_action_get_group (radio_action); + + /* The action group takes ownership of the action. */ + action = GTK_ACTION (radio_action); + gtk_action_group_add_action (action_group, action); + g_object_unref (radio_action); + } + g_list_free (list); + + /* Use any action in the group; doesn't matter which. */ + e_shell_content_set_filter_action (shell_content, radio_action); + + ii = CALENDAR_FILTER_UNMATCHED; + e_shell_content_add_filter_separator_after (shell_content, ii); + + ii = CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS; + e_shell_content_add_filter_separator_after (shell_content, ii); +} diff --git a/modules/calendar/e-cal-shell-view-actions.h b/modules/calendar/e-cal-shell-view-actions.h new file mode 100644 index 0000000000..b02906f179 --- /dev/null +++ b/modules/calendar/e-cal-shell-view-actions.h @@ -0,0 +1,153 @@ +/* + * e-cal-shell-view-actions.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_SHELL_VIEW_ACTIONS_H +#define E_CAL_SHELL_VIEW_ACTIONS_H + +#include + +/* Calendar Actions */ +#define E_SHELL_WINDOW_ACTION_CALENDAR_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-copy") +#define E_SHELL_WINDOW_ACTION_CALENDAR_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-delete") +#define E_SHELL_WINDOW_ACTION_CALENDAR_GO_BACK(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-go-back") +#define E_SHELL_WINDOW_ACTION_CALENDAR_GO_FORWARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-go-forward") +#define E_SHELL_WINDOW_ACTION_CALENDAR_GO_TODAY(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-go-today") +#define E_SHELL_WINDOW_ACTION_CALENDAR_JUMP_TO(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-jump-to") +#define E_SHELL_WINDOW_ACTION_CALENDAR_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-new") +#define E_SHELL_WINDOW_ACTION_CALENDAR_PRINT(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-print") +#define E_SHELL_WINDOW_ACTION_CALENDAR_PRINT_PREVIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-print-preview") +#define E_SHELL_WINDOW_ACTION_CALENDAR_PROPERTIES(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-properties") +#define E_SHELL_WINDOW_ACTION_CALENDAR_PURGE(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-purge") +#define E_SHELL_WINDOW_ACTION_CALENDAR_RENAME(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-rename") +#define E_SHELL_WINDOW_ACTION_CALENDAR_SELECT_ONE(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-select-one") +#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_DAY(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-view-day") +#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_LIST(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-view-list") +#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_MONTH(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-view-month") +#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_WEEK(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-view-week") +#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_WORKWEEK(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-view-workweek") + +/* Event Actions */ +#define E_SHELL_WINDOW_ACTION_EVENT_CLIPBOARD_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "event-clipboard-copy") +#define E_SHELL_WINDOW_ACTION_EVENT_CLIPBOARD_CUT(window) \ + E_SHELL_WINDOW_ACTION ((window), "event-clipboard-cut") +#define E_SHELL_WINDOW_ACTION_EVENT_CLIPBOARD_PASTE(window) \ + E_SHELL_WINDOW_ACTION ((window), "event-clipboard-paste") +#define E_SHELL_WINDOW_ACTION_EVENT_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "event-delete") +#define E_SHELL_WINDOW_ACTION_EVENT_DELETE_OCCURRENCE(window) \ + E_SHELL_WINDOW_ACTION ((window), "event-delete-occurrence") +#define E_SHELL_WINDOW_ACTION_EVENT_DELETE_OCCURRENCE_ALL(window) \ + E_SHELL_WINDOW_ACTION ((window), "event-delete-occurrence-all") +#define E_SHELL_WINDOW_ACTION_EVENT_OPEN(window) \ + E_SHELL_WINDOW_ACTION ((window), "event-open") + +/* Memo Pad Actions */ +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_CLIPBOARD_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-clipboard-copy") +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_CLIPBOARD_CUT(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-clipboard-cut") +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_CLIPBOARD_PASTE(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-clipboard-paste") +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-delete") +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_FORWARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-forward") +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-new") +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_OPEN(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-open") +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_OPEN_URL(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-open-url") +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_PRINT(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-print") +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_SAVE_AS(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-save-as") + +/* Task Pad Actions */ +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_ASSIGN(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-assign") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_CLIPBOARD_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-clipboard-copy") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_CLIPBOARD_CUT(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-clipboard-cut") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_CLIPBOARD_PASTE(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-clipboard-paste") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-delete") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_FORWARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-forward") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_MARK_COMPLETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-mark-complete") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_MARK_INCOMPLETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-mark-incomplete") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-new") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_OPEN(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-open") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_OPEN_URL(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-open-url") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_PRINT(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-print") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_SAVE_AS(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-save-as") + +/* Calendar Query Actions */ +#define E_SHELL_WINDOW_ACTION_CALENDAR_FILTER_ACTIVE_APPOINTMENTS(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-filter-active-appointments") +#define E_SHELL_WINDOW_ACTION_CALENDAR_FILTER_ANY_CATEGORY(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-filter-any-category") +#define E_SHELL_WINDOW_ACTION_CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-filter-next-7-days-appointments") +#define E_SHELL_WINDOW_ACTION_CALENDAR_FILTER_UNMATCHED(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-filter-unmatched") +#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_ANY_FIELD_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-search-any-field-contains") +#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_DESCRIPTION_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-search-description-contains") +#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_SUMMARY_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-search-summary-contains") + +/* Action Groups */ +#define E_SHELL_WINDOW_ACTION_GROUP_CALENDAR(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "calendar") +#define E_SHELL_WINDOW_ACTION_GROUP_CALENDAR_FILTER(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "calendar-filter") + +#endif /* E_CAL_SHELL_VIEW_ACTIONS_H */ diff --git a/modules/calendar/e-cal-shell-view-memopad.c b/modules/calendar/e-cal-shell-view-memopad.c new file mode 100644 index 0000000000..ecee72d8b5 --- /dev/null +++ b/modules/calendar/e-cal-shell-view-memopad.c @@ -0,0 +1,526 @@ +/* + * e-cal-shell-view-memopad.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-view-private.h" + +/* Much of this file is based on e-memo-shell-view-actions.c. */ + +static void +action_calendar_memopad_clipboard_copy_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + e_memo_table_copy_clipboard (memo_table); +} + +static void +action_calendar_memopad_clipboard_cut_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + e_memo_table_cut_clipboard (memo_table); +} + +static void +action_calendar_memopad_clipboard_paste_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + e_memo_table_paste_clipboard (memo_table); +} + +static void +action_calendar_memopad_delete_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + e_cal_shell_view_memopad_set_status_message ( + cal_shell_view, _("Deleting selected memos..."), -1.0); + e_memo_table_delete_selected (memo_table); + e_cal_shell_view_memopad_set_status_message ( + cal_shell_view, NULL, -1.0); +} + +static void +action_calendar_memopad_forward_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + ECalComponent *comp; + icalcomponent *clone; + GSList *list; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only forward the first selected memo. */ + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_component_set_icalcomponent (comp, clone); + itip_send_comp ( + E_CAL_COMPONENT_METHOD_PUBLISH, comp, + comp_data->client, NULL, NULL, NULL, TRUE); + g_object_unref (comp); +} + +static void +action_calendar_memopad_new_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + ECal *client; + ECalComponent *comp; + CompEditor *editor; + GSList *list; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + client = comp_data->client; + editor = memo_editor_new (client, shell, COMP_EDITOR_NEW_ITEM); + comp = cal_comp_memo_new_with_defaults (client); + comp_editor_edit_comp (editor, comp); + + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (comp); + g_object_unref (client); +} + +static void +action_calendar_memopad_open_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + GSList *list; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only open the first selected memo. */ + e_cal_shell_view_memopad_open_memo (cal_shell_view, comp_data); +} + +static void +action_calendar_memopad_open_url_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + icalproperty *prop; + const gchar *uri; + GSList *list; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only open the URI of the first selected memo. */ + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_URL_PROPERTY); + g_return_if_fail (prop == NULL); + + uri = icalproperty_get_url (prop); + e_show_uri (GTK_WINDOW (shell_window), uri); +} + +static void +action_calendar_memopad_print_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + ECalComponent *comp; + icalcomponent *clone; + GtkPrintOperationAction print_action; + GSList *list; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only print the first selected memo. */ + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; + e_cal_component_set_icalcomponent (comp, clone); + print_comp (comp, comp_data->client, print_action); + g_object_unref (comp); +} + +static void +action_calendar_memopad_save_as_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + GSList *list; + gchar *filename; + gchar *string; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + filename = e_file_dialog_save (_("Save as..."), NULL); + if (filename == NULL) + return; + + /* XXX We only save the first selected memo. */ + string = e_cal_get_component_as_string ( + comp_data->client, comp_data->icalcomp); + if (string == NULL) { + g_warning ("Could not convert memo to a string."); + return; + } + + e_write_file_uri (filename, string); + + g_free (filename); + g_free (string); +} + +static GtkActionEntry calendar_memopad_entries[] = { + + { "calendar-memopad-clipboard-copy", + GTK_STOCK_COPY, + NULL, + NULL, + N_("Copy selected memo"), + G_CALLBACK (action_calendar_memopad_clipboard_copy_cb) }, + + { "calendar-memopad-clipboard-cut", + GTK_STOCK_CUT, + NULL, + NULL, + N_("Cut selected memo"), + G_CALLBACK (action_calendar_memopad_clipboard_cut_cb) }, + + { "calendar-memopad-clipboard-paste", + GTK_STOCK_PASTE, + NULL, + NULL, + N_("Paste memo from the clipboard"), + G_CALLBACK (action_calendar_memopad_clipboard_paste_cb) }, + + { "calendar-memopad-delete", + GTK_STOCK_DELETE, + N_("_Delete Memo"), + NULL, + N_("Delete selected memos"), + G_CALLBACK (action_calendar_memopad_delete_cb) }, + + { "calendar-memopad-forward", + "mail-forward", + N_("_Forward as iCalendar..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_memopad_forward_cb) }, + + { "calendar-memopad-new", + "stock_insert-note", + N_("New _Memo"), + NULL, + N_("Create a new memo"), + G_CALLBACK (action_calendar_memopad_new_cb) }, + + { "calendar-memopad-open", + GTK_STOCK_OPEN, + N_("_Open Memo"), + NULL, + N_("View the selected memo"), + G_CALLBACK (action_calendar_memopad_open_cb) }, + + { "calendar-memopad-open-url", + "applications-internet", + N_("Open _Web Page"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_memopad_open_url_cb) }, + + { "calendar-memopad-save-as", + GTK_STOCK_SAVE_AS, + NULL, + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_memopad_save_as_cb) } +}; + +static GtkActionEntry lockdown_printing_entries[] = { + + { "calendar-memopad-print", + GTK_STOCK_PRINT, + NULL, + NULL, + N_("Print the selected memo"), + G_CALLBACK (action_calendar_memopad_print_cb) } +}; + +void +e_cal_shell_view_memopad_actions_init (ECalShellView *cal_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkActionGroup *action_group; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + /* Calendar Actions */ + action_group = ACTION_GROUP (CALENDAR); + gtk_action_group_add_actions ( + action_group, calendar_memopad_entries, + G_N_ELEMENTS (calendar_memopad_entries), cal_shell_view); + + /* Lockdown Printing Actions */ + action_group = ACTION_GROUP (LOCKDOWN_PRINTING); + gtk_action_group_add_actions ( + action_group, lockdown_printing_entries, + G_N_ELEMENTS (lockdown_printing_entries), cal_shell_view); +} + +void +e_cal_shell_view_memopad_actions_update (ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EShellWindow *shell_window; + EShellView *shell_view; + EMemoTable *memo_table; + ETable *table; + GtkAction *action; + GSList *list, *iter; + const gchar *label; + gboolean editable = TRUE; + gboolean has_url = FALSE; + gboolean sensitive; + gint n_selected; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + table = e_memo_table_get_table (memo_table); + n_selected = e_table_selected_count (table); + + list = e_memo_table_get_selected (memo_table); + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + icalproperty *prop; + gboolean read_only; + + e_cal_is_read_only (comp_data->client, &read_only, NULL); + editable &= !read_only; + + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_URL_PROPERTY); + has_url |= (prop != NULL); + } + g_slist_free (list); + + action = ACTION (CALENDAR_MEMOPAD_CLIPBOARD_COPY); + sensitive = (n_selected > 0); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_MEMOPAD_CLIPBOARD_CUT); + sensitive = (n_selected > 0) && editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_MEMOPAD_CLIPBOARD_PASTE); + sensitive = editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_MEMOPAD_DELETE); + sensitive = (n_selected > 0) && editable; + gtk_action_set_sensitive (action, sensitive); + label = ngettext ("Delete Memo", "Delete Memos", n_selected); + g_object_set (action, "label", label, NULL); + + action = ACTION (CALENDAR_MEMOPAD_FORWARD); + sensitive = (n_selected == 1); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_MEMOPAD_OPEN); + sensitive = (n_selected == 1); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_MEMOPAD_OPEN_URL); + sensitive = (n_selected == 1) && has_url; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_MEMOPAD_PRINT); + sensitive = (n_selected == 1); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_MEMOPAD_SAVE_AS); + sensitive = (n_selected == 1); + gtk_action_set_sensitive (action, sensitive); +} + +void +e_cal_shell_view_memopad_open_memo (ECalShellView *cal_shell_view, + ECalModelComponent *comp_data) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + CompEditor *editor; + CompEditorFlags flags = 0; + ECalComponent *comp; + icalcomponent *clone; + const gchar *uid; + + g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); + g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data)); + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + + uid = icalcomponent_get_uid (comp_data->icalcomp); + editor = comp_editor_find_instance (uid); + + if (editor != NULL) + goto exit; + + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_component_set_icalcomponent (comp, clone); + + if (e_cal_component_has_organizer (comp)) + flags |= COMP_EDITOR_IS_SHARED; + + if (itip_organizer_is_user (comp, comp_data->client)) + flags |= COMP_EDITOR_USER_ORG; + + editor = memo_editor_new (comp_data->client, shell, flags); + comp_editor_edit_comp (editor, comp); + + g_object_unref (comp); + +exit: + gtk_window_present (GTK_WINDOW (editor)); +} + +void +e_cal_shell_view_memopad_set_status_message (ECalShellView *cal_shell_view, + const gchar *status_message, + gdouble percent) +{ + EActivity *activity; + EShellView *shell_view; + EShellBackend *shell_backend; + + g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + activity = cal_shell_view->priv->memopad_activity; + + if (status_message == NULL || *status_message == '\0') { + if (activity != NULL) { + e_activity_complete (activity); + g_object_unref (activity); + activity = NULL; + } + + } else if (activity == NULL) { + activity = e_activity_new (status_message); + e_activity_set_percent (activity, percent); + e_shell_backend_add_activity (shell_backend, activity); + + } else { + e_activity_set_percent (activity, percent); + e_activity_set_primary_text (activity, status_message); + } + + cal_shell_view->priv->memopad_activity = activity; +} diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c new file mode 100644 index 0000000000..f681a2c2f3 --- /dev/null +++ b/modules/calendar/e-cal-shell-view-private.c @@ -0,0 +1,650 @@ +/* + * e-cal-shell-view-private.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-view-private.h" + +#include "calendar/gui/calendar-view-factory.h" +#include "widgets/menus/gal-view-factory-etable.h" + +static void +cal_shell_view_process_completed_tasks (ECalShellView *cal_shell_view, + gboolean config_changed) +{ +#if 0 + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + e_calendar_table_process_completed_tasks ( + task_table, clients, config_changed); +#endif +} + +static void +cal_shell_view_config_timezone_changed_cb (GConfClient *client, + guint id, + GConfEntry *entry, + gpointer user_data) +{ + ECalShellView *cal_shell_view = user_data; + + e_cal_shell_view_update_timezone (cal_shell_view); +} + +static struct tm +cal_shell_view_get_current_time (ECalendarItem *calitem, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + struct icaltimetype tt; + icaltimezone *timezone; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + timezone = e_cal_shell_content_get_timezone (cal_shell_content); + + tt = icaltime_from_timet_with_zone (time (NULL), FALSE, timezone); + + return icaltimetype_to_tm (&tt); +} + +static void +cal_shell_view_mini_calendar_date_range_changed_cb (ECalShellView *cal_shell_view, + ECalendarItem *calitem) +{ + /* FIXME gnome-calendar.c calls update_query() here. */ +} + +static void +cal_shell_view_mini_calendar_selection_changed_cb (ECalShellView *cal_shell_view, + ECalendarItem *calitem) +{ + /* FIXME */ +} + +static void +cal_shell_view_mini_calendar_scroll_event_cb (ECalShellView *cal_shell_view, + GdkEventScroll *event, + ECalendar *mini_calendar) +{ + ECalendarItem *calitem; + GDate start_date, end_date; + + calitem = mini_calendar->calitem; + if (!e_calendar_item_get_selection (calitem, &start_date, &end_date)) + return; + + switch (event->direction) { + case GDK_SCROLL_UP: + g_date_subtract_months (&start_date, 1); + g_date_subtract_months (&end_date, 1); + break; + + case GDK_SCROLL_DOWN: + g_date_add_months (&start_date, 1); + g_date_add_months (&end_date, 1); + break; + + default: + g_return_if_reached (); + } + + /* XXX Does ECalendarItem emit a signal for this? If so, maybe + * we could move this handler into ECalShellSidebar. */ + e_calendar_item_set_selection (calitem, &start_date, &end_date); + + cal_shell_view_mini_calendar_date_range_changed_cb ( + cal_shell_view, calitem); +} + +static gboolean +cal_shell_view_selector_popup_event_cb (EShellView *shell_view, + ESource *primary_source, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/calendar-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); + + return TRUE; +} + +static void +cal_shell_view_memopad_popup_event_cb (EShellView *shell_view, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/calendar-memopad-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); +} + +static void +cal_shell_view_taskpad_popup_event_cb (EShellView *shell_view, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/calendar-taskpad-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); +} + +static void +cal_shell_view_load_view_collection (EShellViewClass *shell_view_class) +{ + GalViewCollection *collection; + GalViewFactory *factory; + ETableSpecification *spec; + const gchar *base_dir; + gchar *filename; + + collection = shell_view_class->view_collection; + + base_dir = EVOLUTION_ETSPECDIR; + spec = e_table_specification_new (); + filename = g_build_filename (base_dir, ETSPEC_FILENAME, NULL); + if (!e_table_specification_load_from_file (spec, filename)) + g_critical ("Unable to load ETable specification file " + "for calendars"); + g_free (filename); + + factory = calendar_view_factory_new (GNOME_CAL_DAY_VIEW); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + + factory = calendar_view_factory_new (GNOME_CAL_WORK_WEEK_VIEW); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + + factory = calendar_view_factory_new (GNOME_CAL_WEEK_VIEW); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + + factory = calendar_view_factory_new (GNOME_CAL_MONTH_VIEW); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + + factory = gal_view_factory_etable_new (spec); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + g_object_unref (spec); + + gal_view_collection_load (collection); +} + +static void +cal_shell_view_notify_view_id_cb (ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + GalViewInstance *view_instance; + const gchar *view_id; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + view_instance = + e_cal_shell_content_get_view_instance (cal_shell_content); + view_id = e_shell_view_get_view_id (E_SHELL_VIEW (cal_shell_view)); + + /* A NULL view ID implies we're in a custom view. But you can + * only get to a custom view via the "Define Views" dialog, which + * would have already modified the view instance appropriately. + * Furthermore, there's no way to refer to a custom view by ID + * anyway, since custom views have no IDs. */ + if (view_id == NULL) + return; + + gal_view_instance_set_current_view_id (view_instance, view_id); +} + +void +e_cal_shell_view_private_init (ECalShellView *cal_shell_view, + EShellViewClass *shell_view_class) +{ + if (!gal_view_collection_loaded (shell_view_class->view_collection)) + cal_shell_view_load_view_collection (shell_view_class); + + g_signal_connect ( + cal_shell_view, "notify::view-id", + G_CALLBACK (cal_shell_view_notify_view_id_cb), NULL); +} + +void +e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) +{ + ECalShellViewPrivate *priv = cal_shell_view->priv; + ECalShellContent *cal_shell_content; + ECalShellSidebar *cal_shell_sidebar; + EShellBackend *shell_backend; + EShellContent *shell_content; + EShellSidebar *shell_sidebar; + EShellWindow *shell_window; + EShellView *shell_view; + GnomeCalendar *calendar; + ECalendar *mini_calendar; + EMemoTable *memo_table; + ECalendarTable *task_table; + ESourceSelector *selector; + guint id; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + e_shell_window_add_action_group (shell_window, "calendar"); + e_shell_window_add_action_group (shell_window, "calendar-filter"); + + /* Cache these to avoid lots of awkward casting. */ + priv->cal_shell_backend = g_object_ref (shell_backend); + priv->cal_shell_content = g_object_ref (shell_content); + priv->cal_shell_sidebar = g_object_ref (shell_sidebar); + + cal_shell_content = E_CAL_SHELL_CONTENT (shell_content); + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + cal_shell_sidebar = E_CAL_SHELL_SIDEBAR (shell_sidebar); + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + mini_calendar = e_cal_shell_sidebar_get_mini_calendar (cal_shell_sidebar); + + e_calendar_item_set_get_time_callback ( + mini_calendar->calitem, (ECalendarItemGetTimeCallback) + cal_shell_view_get_current_time, cal_shell_view, NULL); + +#if 0 /* KILL-BONOBO */ + g_signal_connect_swapped ( + calendar, "dates-shown-changed", + G_CALLBACK (e_cal_shell_view_update_sidebar), + cal_shell_view); +#endif + + g_signal_connect_swapped ( + mini_calendar, "scroll-event", + G_CALLBACK (cal_shell_view_mini_calendar_scroll_event_cb), + cal_shell_view); + + g_signal_connect_swapped ( + mini_calendar->calitem, "date-range-changed", + G_CALLBACK (cal_shell_view_mini_calendar_date_range_changed_cb), + cal_shell_view); + + g_signal_connect_swapped ( + mini_calendar->calitem, "selection-changed", + G_CALLBACK (cal_shell_view_mini_calendar_selection_changed_cb), + cal_shell_view); + + g_signal_connect_swapped ( + selector, "popup-event", + G_CALLBACK (cal_shell_view_selector_popup_event_cb), + cal_shell_view); + + g_signal_connect_swapped ( + memo_table, "popup-event", + G_CALLBACK (cal_shell_view_memopad_popup_event_cb), + cal_shell_view); + + g_signal_connect_swapped ( + memo_table, "status-message", + G_CALLBACK (e_cal_shell_view_memopad_set_status_message), + cal_shell_view); + + g_signal_connect_swapped ( + task_table, "popup-event", + G_CALLBACK (cal_shell_view_taskpad_popup_event_cb), + cal_shell_view); + + g_signal_connect_swapped ( + task_table, "status-message", + G_CALLBACK (e_cal_shell_view_taskpad_set_status_message), + cal_shell_view); + + g_signal_connect_swapped ( + e_memo_table_get_table (memo_table), "selection-change", + G_CALLBACK (e_cal_shell_view_memopad_actions_update), + cal_shell_view); + + g_signal_connect_swapped ( + e_calendar_table_get_table (task_table), "selection-change", + G_CALLBACK (e_cal_shell_view_taskpad_actions_update), + cal_shell_view); + + e_categories_register_change_listener ( + G_CALLBACK (e_cal_shell_view_update_search_filter), + cal_shell_view); + + /* Listen for configuration changes. */ + + /* Timezone */ + id = calendar_config_add_notification_timezone ( + cal_shell_view_config_timezone_changed_cb, cal_shell_view); + priv->notifications = g_list_prepend ( + priv->notifications, GUINT_TO_POINTER (id)); + + e_cal_shell_view_actions_init (cal_shell_view); + e_cal_shell_view_update_sidebar (cal_shell_view); + e_cal_shell_view_update_search_filter (cal_shell_view); + e_cal_shell_view_update_timezone (cal_shell_view); +} + +void +e_cal_shell_view_private_dispose (ECalShellView *cal_shell_view) +{ + ECalShellViewPrivate *priv = cal_shell_view->priv; + GList *iter; + + DISPOSE (priv->cal_shell_backend); + DISPOSE (priv->cal_shell_content); + DISPOSE (priv->cal_shell_sidebar); + + if (priv->calendar_activity != NULL) { + /* XXX Activity is not cancellable. */ + e_activity_complete (priv->calendar_activity); + g_object_unref (priv->calendar_activity); + priv->calendar_activity = NULL; + } + + if (priv->memopad_activity != NULL) { + /* XXX Activity is not cancellable. */ + e_activity_complete (priv->memopad_activity); + g_object_unref (priv->memopad_activity); + priv->memopad_activity = NULL; + } + + if (priv->taskpad_activity != NULL) { + /* XXX Activity is not cancellable. */ + e_activity_complete (priv->taskpad_activity); + g_object_unref (priv->taskpad_activity); + priv->taskpad_activity = NULL; + } + + for (iter = priv->notifications; iter != NULL; iter = iter->next) { + guint notification_id = GPOINTER_TO_UINT (iter->data); + calendar_config_remove_notification (notification_id); + } + g_list_free (priv->notifications); + priv->notifications = NULL; +} + +void +e_cal_shell_view_private_finalize (ECalShellView *cal_shell_view) +{ + /* XXX Nothing to do? */ +} + +void +e_cal_shell_view_execute_search (ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +void +e_cal_shell_view_open_event (ECalShellView *cal_shell_view, + ECalModelComponent *comp_data) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + CompEditor *editor; + CompEditorFlags flags = 0; + ECalComponent *comp; + icalcomponent *clone; + icalproperty *prop; + const gchar *uid; + + g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); + g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data)); + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + + uid = icalcomponent_get_uid (comp_data->icalcomp); + editor = comp_editor_find_instance (uid); + + if (editor != NULL) + goto exit; + + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_component_set_icalcomponent (comp, clone); + + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_ATTENDEE_PROPERTY); + if (prop != NULL) + flags |= COMP_EDITOR_MEETING; + + if (itip_organizer_is_user (comp, comp_data->client)) + flags |= COMP_EDITOR_USER_ORG; + + if (itip_sentby_is_user (comp, comp_data->client)) + flags |= COMP_EDITOR_USER_ORG; + + if (!e_cal_component_has_attendees (comp)) + flags |= COMP_EDITOR_USER_ORG; + + editor = event_editor_new (comp_data->client, shell, flags); + comp_editor_edit_comp (editor, comp); + + g_object_ref (comp); + +exit: + gtk_window_present (GTK_WINDOW (editor)); +} + +void +e_cal_shell_view_set_status_message (ECalShellView *cal_shell_view, + const gchar *status_message, + gdouble percent) +{ + EActivity *activity; + EShellView *shell_view; + EShellBackend *shell_backend; + + g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + activity = cal_shell_view->priv->calendar_activity; + + if (status_message == NULL || *status_message == '\0') { + if (activity != NULL) { + e_activity_complete (activity); + g_object_unref (activity); + activity = NULL; + } + + } else if (activity == NULL) { + activity = e_activity_new (status_message); + e_activity_set_percent (activity, percent); + e_shell_backend_add_activity (shell_backend, activity); + + } else { + e_activity_set_percent (activity, percent); + e_activity_set_primary_text (activity, status_message); + } + + cal_shell_view->priv->calendar_activity = activity; +} + +void +e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view) +{ +#if 0 /* KILL-BONOBO */ + EShellView *shell_view; + EShellSidebar *shell_sidebar; + GnomeCalendar *calendar; + GnomeCalendarViewType view; + time_t start_time, end_time; + struct tm start_tm, end_tm; + struct icaltimetype start_tt, end_tt; + icaltimezone *timezone; + gchar buffer[512]; + gchar end_buffer[512]; + + g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + + calendar = e_cal_shell_view_get_calendar (cal_shell_view); + + gnome_calendar_get_visible_time_range ( + calendar, &start_time, &end_time); + timezone = gnome_calendar_get_timezone (calendar); + view = gnome_calendar_get_view (calendar); + + start_tt = icaltime_from_timet_with_zone (start_time, FALSE, timezone); + start_tm.tm_year = start_tt.year - 1900; + start_tm.tm_mon = start_tt.month - 1; + start_tm.tm_mday = start_tt.day; + start_tm.tm_hour = start_tt.hour; + start_tm.tm_min = start_tt.minute; + start_tm.tm_sec = start_tt.second; + start_tm.tm_isdst = -1; + start_tm.tm_wday = time_day_of_week ( + start_tt.day, start_tt.month - 1, start_tt.year); + + /* Subtract one from end_time so we don't get an extra day. */ + end_tt = icaltime_from_timet_with_zone (end_time - 1, FALSE, timezone); + end_tm.tm_year = end_tt.year - 1900; + end_tm.tm_mon = end_tt.month - 1; + end_tm.tm_mday = end_tt.day; + end_tm.tm_hour = end_tt.hour; + end_tm.tm_min = end_tt.minute; + end_tm.tm_sec = end_tt.second; + end_tm.tm_isdst = -1; + end_tm.tm_wday = time_day_of_week ( + end_tt.day, end_tt.month - 1, end_tt.year); + + switch (view) { + case GNOME_CAL_DAY_VIEW: + case GNOME_CAL_WORK_WEEK_VIEW: + case GNOME_CAL_WEEK_VIEW: + if (start_tm.tm_year == end_tm.tm_year && + start_tm.tm_mon == end_tm.tm_mon && + start_tm.tm_mday == end_tm.tm_mday) { + e_utf8_strftime ( + buffer, sizeof (buffer), + _("%A %d %b %Y"), &start_tm); + } else if (start_tm.tm_year == end_tm.tm_year) { + e_utf8_strftime ( + buffer, sizeof (buffer), + _("%a %d %b"), &start_tm); + e_utf8_strftime ( + end_buffer, sizeof (end_buffer), + _("%a %d %b %Y"), &end_tm); + strcat (buffer, " - "); + strcat (buffer, end_buffer); + } else { + e_utf8_strftime ( + buffer, sizeof (buffer), + _("%a %d %b %Y"), &start_tm); + e_utf8_strftime ( + end_buffer, sizeof (end_buffer), + _("%a %d %b %Y"), &end_tm); + strcat (buffer, " - "); + strcat (buffer, end_buffer); + } + break; + + case GNOME_CAL_MONTH_VIEW: + case GNOME_CAL_LIST_VIEW: + if (start_tm.tm_year == end_tm.tm_year) { + if (start_tm.tm_mon == end_tm.tm_mon) { + e_utf8_strftime ( + buffer, + sizeof (buffer), + "%d", &start_tm); + e_utf8_strftime ( + end_buffer, + sizeof (end_buffer), + _("%d %b %Y"), &end_tm); + strcat (buffer, " - "); + strcat (buffer, end_buffer); + } else { + e_utf8_strftime ( + buffer, + sizeof (buffer), + _("%d %b"), &start_tm); + e_utf8_strftime ( + end_buffer, + sizeof (end_buffer), + _("%d %b %Y"), &end_tm); + strcat (buffer, " - "); + strcat (buffer, end_buffer); + } + } else { + e_utf8_strftime ( + buffer, sizeof (buffer), + _("%d %b %Y"), &start_tm); + e_utf8_strftime ( + end_buffer, sizeof (end_buffer), + _("%d %b %Y"), &end_tm); + strcat (buffer, " - "); + strcat (buffer, end_buffer); + } + break; + + default: + g_return_if_reached (); + } + + e_shell_sidebar_set_secondary_text (shell_sidebar, buffer); +#endif +} + +void +e_cal_shell_view_update_timezone (ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellContent *cal_shell_content; + ECalShellSidebar *cal_shell_sidebar; + GnomeCalendarViewType view_type; + ECalendarView *calendar_view; + icaltimezone *timezone; + GList *clients, *iter; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + view_type = e_cal_shell_content_get_current_view (cal_shell_content); + calendar_view = e_cal_shell_content_get_calendar_view ( + cal_shell_content, view_type); + + cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; + clients = e_cal_shell_sidebar_get_clients (cal_shell_sidebar); + + timezone = calendar_config_get_icaltimezone (); + + for (iter = clients; iter != NULL; iter = iter->next) { + ECal *client = iter->data; + + if (e_cal_get_load_state (client) == E_CAL_LOAD_LOADED) + e_cal_set_default_timezone (client, timezone, NULL); + } + + e_calendar_view_set_icaltimezone (calendar_view, timezone); + + g_list_free (clients); +#endif +} diff --git a/modules/calendar/e-cal-shell-view-private.h b/modules/calendar/e-cal-shell-view-private.h new file mode 100644 index 0000000000..8308e0bf7f --- /dev/null +++ b/modules/calendar/e-cal-shell-view-private.h @@ -0,0 +1,170 @@ +/* + * e-cal-shell-view-private.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_SHELL_VIEW_PRIVATE_H +#define E_CAL_SHELL_VIEW_PRIVATE_H + +#include "e-cal-shell-view.h" + +#include +#include +#include +#include +#include + +#include "e-util/e-util.h" +#include "e-util/e-dialog-utils.h" +#include "widgets/misc/e-popup-action.h" + +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/comp-util.h" +#include "calendar/gui/e-cal-list-view.h" +#include "calendar/gui/e-cal-model-tasks.h" +#include "calendar/gui/e-calendar-view.h" +#include "calendar/gui/gnome-cal.h" +/*#include "calendar/gui/goto.h"*/ +#include "calendar/gui/print.h" +#include "calendar/gui/dialogs/copy-source-dialog.h" +#include "calendar/gui/dialogs/event-editor.h" +#include "calendar/gui/dialogs/memo-editor.h" +#include "calendar/gui/dialogs/task-editor.h" + +#include "e-cal-shell-backend.h" +#include "e-cal-shell-content.h" +#include "e-cal-shell-sidebar.h" +#include "e-cal-shell-view-actions.h" + +#define E_CAL_SHELL_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_CAL_SHELL_VIEW, ECalShellViewPrivate)) + +/* Shorthand, requires a variable named "shell_window". */ +#define ACTION(name) \ + (E_SHELL_WINDOW_ACTION_##name (shell_window)) +#define ACTION_GROUP(name) \ + (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) + +/* For use in dispose() methods. */ +#define DISPOSE(obj) \ + G_STMT_START { \ + if ((obj) != NULL) { g_object_unref (obj); (obj) = NULL; } \ + } G_STMT_END + +/* ETable Specifications */ +#define ETSPEC_FILENAME "e-calendar-table.etspec" + +G_BEGIN_DECLS + +/* Filter items are displayed in ascending order. + * Non-negative values are reserved for categories. */ +enum { + CALENDAR_FILTER_ANY_CATEGORY = -4, + CALENDAR_FILTER_UNMATCHED = -3, + CALENDAR_FILTER_ACTIVE_APPOINTMENTS = -2, + CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS = -1 +}; + +/* Search items are displayed in ascending order. */ +enum { + CALENDAR_SEARCH_SUMMARY_CONTAINS, + CALENDAR_SEARCH_DESCRIPTION_CONTAINS, + CALENDAR_SEARCH_ANY_FIELD_CONTAINS +}; + +struct _ECalShellViewPrivate { + + /* These are just for convenience. */ + ECalShellBackend *cal_shell_backend; + ECalShellContent *cal_shell_content; + ECalShellSidebar *cal_shell_sidebar; + + /* The last time explicitly selected by the user. */ + time_t base_view_time; + + EActivity *calendar_activity; + EActivity *memopad_activity; + EActivity *taskpad_activity; + + /* GConf notification IDs */ + GList *notifications; +}; + +void e_cal_shell_view_private_init + (ECalShellView *cal_shell_view, + EShellViewClass *shell_view_class); +void e_cal_shell_view_private_constructed + (ECalShellView *cal_shell_view); +void e_cal_shell_view_private_dispose + (ECalShellView *cal_shell_view); +void e_cal_shell_view_private_finalize + (ECalShellView *cal_shell_view); + +/* Private Utilities */ + +void e_cal_shell_view_actions_init + (ECalShellView *cal_shell_view); +void e_cal_shell_view_execute_search + (ECalShellView *cal_shell_view); +void e_cal_shell_view_open_event + (ECalShellView *cal_shell_view, + ECalModelComponent *comp_data); +void e_cal_shell_view_set_status_message + (ECalShellView *cal_shell_view, + const gchar *status_message, + gdouble percent); +void e_cal_shell_view_update_sidebar + (ECalShellView *cal_shell_view); +void e_cal_shell_view_update_search_filter + (ECalShellView *cal_shell_view); +void e_cal_shell_view_update_timezone + (ECalShellView *cal_shell_view); + +/* Memo Pad Utilities */ + +void e_cal_shell_view_memopad_actions_init + (ECalShellView *cal_shell_view); +void e_cal_shell_view_memopad_actions_update + (ECalShellView *cal_shell_view); +void e_cal_shell_view_memopad_open_memo + (ECalShellView *cal_shell_view, + ECalModelComponent *comp_data); +void e_cal_shell_view_memopad_set_status_message + (ECalShellView *cal_shell_view, + const gchar *status_message, + gdouble percent); + +/* Task Pad Utilities */ + +void e_cal_shell_view_taskpad_actions_init + (ECalShellView *cal_shell_view); +void e_cal_shell_view_taskpad_actions_update + (ECalShellView *cal_shell_view); +void e_cal_shell_view_taskpad_open_task + (ECalShellView *cal_shell_view, + ECalModelComponent *comp_data); +void e_cal_shell_view_taskpad_set_status_message + (ECalShellView *cal_shell_view, + const gchar *status_message, + gdouble percent); + +G_END_DECLS + +#endif /* E_CAL_SHELL_VIEW_PRIVATE_H */ diff --git a/modules/calendar/e-cal-shell-view-taskpad.c b/modules/calendar/e-cal-shell-view-taskpad.c new file mode 100644 index 0000000000..bdd136b6f7 --- /dev/null +++ b/modules/calendar/e-cal-shell-view-taskpad.c @@ -0,0 +1,654 @@ +/* + * e-cal-shell-view-taskpad.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-view-private.h" + +/* Much of this file is based on e-task-shell-view-actions.c. */ + +static void +action_calendar_taskpad_assign_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + GSList *list; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only open the first selected task. */ + e_cal_shell_view_taskpad_open_task (cal_shell_view, comp_data); + + /* FIXME Need to actually assign the task. */ +} + +static void +action_calendar_taskpad_clipboard_copy_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + e_calendar_table_copy_clipboard (task_table); +} + +static void +action_calendar_taskpad_clipboard_cut_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + e_calendar_table_cut_clipboard (task_table); +} + +static void +action_calendar_taskpad_clipboard_paste_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + e_calendar_table_paste_clipboard (task_table); +} + +static void +action_calendar_taskpad_delete_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + e_cal_shell_view_taskpad_set_status_message ( + cal_shell_view, _("Deleting selected tasks..."), -1.0); + e_calendar_table_delete_selected (task_table); + e_cal_shell_view_taskpad_set_status_message ( + cal_shell_view, NULL, -1.0); +} + +static void +action_calendar_taskpad_forward_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + ECalComponent *comp; + icalcomponent *clone; + GSList *list; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only forward the first selected task. */ + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_component_set_icalcomponent (comp, clone); + itip_send_comp ( + E_CAL_COMPONENT_METHOD_PUBLISH, comp, + comp_data->client, NULL, NULL, NULL, TRUE); + g_object_unref (comp); +} + +static void +action_calendar_taskpad_mark_complete_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + ECalModel *model; + GSList *list, *iter; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + list = e_calendar_table_get_selected (task_table); + model = e_calendar_table_get_model (task_table); + + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + e_cal_model_tasks_mark_comp_complete ( + E_CAL_MODEL_TASKS (model), comp_data); + } + + g_slist_free (list); +} + +static void +action_calendar_taskpad_mark_incomplete_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + ECalModel *model; + GSList *list, *iter; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + list = e_calendar_table_get_selected (task_table); + model = e_calendar_table_get_model (task_table); + + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + e_cal_model_tasks_mark_comp_incomplete ( + E_CAL_MODEL_TASKS (model), comp_data); + } + + g_slist_free (list); +} + +static void +action_calendar_taskpad_new_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + ECal *client; + ECalComponent *comp; + CompEditor *editor; + GSList *list; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + client = comp_data->client; + editor = task_editor_new (client, shell, COMP_EDITOR_NEW_ITEM); + comp = cal_comp_task_new_with_defaults (client); + comp_editor_edit_comp (editor, comp); + + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (comp); + g_object_unref (client); +} + +static void +action_calendar_taskpad_open_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + GSList *list; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only open the first selected task. */ + e_cal_shell_view_taskpad_open_task (cal_shell_view, comp_data); +} + +static void +action_calendar_taskpad_open_url_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + icalproperty *prop; + const gchar *uri; + GSList *list; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + + /* XXX We only open the URI of the first selected task. */ + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_URL_PROPERTY); + g_return_if_fail (prop == NULL); + + uri = icalproperty_get_url (prop); + e_show_uri (GTK_WINDOW (shell_window), uri); +} + +static void +action_calendar_taskpad_print_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + ECalComponent *comp; + icalcomponent *clone; + GtkPrintOperationAction print_action; + GSList *list; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only print the first selected task. */ + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; + e_cal_component_set_icalcomponent (comp, clone); + print_comp (comp, comp_data->client, print_action); + g_object_unref (comp); +} + +static void +action_calendar_taskpad_save_as_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + GSList *list; + gchar *filename; + gchar *string; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + filename = e_file_dialog_save (_("Save as..."), NULL); + if (filename == NULL) + return; + + string = e_cal_get_component_as_string ( + comp_data->client, comp_data->icalcomp); + if (string == NULL) { + g_warning ("Could not convert task to a string"); + return; + } + + e_write_file_uri (filename, string); + + g_free (filename); + g_free (string); +} + +static GtkActionEntry calendar_taskpad_entries[] = { + + { "calendar-taskpad-assign", + NULL, + N_("_Assign Task"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_taskpad_assign_cb) }, + + { "calendar-taskpad-clipboard-copy", + GTK_STOCK_COPY, + NULL, + NULL, + N_("Copy selected tasks"), + G_CALLBACK (action_calendar_taskpad_clipboard_copy_cb) }, + + { "calendar-taskpad-clipboard-cut", + GTK_STOCK_CUT, + NULL, + NULL, + N_("Cut selected tasks"), + G_CALLBACK (action_calendar_taskpad_clipboard_cut_cb) }, + + { "calendar-taskpad-clipboard-paste", + GTK_STOCK_PASTE, + NULL, + NULL, + N_("Paste tasks from the clipboard"), + G_CALLBACK (action_calendar_taskpad_clipboard_paste_cb) }, + + { "calendar-taskpad-delete", + GTK_STOCK_DELETE, + N_("_Delete Task"), + NULL, + N_("Delete selected tasks"), + G_CALLBACK (action_calendar_taskpad_delete_cb) }, + + { "calendar-taskpad-forward", + "mail-forward", + N_("_Forward as iCalendar..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_taskpad_forward_cb) }, + + { "calendar-taskpad-mark-complete", + NULL, + N_("_Mark as Complete"), + NULL, + N_("Mark selected tasks as complete"), + G_CALLBACK (action_calendar_taskpad_mark_complete_cb) }, + + { "calendar-taskpad-mark-incomplete", + NULL, + N_("_Mar_k as Incomplete"), + NULL, + N_("Mark selected tasks as incomplete"), + G_CALLBACK (action_calendar_taskpad_mark_incomplete_cb) }, + + { "calendar-taskpad-new", + "stock_task", + N_("New _Task"), + NULL, + N_("Create a new task"), + G_CALLBACK (action_calendar_taskpad_new_cb) }, + + { "calendar-taskpad-open", + GTK_STOCK_OPEN, + N_("_Open Task"), + NULL, + N_("View the selected task"), + G_CALLBACK (action_calendar_taskpad_open_cb) }, + + { "calendar-taskpad-open-url", + "applications-internet", + N_("Open _Web Page"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_taskpad_open_url_cb) }, + + { "calendar-taskpad-save-as", + GTK_STOCK_SAVE_AS, + N_("_Save as iCalendar..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_taskpad_save_as_cb) } +}; + +static GtkActionEntry lockdown_printing_entries[] = { + + { "calendar-taskpad-print", + GTK_STOCK_PRINT, + NULL, + NULL, + N_("Print the selected task"), + G_CALLBACK (action_calendar_taskpad_print_cb) } +}; + +void +e_cal_shell_view_taskpad_actions_init (ECalShellView *cal_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkActionGroup *action_group; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + /* Calendar Actions */ + action_group = ACTION_GROUP (CALENDAR); + gtk_action_group_add_actions ( + action_group, calendar_taskpad_entries, + G_N_ELEMENTS (calendar_taskpad_entries), cal_shell_view); + + /* Lockdown Printing Actions */ + action_group = ACTION_GROUP (LOCKDOWN_PRINTING); + gtk_action_group_add_actions ( + action_group, lockdown_printing_entries, + G_N_ELEMENTS (lockdown_printing_entries), cal_shell_view); +} + +void +e_cal_shell_view_taskpad_actions_update (ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EShellWindow *shell_window; + EShellView *shell_view; + ECalendarTable *task_table; + ETable *table; + GtkAction *action; + GSList *list, *iter; + const gchar *label; + gboolean assignable = TRUE; + gboolean editable = TRUE; + gboolean has_url = FALSE; + gboolean sensitive; + gint n_selected; + gint n_complete = 0; + gint n_incomplete = 0; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + table = e_calendar_table_get_table (task_table); + n_selected = e_table_selected_count (table); + + list = e_calendar_table_get_selected (task_table); + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + icalproperty *prop; + const gchar *cap; + gboolean read_only; + + e_cal_is_read_only (comp_data->client, &read_only, NULL); + editable &= !read_only; + + cap = CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT; + if (e_cal_get_static_capability (comp_data->client, cap)) + assignable = FALSE; + + cap = CAL_STATIC_CAPABILITY_NO_CONV_TO_ASSIGN_TASK; + if (e_cal_get_static_capability (comp_data->client, cap)) + assignable = FALSE; + + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_URL_PROPERTY); + has_url |= (prop != NULL); + + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_COMPLETED_PROPERTY); + if (prop != NULL) + n_complete++; + else + n_incomplete++; + } + g_slist_free (list); + + action = ACTION (CALENDAR_TASKPAD_ASSIGN); + sensitive = (n_selected == 1) && editable && assignable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_CLIPBOARD_COPY); + sensitive = (n_selected > 0); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_CLIPBOARD_CUT); + sensitive = (n_selected > 0) && editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_CLIPBOARD_PASTE); + sensitive = editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_DELETE); + sensitive = (n_selected > 0) && editable; + gtk_action_set_sensitive (action, sensitive); + label = ngettext ("Delete Task", "Delete Tasks", n_selected); + g_object_set (action, "label", label, NULL); + + action = ACTION (CALENDAR_TASKPAD_FORWARD); + sensitive = (n_selected == 1); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_MARK_COMPLETE); + sensitive = (n_selected > 0) && editable && (n_incomplete > 0); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_MARK_INCOMPLETE); + sensitive = (n_selected > 0) && editable && (n_complete > 0); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_OPEN); + sensitive = (n_selected == 1); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_OPEN_URL); + sensitive = (n_selected == 1) && has_url; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_PRINT); + sensitive = (n_selected == 1); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_SAVE_AS); + sensitive = (n_selected == 1); + gtk_action_set_sensitive (action, sensitive); +} + +void +e_cal_shell_view_taskpad_open_task (ECalShellView *cal_shell_view, + ECalModelComponent *comp_data) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + CompEditor *editor; + CompEditorFlags flags = 0; + ECalComponent *comp; + icalcomponent *clone; + icalproperty *prop; + const gchar *uid; + + g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); + g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data)); + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + + uid = icalcomponent_get_uid (comp_data->icalcomp); + editor = comp_editor_find_instance (uid); + + if (editor != NULL) + goto exit; + + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_component_set_icalcomponent (comp, clone); + + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_ATTENDEE_PROPERTY); + if (prop != NULL) + flags |= COMP_EDITOR_IS_ASSIGNED; + + if (itip_organizer_is_user (comp, comp_data->client)) + flags |= COMP_EDITOR_USER_ORG; + + if (!e_cal_component_has_attendees (comp)) + flags |= COMP_EDITOR_USER_ORG; + + editor = task_editor_new (comp_data->client, shell, flags); + comp_editor_edit_comp (editor, comp); + + g_object_ref (comp); + + if (flags & COMP_EDITOR_IS_ASSIGNED) + task_editor_show_assignment (TASK_EDITOR (editor)); + +exit: + gtk_window_present (GTK_WINDOW (editor)); +} + +void +e_cal_shell_view_taskpad_set_status_message (ECalShellView *cal_shell_view, + const gchar *status_message, + gdouble percent) +{ + EActivity *activity; + EShellView *shell_view; + EShellBackend *shell_backend; + + g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + activity = cal_shell_view->priv->taskpad_activity; + + if (status_message == NULL || *status_message == '\0') { + if (activity != NULL) { + e_activity_complete (activity); + g_object_unref (activity); + activity = NULL; + } + + } else if (activity == NULL) { + activity = e_activity_new (status_message); + e_activity_set_percent (activity, percent); + e_shell_backend_add_activity (shell_backend, activity); + + } else { + e_activity_set_percent (activity, percent); + e_activity_set_primary_text (activity, status_message); + } + + cal_shell_view->priv->taskpad_activity = activity; +} diff --git a/modules/calendar/e-cal-shell-view.c b/modules/calendar/e-cal-shell-view.c new file mode 100644 index 0000000000..5bf1c749a1 --- /dev/null +++ b/modules/calendar/e-cal-shell-view.c @@ -0,0 +1,226 @@ +/* + * e-cal-shell-view.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-view-private.h" + +static gpointer parent_class; +static GType cal_shell_view_type; + +static void +cal_shell_view_dispose (GObject *object) +{ + e_cal_shell_view_private_dispose (E_CAL_SHELL_VIEW (object)); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +cal_shell_view_finalize (GObject *object) +{ + e_cal_shell_view_private_finalize (E_CAL_SHELL_VIEW (object)); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +cal_shell_view_constructed (GObject *object) +{ + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + e_cal_shell_view_private_constructed (E_CAL_SHELL_VIEW (object)); +} + +static void +cal_shell_view_update_actions (EShellView *shell_view) +{ +#if 0 + ECalShellViewPrivate *priv; + ECalShellContent *cal_shell_content; + ECalShellSidebar *cal_shell_sidebar; + EShellWindow *shell_window; + GnomeCalendar *calendar; + ECalModel *model; + ESourceSelector *selector; + ESource *source; + GtkAction *action; + GtkWidget *widget; + GList *list, *iter; + const gchar *uri = NULL; + gboolean user_created_source; + gboolean editable = TRUE; + gboolean recurring = FALSE; + gboolean sensitive; + gint n_selected; + + priv = E_CAL_SHELL_VIEW_GET_PRIVATE (shell_view); + + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_content = priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + widget = gnome_calendar_get_current_view_widget (calendar); + model = e_calendar_view_get_model (E_CALENDAR_VIEW (widget)); + + cal_shell_sidebar = priv->cal_shell_sidebar; + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + + list = e_calendar_view_get_selected_events (E_CALENDAR_VIEW (widget)); + n_selected = g_list_length (list); + + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + gboolean read_only; + + e_cal_is_read_only (comp_data->client, &read_only, NULL); + editable &= !read_only; + + if (e_cal_util_component_has_recurrences (comp_data->icalcomp)) + recurring |= TRUE; + else if (e_cal_util_component_is_instance (comp_data->icalcomp)) + recurring |= TRUE; + } + + source = e_source_selector_peek_primary_selection (selector); + if (source != NULL) + uri = e_source_peek_relative_uri (source); + user_created_source = (uri != NULL && strcmp (uri, "system") != 0); + + action = ACTION (CALENDAR_COPY); + sensitive = (source != NULL); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_DELETE); + sensitive = user_created_source; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_PROPERTIES); + sensitive = (source != NULL); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_RENAME); + sensitive = has_primary_source; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (EVENT_CLIPBOARD_COPY); + sensitive = (n_selected > 0); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (EVENT_CLIPBOARD_CUT); + sensitive = (n_selected > 0) && editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (EVENT_CLIPBOARD_PASTE); + sensitive = editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (EVENT_DELETE); + sensitive = (n_selected > 0) && editable && !recurring; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (EVENT_DELETE_OCCURRENCE); + sensitive = (n_selected > 0) && editable && recurring; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (EVENT_DELETE_OCCURRENCE_ALL); + sensitive = (n_selected > 0) && editable && recurring; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (EVENT_OPEN); + sensitive = (n_selected == 1); + gtk_action_set_sensitive (action, sensitive); +#endif +} + +static void +cal_shell_view_class_init (ECalShellViewClass *class, + GTypeModule *type_module) +{ + GObjectClass *object_class; + EShellViewClass *shell_view_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ECalShellViewPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->dispose = cal_shell_view_dispose; + object_class->finalize = cal_shell_view_finalize; + object_class->constructed = cal_shell_view_constructed; + + shell_view_class = E_SHELL_VIEW_CLASS (class); + shell_view_class->label = _("Calendar"); + shell_view_class->icon_name = "x-office-calendar"; + shell_view_class->ui_definition = "evolution-calendars.ui"; + shell_view_class->ui_manager_id = "org.gnome.evolution.calendars"; + shell_view_class->search_options = "/calendar-search-options"; + shell_view_class->search_rules = "caltypes.xml"; + shell_view_class->new_shell_content = e_cal_shell_content_new; + shell_view_class->new_shell_sidebar = e_cal_shell_sidebar_new; + shell_view_class->update_actions = cal_shell_view_update_actions; +} + +static void +cal_shell_view_init (ECalShellView *cal_shell_view, + EShellViewClass *shell_view_class) +{ + cal_shell_view->priv = + E_CAL_SHELL_VIEW_GET_PRIVATE (cal_shell_view); + + e_cal_shell_view_private_init (cal_shell_view, shell_view_class); +} + +GType +e_cal_shell_view_get_type (void) +{ + return cal_shell_view_type; +} + +void +e_cal_shell_view_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (ECalShellViewClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) cal_shell_view_class_init, + (GClassFinalizeFunc) NULL, + type_module, + sizeof (ECalShellView), + 0, /* n_preallocs */ + (GInstanceInitFunc) cal_shell_view_init, + NULL /* value_table */ + }; + + cal_shell_view_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_VIEW, + "ECalShellView", &type_info, 0); +} + +GnomeCalendar * +e_cal_shell_view_get_calendar (ECalShellView *cal_shell_view) +{ + g_return_val_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view), NULL); + + /* FIXME */ + return NULL; +} diff --git a/modules/calendar/e-cal-shell-view.h b/modules/calendar/e-cal-shell-view.h new file mode 100644 index 0000000000..67fa15220c --- /dev/null +++ b/modules/calendar/e-cal-shell-view.h @@ -0,0 +1,69 @@ +/* + * e-cal-shell-view.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_SHELL_VIEW_H +#define E_CAL_SHELL_VIEW_H + +#include +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_CAL_SHELL_VIEW \ + (e_cal_shell_view_get_type ()) +#define E_CAL_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_CAL_SHELL_VIEW, ECalShellView)) +#define E_CAL_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_CAL_SHELL_VIEW, ECalShellViewClass)) +#define E_IS_CAL_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_CAL_SHELL_VIEW)) +#define E_IS_CAL_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_CAL_SHELL_VIEW)) +#define E_CAL_SHELL_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_CAL_SHELL_VIEW, ECalShellViewClass)) + +G_BEGIN_DECLS + +typedef struct _ECalShellView ECalShellView; +typedef struct _ECalShellViewClass ECalShellViewClass; +typedef struct _ECalShellViewPrivate ECalShellViewPrivate; + +struct _ECalShellView { + EShellView parent; + ECalShellViewPrivate *priv; +}; + +struct _ECalShellViewClass { + EShellViewClass parent_class; +}; + +GType e_cal_shell_view_get_type (void); +void e_cal_shell_view_register_type (GTypeModule *type_module); +GnomeCalendar * e_cal_shell_view_get_calendar (ECalShellView *cal_shell_view); + +G_END_DECLS + +#endif /* E_CAL_SHELL_VIEW_H */ diff --git a/modules/calendar/e-memo-shell-backend.c b/modules/calendar/e-memo-shell-backend.c new file mode 100644 index 0000000000..d2734e066a --- /dev/null +++ b/modules/calendar/e-memo-shell-backend.c @@ -0,0 +1,613 @@ +/* + * e-memo-shell-backend.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-memo-shell-backend.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "shell/e-shell.h" +#include "shell/e-shell-backend.h" +#include "shell/e-shell-window.h" + +#include "calendar/common/authentication.h" +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/comp-util.h" +#include "calendar/gui/dialogs/calendar-setup.h" +#include "calendar/gui/dialogs/memo-editor.h" + +#include "e-memo-shell-migrate.h" +#include "e-memo-shell-view.h" + +#define E_MEMO_SHELL_BACKEND_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MEMO_SHELL_BACKEND, EMemoShellBackendPrivate)) + +#define WEB_BASE_URI "webcal://" +#define PERSONAL_RELATIVE_URI "system" + +struct _EMemoShellBackendPrivate { + ESourceList *source_list; +}; + +enum { + PROP_0, + PROP_SOURCE_LIST +}; + +static gpointer parent_class; +static GType memo_shell_backend_type; + +static void +memo_module_ensure_sources (EShellBackend *shell_backend) +{ + /* XXX This is basically the same algorithm across all modules. + * Maybe we could somehow integrate this into EShellBackend? */ + + EMemoShellBackendPrivate *priv; + ESourceGroup *on_this_computer; + ESourceGroup *on_the_web; + ESource *personal; + GSList *groups, *iter; + const gchar *data_dir; + const gchar *name; + gchar *base_uri; + gchar *filename; + + on_this_computer = NULL; + on_the_web = NULL; + personal = NULL; + + priv = E_MEMO_SHELL_BACKEND_GET_PRIVATE (shell_backend); + + if (!e_cal_get_sources (&priv->source_list, E_CAL_SOURCE_TYPE_JOURNAL, NULL)) { + g_warning ("Could not get memo sources from GConf!"); + return; + } + + data_dir = e_shell_backend_get_data_dir (shell_backend); + filename = g_build_filename (data_dir, "local", NULL); + base_uri = g_filename_to_uri (filename, NULL, NULL); + g_free (filename); + + groups = e_source_list_peek_groups (priv->source_list); + for (iter = groups; iter != NULL; iter = iter->next) { + ESourceGroup *source_group = iter->data; + const gchar *group_base_uri; + + group_base_uri = e_source_group_peek_base_uri (source_group); + + /* Compare only "file://" part. If the user's home + * changes, we do not want to create another group. */ + if (on_this_computer == NULL && + strncmp (base_uri, group_base_uri, 7) == 0) + on_this_computer = source_group; + + else if (on_the_web == NULL && + strcmp (WEB_BASE_URI, group_base_uri) == 0) + on_the_web = source_group; + } + + name = _("On This Computer"); + + if (on_this_computer != NULL) { + GSList *sources; + const gchar *group_base_uri; + + /* Force the group name to the current locale. */ + e_source_group_set_name (on_this_computer, name); + + sources = e_source_group_peek_sources (on_this_computer); + group_base_uri = e_source_group_peek_base_uri (on_this_computer); + + /* Make sure this group includes a "Personal" source. */ + for (iter = sources; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + const gchar *relative_uri; + + relative_uri = e_source_peek_relative_uri (source); + if (relative_uri == NULL) + continue; + + if (strcmp (PERSONAL_RELATIVE_URI, relative_uri) != 0) + continue; + + personal = source; + break; + } + + /* Make sure we have the correct base URI. This can + * change when the user's home directory changes. */ + if (strcmp (base_uri, group_base_uri) != 0) { + e_source_group_set_base_uri ( + on_this_computer, base_uri); + + /* XXX We shouldn't need this sync call here as + * set_base_uri() results in synching to GConf, + * but that happens in an idle loop and too late + * to prevent the user from seeing a "Cannot + * Open ... because of invalid URI" error. */ + e_source_list_sync (priv->source_list, NULL); + } + + } else { + ESourceGroup *source_group; + + source_group = e_source_group_new (name, base_uri); + e_source_list_add_group (priv->source_list, source_group, -1); + g_object_unref (source_group); + } + + name = _("Personal"); + + if (personal == NULL) { + ESource *source; + GSList *selected; + gchar *primary; + + source = e_source_new (name, PERSONAL_RELATIVE_URI); + e_source_group_add_source (on_this_computer, source, -1); + g_object_unref (source); + + primary = calendar_config_get_primary_memos (); + selected = calendar_config_get_memos_selected (); + + if (primary == NULL && selected == NULL) { + const gchar *uid; + + uid = e_source_peek_uid (source); + selected = g_slist_prepend (NULL, g_strdup (uid)); + + calendar_config_set_primary_memos (uid); + calendar_config_set_memos_selected (selected); + } + + g_slist_foreach (selected, (GFunc) g_free, NULL); + g_slist_free (selected); + g_free (primary); + } else { + /* Force the source name to the current locale. */ + e_source_set_name (personal, name); + } + + name = _("On The Web"); + + if (on_the_web == NULL) { + ESourceGroup *source_group; + + source_group = e_source_group_new (name, WEB_BASE_URI); + e_source_list_add_group (priv->source_list, source_group, -1); + g_object_unref (source_group); + } else { + /* Force the group name to the current locale. */ + e_source_group_set_name (on_the_web, name); + } + + g_free (base_uri); +} + +static void +memo_module_cal_opened_cb (ECal *cal, + ECalendarStatus status, + GtkAction *action) +{ + EShell *shell; + ECalComponent *comp; + CompEditor *editor; + CompEditorFlags flags = 0; + const gchar *action_name; + + /* FIXME Pass this in. */ + shell = e_shell_get_default (); + + /* XXX Handle errors better. */ + if (status != E_CALENDAR_STATUS_OK) + return; + + action_name = gtk_action_get_name (action); + + flags |= COMP_EDITOR_NEW_ITEM; + if (strcmp (action_name, "memo-shared-new") == 0) { + flags |= COMP_EDITOR_IS_SHARED; + flags |= COMP_EDITOR_USER_ORG; + } + + editor = memo_editor_new (cal, shell, flags); + comp = cal_comp_memo_new_with_defaults (cal); + comp_editor_edit_comp (editor, comp); + + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (comp); + g_object_unref (cal); +} + +static void +action_memo_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + ECal *cal = NULL; + ECalSourceType source_type; + ESourceList *source_list; + gchar *uid; + + /* This callback is used for both memos and shared memos. */ + + source_type = E_CAL_SOURCE_TYPE_JOURNAL; + + if (!e_cal_get_sources (&source_list, source_type, NULL)) { + g_warning ("Could not get memo sources from GConf!"); + return; + } + + uid = calendar_config_get_primary_memos (); + + if (uid != NULL) { + ESource *source; + + source = e_source_list_peek_source_by_uid (source_list, uid); + if (source != NULL) + cal = auth_new_cal_from_source (source, source_type); + g_free (uid); + } + + if (cal == NULL) + cal = auth_new_cal_from_default (source_type); + + g_return_if_fail (cal != NULL); + + g_signal_connect ( + cal, "cal-opened", + G_CALLBACK (memo_module_cal_opened_cb), action); + + e_cal_open_async (cal, FALSE); +} + +static void +action_memo_list_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + calendar_setup_new_memo_list (GTK_WINDOW (shell_window)); +} + +static GtkActionEntry item_entries[] = { + + { "memo-new", + "stock_insert-note", + NC_("New", "Mem_o"), + "o", + N_("Create a new memo"), + G_CALLBACK (action_memo_new_cb) }, + + { "memo-shared-new", + "stock_insert-note", + N_("_Shared Memo"), + "h", + N_("Create a new shared memo"), + G_CALLBACK (action_memo_new_cb) } +}; + +static GtkActionEntry source_entries[] = { + + { "memo-list-new", + "stock_notes", + NC_("New", "Memo Li_st"), + NULL, + N_("Create a new memo list"), + G_CALLBACK (action_memo_list_new_cb) } +}; + +static gboolean +memo_module_handle_uri_cb (EShellBackend *shell_backend, + const gchar *uri) +{ + EShell *shell; + CompEditor *editor; + CompEditorFlags flags = 0; + ECal *client; + ECalComponent *comp; + ESource *source; + ESourceList *source_list; + ECalSourceType source_type; + EUri *euri; + icalcomponent *icalcomp; + const gchar *cp; + gchar *source_uid = NULL; + gchar *comp_uid = NULL; + gchar *comp_rid = NULL; + gboolean handled = FALSE; + GError *error = NULL; + + source_type = E_CAL_SOURCE_TYPE_JOURNAL; + shell = e_shell_backend_get_shell (shell_backend); + + if (strncmp (uri, "memo:", 5) != 0) + return FALSE; + + euri = e_uri_new (uri); + cp = euri->query; + if (cp == NULL) + goto exit; + + while (*cp != '\0') { + gchar *header; + gchar *content; + gsize header_len; + gsize content_len; + + header_len = strcspn (cp, "=&"); + + /* If it's malformed, give up. */ + if (cp[header_len] != '=') + break; + + header = (gchar *) cp; + header[header_len] = '\0'; + cp += header_len + 1; + + content_len = strcspn (cp, "&"); + + content = g_strndup (cp, content_len); + if (g_ascii_strcasecmp (header, "source-uid") == 0) + source_uid = g_strdup (content); + else if (g_ascii_strcasecmp (header, "comp-uid") == 0) + comp_uid = g_strdup (content); + else if (g_ascii_strcasecmp (header, "comp-rid") == 0) + comp_rid = g_strdup (content); + g_free (content); + + cp += content_len; + if (*cp == '&') { + cp++; + if (strcmp (cp, "amp;") == 0) + cp += 4; + } + } + + if (source_uid == NULL || comp_uid == NULL) + goto exit; + + /* URI is valid, so consider it handled. Whether + * we successfully open it is another matter... */ + handled = TRUE; + + if (!e_cal_get_sources (&source_list, source_type, NULL)) { + g_printerr ("Could not get memo sources from GConf!\n"); + goto exit; + } + + source = e_source_list_peek_source_by_uid (source_list, source_uid); + if (source == NULL) { + g_printerr ("No source for UID `%s'\n", source_uid); + g_object_unref (source_list); + goto exit; + } + + client = auth_new_cal_from_source (source, source_type); + if (client == NULL || !e_cal_open (client, TRUE, &error)) { + g_printerr ("%s\n", error->message); + g_object_unref (source_list); + g_error_free (error); + goto exit; + } + + /* XXX Copied from e_memo_shell_view_open_memo(). + * Clearly a new utility function is needed. */ + + editor = comp_editor_find_instance (comp_uid); + + if (editor != NULL) + goto present; + + if (!e_cal_get_object (client, comp_uid, comp_rid, &icalcomp, &error)) { + g_printerr ("%s\n", error->message); + g_object_unref (source_list); + g_error_free (error); + goto exit; + } + + comp = e_cal_component_new (); + e_cal_component_set_icalcomponent (comp, icalcomp); + + if (e_cal_component_has_organizer (comp)) + flags |= COMP_EDITOR_IS_SHARED; + + if (itip_organizer_is_user (comp, client)) + flags |= COMP_EDITOR_USER_ORG; + + editor = memo_editor_new (client, shell, flags); + comp_editor_edit_comp (editor, comp); + + g_object_unref (comp); + +present: + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (source_list); + g_object_unref (client); + +exit: + g_free (source_uid); + g_free (comp_uid); + g_free (comp_rid); + + e_uri_free (euri); + + return handled; +} + +static void +memo_module_window_created_cb (EShellBackend *shell_backend, + GtkWindow *window) +{ + const gchar *module_name; + + if (!E_IS_SHELL_WINDOW (window)) + return; + + module_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name; + + e_shell_window_register_new_item_actions ( + E_SHELL_WINDOW (window), module_name, + item_entries, G_N_ELEMENTS (item_entries)); + + e_shell_window_register_new_source_actions ( + E_SHELL_WINDOW (window), module_name, + source_entries, G_N_ELEMENTS (source_entries)); +} + +static void +memo_shell_backend_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SOURCE_LIST: + g_value_set_object ( + value, + e_memo_shell_backend_get_source_list ( + E_MEMO_SHELL_BACKEND (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +memo_shell_backend_dispose (GObject *object) +{ + EMemoShellBackendPrivate *priv; + + priv = E_MEMO_SHELL_BACKEND_GET_PRIVATE (object); + + if (priv->source_list != NULL) { + g_object_unref (priv->source_list); + priv->source_list = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +memo_shell_backend_constructed (GObject *object) +{ + EShell *shell; + EShellBackend *shell_backend; + + shell_backend = E_SHELL_BACKEND (object); + shell = e_shell_backend_get_shell (shell_backend); + + memo_module_ensure_sources (shell_backend); + + g_signal_connect_swapped ( + shell, "handle-uri", + G_CALLBACK (memo_module_handle_uri_cb), shell_backend); + + g_signal_connect_swapped ( + shell, "window-created", + G_CALLBACK (memo_module_window_created_cb), shell_backend); +} + +static void +memo_shell_backend_class_init (EMemoShellBackendClass *class) +{ + GObjectClass *object_class; + EShellBackendClass *shell_backend_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMemoShellBackendPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->get_property = memo_shell_backend_get_property; + object_class->dispose = memo_shell_backend_dispose; + object_class->constructed = memo_shell_backend_constructed; + + shell_backend_class = E_SHELL_BACKEND_CLASS (class); + shell_backend_class->shell_view_type = E_TYPE_MEMO_SHELL_VIEW; + shell_backend_class->name = "memos"; + shell_backend_class->aliases = ""; + shell_backend_class->schemes = "memo"; + shell_backend_class->sort_order = 500; + shell_backend_class->start = NULL; + shell_backend_class->is_busy = NULL; + shell_backend_class->shutdown = NULL; + shell_backend_class->migrate = e_memo_shell_backend_migrate; + + g_object_class_install_property ( + object_class, + PROP_SOURCE_LIST, + g_param_spec_object ( + "source-list", + _("Source List"), + _("The registry of memo lists"), + E_TYPE_SOURCE_LIST, + G_PARAM_READABLE)); +} + +static void +memo_shell_backend_init (EMemoShellBackend *memo_shell_backend) +{ + memo_shell_backend->priv = + E_MEMO_SHELL_BACKEND_GET_PRIVATE (memo_shell_backend); +} + +GType +e_memo_shell_backend_get_type (void) +{ + return memo_shell_backend_type; +} + +void +e_memo_shell_backend_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (EMemoShellBackendClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) memo_shell_backend_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMemoShellBackend), + 0, /* n_preallocs */ + (GInstanceInitFunc) memo_shell_backend_init, + NULL /* value_table */ + }; + + memo_shell_backend_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_BACKEND, + "EMemoShellBackend", &type_info, 0); +} + +ESourceList * +e_memo_shell_backend_get_source_list (EMemoShellBackend *memo_shell_backend) +{ + g_return_val_if_fail ( + E_IS_MEMO_SHELL_BACKEND (memo_shell_backend), NULL); + + return memo_shell_backend->priv->source_list; +} diff --git a/modules/calendar/e-memo-shell-backend.h b/modules/calendar/e-memo-shell-backend.h new file mode 100644 index 0000000000..37fe41a784 --- /dev/null +++ b/modules/calendar/e-memo-shell-backend.h @@ -0,0 +1,70 @@ +/* + * e-memo-shell-backend.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MEMO_SHELL_BACKEND_H +#define E_MEMO_SHELL_BACKEND_H + +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_MEMO_SHELL_BACKEND \ + (e_memo_shell_backend_get_type ()) +#define E_MEMO_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MEMO_SHELL_BACKEND, EMemoShellBackend)) +#define E_MEMO_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MEMO_SHELL_BACKEND, EMemoShellBackendClass)) +#define E_IS_MEMO_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MEMO_SHELL_BACKEND)) +#define E_IS_MEMO_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MEMO_SHELL_BACKEND)) +#define E_MEMO_SHELL_BACKEND_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MEMO_SHELL_BACKEND, EMemoShellBackendClass)) + +G_BEGIN_DECLS + +typedef struct _EMemoShellBackend EMemoShellBackend; +typedef struct _EMemoShellBackendClass EMemoShellBackendClass; +typedef struct _EMemoShellBackendPrivate EMemoShellBackendPrivate; + +struct _EMemoShellBackend { + EShellBackend parent; + EMemoShellBackendPrivate *priv; +}; + +struct _EMemoShellBackendClass { + EShellBackendClass parent_class; +}; + +GType e_memo_shell_backend_get_type (void); +void e_memo_shell_backend_register_type + (GTypeModule *type_module); +ESourceList * e_memo_shell_backend_get_source_list + (EMemoShellBackend *memo_shell_backend); + +G_END_DECLS + +#endif /* E_MEMO_SHELL_BACKEND_H */ diff --git a/modules/calendar/e-memo-shell-content.c b/modules/calendar/e-memo-shell-content.c new file mode 100644 index 0000000000..ce020158ae --- /dev/null +++ b/modules/calendar/e-memo-shell-content.c @@ -0,0 +1,676 @@ +/* + * e-memo-shell-content.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-memo-shell-content.h" + +#include + +#include "e-util/gconf-bridge.h" + +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/comp-util.h" +#include "calendar/gui/e-cal-model-memos.h" +#include "calendar/gui/e-memo-table.h" +#include "calendar/gui/e-memo-table-config.h" + +#include "widgets/menus/gal-view-etable.h" + +#define E_MEMO_SHELL_CONTENT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MEMO_SHELL_CONTENT, EMemoShellContentPrivate)) + +#define E_MEMO_TABLE_DEFAULT_STATE \ + "" \ + "" \ + " " \ + " " \ + " " \ + " " \ + "" + +struct _EMemoShellContentPrivate { + GtkWidget *paned; + GtkWidget *memo_table; + GtkWidget *memo_preview; + + ECalModel *memo_model; + EMemoTableConfig *table_config; + GalViewInstance *view_instance; + + gchar *current_uid; +}; + +enum { + PROP_0, + PROP_MODEL, + PROP_PREVIEW_VISIBLE +}; + +enum { + TARGET_VCALENDAR +}; + +static GtkTargetEntry drag_types[] = { + { (gchar *) "text/calendar", 0, TARGET_VCALENDAR }, + { (gchar *) "text/x-calendar", 0, TARGET_VCALENDAR } +}; + +static gpointer parent_class; +static GType memo_shell_content_type; + +static void +memo_shell_content_display_view_cb (EMemoShellContent *memo_shell_content, + GalView *gal_view) +{ + EMemoTable *memo_table; + ETable *table; + + if (!GAL_IS_VIEW_ETABLE (gal_view)) + return; + + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + table = e_memo_table_get_table (memo_table); + + gal_view_etable_attach_table (GAL_VIEW_ETABLE (gal_view), table); +} + +static void +memo_shell_content_table_foreach_cb (gint model_row, + gpointer user_data) +{ + ECalModelComponent *comp_data; + icalcomponent *clone; + icalcomponent *vcal; + gchar *string; + + struct { + ECalModel *model; + GSList *list; + } *foreach_data = user_data; + + comp_data = e_cal_model_get_component_at ( + foreach_data->model, model_row); + + vcal = e_cal_util_new_top_level (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_util_add_timezones_from_component (vcal, comp_data->icalcomp); + icalcomponent_add_component (vcal, clone); + + /* String is owned by libical; do not free. */ + string = icalcomponent_as_ical_string (vcal); + if (string != NULL) { + ESource *source; + const gchar *source_uid; + + source = e_cal_get_source (comp_data->client); + source_uid = e_source_peek_uid (source); + + foreach_data->list = g_slist_prepend ( + foreach_data->list, + g_strdup_printf ("%s\n%s", source_uid, string)); + } + + icalcomponent_free (vcal); +} + +static void +memo_shell_content_table_drag_data_get_cb (EMemoShellContent *memo_shell_content, + gint row, + gint col, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time) +{ + EMemoTable *memo_table; + ETable *table; + + struct { + ECalModel *model; + GSList *list; + } foreach_data; + + if (info != TARGET_VCALENDAR) + return; + + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + table = e_memo_table_get_table (memo_table); + + foreach_data.model = e_memo_table_get_model (memo_table); + foreach_data.list = NULL; + + e_table_selected_row_foreach ( + table, memo_shell_content_table_foreach_cb, + &foreach_data); + + if (foreach_data.list != NULL) { + cal_comp_selection_set_string_list ( + selection_data, foreach_data.list); + g_slist_foreach (foreach_data.list, (GFunc) g_free, NULL); + g_slist_free (foreach_data.list); + } +} + +static void +memo_shell_content_table_drag_data_delete_cb (EMemoShellContent *memo_shell_content, + gint row, + gint col, + GdkDragContext *context) +{ + /* Moved components are deleted from source immediately when moved, + * because some of them can be part of destination source, and we + * don't want to delete not-moved memos. There is no such information + * which event has been moved and which not, so skip this method. */ +} + +static void +memo_shell_content_cursor_change_cb (EMemoShellContent *memo_shell_content, + gint row, + ETable *table) +{ + ECalComponentPreview *memo_preview; + EMemoTable *memo_table; + ECalModel *memo_model; + ECalModelComponent *comp_data; + ECalComponent *comp; + const gchar *uid; + + memo_model = e_memo_shell_content_get_memo_model (memo_shell_content); + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + memo_preview = e_memo_shell_content_get_memo_preview (memo_shell_content); + + if (e_table_selected_count (table) != 1) { + e_cal_component_preview_clear (memo_preview); + return; + } + + row = e_table_get_cursor_row (table); + comp_data = e_cal_model_get_component_at (memo_model, row); + + comp = e_cal_component_new (); + e_cal_component_set_icalcomponent ( + comp, icalcomponent_new_clone (comp_data->icalcomp)); + e_cal_component_preview_display ( + memo_preview, comp_data->client, comp); + + e_cal_component_get_uid (comp, &uid); + g_free (memo_shell_content->priv->current_uid); + memo_shell_content->priv->current_uid = g_strdup (uid); + + g_object_unref (comp); +} + +static void +memo_shell_content_selection_change_cb (EMemoShellContent *memo_shell_content, + ETable *table) +{ + ECalComponentPreview *memo_preview; + + memo_preview = e_memo_shell_content_get_memo_preview (memo_shell_content); + + /* XXX Old code emits a "selection-changed" signal here. */ + + if (e_table_selected_count (table) != 1) + e_cal_component_preview_clear (memo_preview); +} + +static void +memo_shell_content_model_row_changed_cb (EMemoShellContent *memo_shell_content, + gint row, + ETableModel *model) +{ + ECalModelComponent *comp_data; + EMemoTable *memo_table; + ETable *table; + const gchar *current_uid; + const gchar *uid; + + current_uid = memo_shell_content->priv->current_uid; + if (current_uid == NULL) + return; + + comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row); + if (comp_data == NULL) + return; + + uid = icalcomponent_get_uid (comp_data->icalcomp); + if (g_strcmp0 (uid, current_uid) != 0) + return; + + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + table = e_memo_table_get_table (memo_table); + + memo_shell_content_cursor_change_cb (memo_shell_content, 0, table); +} + +static void +memo_shell_content_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_PREVIEW_VISIBLE: + e_memo_shell_content_set_preview_visible ( + E_MEMO_SHELL_CONTENT (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +memo_shell_content_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_MODEL: + g_value_set_object ( + value, e_memo_shell_content_get_memo_model ( + E_MEMO_SHELL_CONTENT (object))); + return; + + case PROP_PREVIEW_VISIBLE: + g_value_set_boolean ( + value, e_memo_shell_content_get_preview_visible ( + E_MEMO_SHELL_CONTENT (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +memo_shell_content_dispose (GObject *object) +{ + EMemoShellContentPrivate *priv; + + priv = E_MEMO_SHELL_CONTENT_GET_PRIVATE (object); + + if (priv->paned != NULL) { + g_object_unref (priv->paned); + priv->paned = NULL; + } + + if (priv->memo_table != NULL) { + g_object_unref (priv->memo_table); + priv->memo_table = NULL; + } + + if (priv->memo_preview != NULL) { + g_object_unref (priv->memo_preview); + priv->memo_preview = NULL; + } + + if (priv->memo_model != NULL) { + g_object_unref (priv->memo_model); + priv->memo_model = NULL; + } + + if (priv->table_config != NULL) { + g_object_unref (priv->table_config); + priv->table_config = NULL; + } + + if (priv->view_instance != NULL) { + g_object_unref (priv->view_instance); + priv->view_instance = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +memo_shell_content_finalize (GObject *object) +{ + EMemoShellContentPrivate *priv; + + priv = E_MEMO_SHELL_CONTENT_GET_PRIVATE (object); + + g_free (priv->current_uid); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +memo_shell_content_constructed (GObject *object) +{ + EMemoShellContentPrivate *priv; + EShellContent *shell_content; + EShellView *shell_view; + GalViewInstance *view_instance; + ETable *table; + GConfBridge *bridge; + GtkWidget *container; + GtkWidget *widget; + const gchar *key; + + priv = E_MEMO_SHELL_CONTENT_GET_PRIVATE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_content = E_SHELL_CONTENT (object); + shell_view = e_shell_content_get_shell_view (shell_content); + + /* Build content widgets. */ + + container = GTK_WIDGET (object); + + widget = gtk_vpaned_new (); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->paned = g_object_ref (widget); + gtk_widget_show (widget); + + container = widget; + + widget = e_memo_table_new (shell_view, priv->memo_model); + gtk_paned_add1 (GTK_PANED (container), widget); + priv->memo_table = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_paned_add2 (GTK_PANED (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = e_cal_component_preview_new (); + e_cal_component_preview_set_default_timezone ( + E_CAL_COMPONENT_PREVIEW (widget), + calendar_config_get_icaltimezone ()); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->memo_preview = g_object_ref (widget); + gtk_widget_show (widget); + + /* Configure the memo table. */ + + widget = E_MEMO_TABLE (priv->memo_table)->etable; + table = e_table_scrolled_get_table (E_TABLE_SCROLLED (widget)); + + priv->table_config = e_memo_table_config_new ( + E_MEMO_TABLE (priv->memo_table)); + + e_table_set_state (table, E_MEMO_TABLE_DEFAULT_STATE); + + e_table_drag_source_set ( + table, GDK_BUTTON1_MASK, + drag_types, G_N_ELEMENTS (drag_types), + GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_ASK); + + g_signal_connect_swapped ( + table, "table-drag-data-get", + G_CALLBACK (memo_shell_content_table_drag_data_get_cb), + object); + + g_signal_connect_swapped ( + table, "table-drag-data-delete", + G_CALLBACK (memo_shell_content_table_drag_data_delete_cb), + object); + + g_signal_connect_swapped ( + table, "cursor-change", + G_CALLBACK (memo_shell_content_cursor_change_cb), + object); + + g_signal_connect_swapped ( + table, "selection-change", + G_CALLBACK (memo_shell_content_selection_change_cb), + object); + + g_signal_connect_swapped ( + priv->memo_model, "model-row-changed", + G_CALLBACK (memo_shell_content_model_row_changed_cb), + object); + + /* Load the view instance. */ + + view_instance = e_shell_view_new_view_instance (shell_view, NULL); + g_signal_connect_swapped ( + view_instance, "display-view", + G_CALLBACK (memo_shell_content_display_view_cb), + object); + gal_view_instance_load (view_instance); + priv->view_instance = view_instance; + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (priv->paned); + key = "/apps/evolution/calendar/display/memo_vpane_position"; + gconf_bridge_bind_property_delayed (bridge, key, object, "position"); +} + +static guint32 +memo_shell_content_check_state (EShellContent *shell_content) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ETable *table; + GSList *list, *iter; + gboolean editable = TRUE; + gboolean has_url = FALSE; + gint n_selected; + guint32 state = 0; + + memo_shell_content = E_MEMO_SHELL_CONTENT (shell_content); + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + table = e_memo_table_get_table (memo_table); + n_selected = e_table_selected_count (table); + + list = e_memo_table_get_selected (memo_table); + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + icalproperty *prop; + gboolean read_only; + + e_cal_is_read_only (comp_data->client, &read_only, NULL); + editable &= !read_only; + + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_URL_PROPERTY); + has_url |= (prop != NULL); + } + g_slist_free (list); + + if (n_selected == 1) + state |= E_MEMO_SHELL_CONTENT_SELECTION_SINGLE; + if (n_selected > 1) + state |= E_MEMO_SHELL_CONTENT_SELECTION_MULTIPLE; + if (editable) + state |= E_MEMO_SHELL_CONTENT_SELECTION_CAN_EDIT; + if (has_url) + state |= E_MEMO_SHELL_CONTENT_SELECTION_HAS_URL; + + return state; +} + +static void +memo_shell_content_class_init (EMemoShellContentClass *class) +{ + GObjectClass *object_class; + EShellContentClass *shell_content_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMemoShellContentPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = memo_shell_content_set_property; + object_class->get_property = memo_shell_content_get_property; + object_class->dispose = memo_shell_content_dispose; + object_class->finalize = memo_shell_content_finalize; + object_class->constructed = memo_shell_content_constructed; + + shell_content_class = E_SHELL_CONTENT_CLASS (class); + shell_content_class->check_state = memo_shell_content_check_state; + + g_object_class_install_property ( + object_class, + PROP_MODEL, + g_param_spec_object ( + "model", + _("Model"), + _("The memo table model"), + E_TYPE_CAL_MODEL, + G_PARAM_READABLE)); + + g_object_class_install_property ( + object_class, + PROP_PREVIEW_VISIBLE, + g_param_spec_boolean ( + "preview-visible", + _("Preview is Visible"), + _("Whether the preview pane is visible"), + TRUE, + G_PARAM_READWRITE)); +} + +static void +memo_shell_content_init (EMemoShellContent *memo_shell_content) +{ + memo_shell_content->priv = + E_MEMO_SHELL_CONTENT_GET_PRIVATE (memo_shell_content); + + memo_shell_content->priv->memo_model = e_cal_model_memos_new (); + + /* Postpone widget construction until we have a shell view. */ +} + +GType +e_memo_shell_content_get_type (void) +{ + return memo_shell_content_type; +} + +void +e_memo_shell_content_register_type (GTypeModule *type_module) +{ + static const GTypeInfo type_info = { + sizeof (EMemoShellContentClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) memo_shell_content_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMemoShellContent), + 0, /* n_preallocs */ + (GInstanceInitFunc) memo_shell_content_init, + NULL /* value_table */ + }; + + memo_shell_content_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_CONTENT, + "EMemoShellContent", &type_info, 0); +} + +GtkWidget * +e_memo_shell_content_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_MEMO_SHELL_CONTENT, + "shell-view", shell_view, NULL); +} + +ECalModel * +e_memo_shell_content_get_memo_model (EMemoShellContent *memo_shell_content) +{ + g_return_val_if_fail ( + E_IS_MEMO_SHELL_CONTENT (memo_shell_content), NULL); + + return memo_shell_content->priv->memo_model; +} + +ECalComponentPreview * +e_memo_shell_content_get_memo_preview (EMemoShellContent *memo_shell_content) +{ + g_return_val_if_fail ( + E_IS_MEMO_SHELL_CONTENT (memo_shell_content), NULL); + + return E_CAL_COMPONENT_PREVIEW ( + memo_shell_content->priv->memo_preview); +} + +EMemoTable * +e_memo_shell_content_get_memo_table (EMemoShellContent *memo_shell_content) +{ + g_return_val_if_fail ( + E_IS_MEMO_SHELL_CONTENT (memo_shell_content), NULL); + + return E_MEMO_TABLE (memo_shell_content->priv->memo_table); +} + +GalViewInstance * +e_memo_shell_content_get_view_instance (EMemoShellContent *memo_shell_content) +{ + g_return_val_if_fail ( + E_IS_MEMO_SHELL_CONTENT (memo_shell_content), NULL); + + return memo_shell_content->priv->view_instance; +} + +gboolean +e_memo_shell_content_get_preview_visible (EMemoShellContent *memo_shell_content) +{ + GtkPaned *paned; + GtkWidget *child; + + g_return_val_if_fail ( + E_IS_MEMO_SHELL_CONTENT (memo_shell_content), FALSE); + + paned = GTK_PANED (memo_shell_content->priv->paned); + child = gtk_paned_get_child2 (paned); + + return GTK_WIDGET_VISIBLE (child); +} + +void +e_memo_shell_content_set_preview_visible (EMemoShellContent *memo_shell_content, + gboolean preview_visible) +{ + GtkPaned *paned; + GtkWidget *child; + + g_return_if_fail (E_IS_MEMO_SHELL_CONTENT (memo_shell_content)); + + paned = GTK_PANED (memo_shell_content->priv->paned); + child = gtk_paned_get_child2 (paned); + + if (preview_visible) + gtk_widget_show (child); + else + gtk_widget_hide (child); + + g_object_notify (G_OBJECT (memo_shell_content), "preview-visible"); +} diff --git a/modules/calendar/e-memo-shell-content.h b/modules/calendar/e-memo-shell-content.h new file mode 100644 index 0000000000..84c22d6ce4 --- /dev/null +++ b/modules/calendar/e-memo-shell-content.h @@ -0,0 +1,96 @@ +/* + * e-memo-shell-content.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MEMO_SHELL_CONTENT_H +#define E_MEMO_SHELL_CONTENT_H + +#include +#include + +#include +#include + +#include + +/* Standard GObject macros */ +#define E_TYPE_MEMO_SHELL_CONTENT \ + (e_memo_shell_content_get_type ()) +#define E_MEMO_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MEMO_SHELL_CONTENT, EMemoShellContent)) +#define E_MEMO_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MEMO_SHELL_CONTENT, EMemoShellContentClass)) +#define E_IS_MEMO_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MEMO_SHELL_CONTENT)) +#define E_IS_MEMO_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MEMO_SHELL_CONTENT)) +#define E_MEMO_SHELL_CONTENT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MEMO_SHELL_CONTENT, EMemoShellContentClass)) + +G_BEGIN_DECLS + +typedef struct _EMemoShellContent EMemoShellContent; +typedef struct _EMemoShellContentClass EMemoShellContentClass; +typedef struct _EMemoShellContentPrivate EMemoShellContentPrivate; + +enum { + E_MEMO_SHELL_CONTENT_SELECTION_SINGLE = 1 << 0, + E_MEMO_SHELL_CONTENT_SELECTION_MULTIPLE = 1 << 1, + E_MEMO_SHELL_CONTENT_SELECTION_CAN_EDIT = 1 << 2, + E_MEMO_SHELL_CONTENT_SELECTION_HAS_URL = 1 << 3 +}; + +struct _EMemoShellContent { + EShellContent parent; + EMemoShellContentPrivate *priv; +}; + +struct _EMemoShellContentClass { + EShellContentClass parent_class; +}; + +GType e_memo_shell_content_get_type (void); +void e_memo_shell_content_register_type + (GTypeModule *type_module); +GtkWidget * e_memo_shell_content_new(EShellView *shell_view); +ECalModel * e_memo_shell_content_get_memo_model + (EMemoShellContent *memo_shell_conent); +ECalComponentPreview * + e_memo_shell_content_get_memo_preview + (EMemoShellContent *memo_shell_content); +EMemoTable * e_memo_shell_content_get_memo_table + (EMemoShellContent *memo_shell_content); +GalViewInstance * + e_memo_shell_content_get_view_instance + (EMemoShellContent *memo_shell_content); +gboolean e_memo_shell_content_get_preview_visible + (EMemoShellContent *memo_shell_content); +void e_memo_shell_content_set_preview_visible + (EMemoShellContent *memo_shell_content, + gboolean preview_visible); + +G_END_DECLS + +#endif /* E_MEMO_SHELL_CONTENT_H */ diff --git a/modules/calendar/e-memo-shell-migrate.c b/modules/calendar/e-memo-shell-migrate.c new file mode 100644 index 0000000000..d2e7df6d1b --- /dev/null +++ b/modules/calendar/e-memo-shell-migrate.c @@ -0,0 +1,257 @@ +/* + * e-memo-shell-migrate.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-memo-shell-migrate.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/calendar-config-keys.h" + +#define WEBCAL_BASE_URI "webcal://" +#define PERSONAL_RELATIVE_URI "system" +#define GROUPWISE_BASE_URI "groupwise://" + +static void +create_memo_sources (EShellBackend *shell_backend, + ESourceList *source_list, + ESourceGroup **on_this_computer, + ESourceGroup **on_the_web, + ESource **personal_source) +{ + GSList *groups; + ESourceGroup *group; + gchar *base_uri, *base_uri_proto; + const gchar *base_dir; + + *on_this_computer = NULL; + *on_the_web = NULL; + *personal_source = NULL; + + base_dir = e_shell_backend_get_config_dir (shell_backend); + base_uri = g_build_filename (base_dir, "local", NULL); + + base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL); + + groups = e_source_list_peek_groups (source_list); + if (groups) { + /* groups are already there, we need to search for things... */ + GSList *g; + + for (g = groups; g; g = g->next) { + + group = E_SOURCE_GROUP (g->data); + + if (!*on_this_computer && !strcmp (base_uri_proto, e_source_group_peek_base_uri (group))) + *on_this_computer = g_object_ref (group); + else if (!*on_the_web && !strcmp (WEBCAL_BASE_URI, e_source_group_peek_base_uri (group))) + *on_the_web = g_object_ref (group); + } + } + + if (*on_this_computer) { + /* make sure "Personal" shows up as a source under + this group */ + GSList *sources = e_source_group_peek_sources (*on_this_computer); + GSList *s; + for (s = sources; s; s = s->next) { + ESource *source = E_SOURCE (s->data); + const gchar *relative_uri; + + relative_uri = e_source_peek_relative_uri (source); + if (relative_uri == NULL) + continue; + if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) { + *personal_source = g_object_ref (source); + break; + } + } + } else { + /* create the local source group */ + group = e_source_group_new (_("On This Computer"), base_uri_proto); + e_source_list_add_group (source_list, group, -1); + + *on_this_computer = group; + } + + if (!*personal_source) { + /* Create the default Person task list */ + ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); + e_source_group_add_source (*on_this_computer, source, -1); + + if (!calendar_config_get_primary_memos () && !calendar_config_get_memos_selected ()) { + GSList selected; + + calendar_config_set_primary_memos (e_source_peek_uid (source)); + + selected.data = (gpointer)e_source_peek_uid (source); + selected.next = NULL; + calendar_config_set_memos_selected (&selected); + } + + e_source_set_color_spec (source, "#BECEDD"); + *personal_source = source; + } + + if (!*on_the_web) { + /* Create the Webcal source group */ + group = e_source_group_new (_("On The Web"), WEBCAL_BASE_URI); + e_source_list_add_group (source_list, group, -1); + + *on_the_web = group; + } + + g_free (base_uri_proto); + g_free (base_uri); +} + +static gboolean +is_groupwise_account (EAccount *account) +{ + if (account->source->url != NULL) { + return g_str_has_prefix (account->source->url, GROUPWISE_BASE_URI); + } else { + return FALSE; + } +} + +static void +add_gw_esource (ESourceList *source_list, const gchar *group_name, const gchar *source_name, CamelURL *url, GConfClient *client) +{ + ESourceGroup *group; + ESource *source; + GSList *ids, *temp; + GError *error = NULL; + gchar *relative_uri; + const gchar *soap_port; + const gchar * use_ssl; + const gchar *poa_address; + const gchar *offline_sync; + + + poa_address = url->host; + if (!poa_address || strlen (poa_address) ==0) + return; + soap_port = camel_url_get_param (url, "soap_port"); + + if (!soap_port || strlen (soap_port) == 0) + soap_port = "7191"; + + use_ssl = camel_url_get_param (url, "use_ssl"); + offline_sync = camel_url_get_param (url, "offline_sync"); + + group = e_source_group_new (group_name, GROUPWISE_BASE_URI); + if (!e_source_list_add_group (source_list, group, -1)) + return; + relative_uri = g_strdup_printf ("%s@%s/", url->user, poa_address); + + source = e_source_new (source_name, relative_uri); + e_source_set_property (source, "auth", "1"); + e_source_set_property (source, "username", url->user); + e_source_set_property (source, "port", camel_url_get_param (url, "soap_port")); + e_source_set_property (source, "auth-domain", "Groupwise"); + e_source_set_property (source, "use_ssl", use_ssl); + e_source_set_property (source, "offline_sync", offline_sync ? "1" : "0" ); + + e_source_set_color_spec (source, "#EEBC60"); + e_source_group_add_source (group, source, -1); + + ids = gconf_client_get_list (client, CALENDAR_CONFIG_MEMOS_SELECTED_MEMOS, GCONF_VALUE_STRING, &error); + if ( error != NULL ) { + g_warning("%s (%s) %s\n", G_STRLOC, G_STRFUNC, error->message); + g_error_free(error); + } + ids = g_slist_append (ids, g_strdup (e_source_peek_uid (source))); + gconf_client_set_list (client, CALENDAR_CONFIG_MEMOS_SELECTED_MEMOS, GCONF_VALUE_STRING, ids, NULL); + temp = ids; + for (; temp != NULL; temp = g_slist_next (temp)) + g_free (temp->data); + + g_slist_free (ids); + g_object_unref (source); + g_object_unref (group); + g_free (relative_uri); +} + +gboolean +e_memo_shell_backend_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint revision, + GError **error) +{ + ESourceGroup *on_this_computer = NULL; + ESourceGroup *on_the_web = NULL; + ESource *personal_source = NULL; + ESourceList *source_list = NULL; + gboolean retval = FALSE; + + source_list = g_object_get_data ( + G_OBJECT (shell_backend), "source-list"); + + /* we call this unconditionally now - create_groups either + creates the groups/sources or it finds the necessary + groups/sources. */ + create_memo_sources ( + shell_backend, source_list, &on_this_computer, + &on_the_web, &personal_source); + + /* Migration for Gw accounts between versions < 2.8 */ + if (major == 2 && minor < 8) { + EAccountList *al; + EAccount *a; + CamelURL *url; + EIterator *it; + GConfClient *gconf_client = gconf_client_get_default (); + al = e_account_list_new (gconf_client); + for (it = e_list_get_iterator((EList *)al); + e_iterator_is_valid(it); + e_iterator_next(it)) { + a = (EAccount *) e_iterator_get(it); + if (!a->enabled || !is_groupwise_account (a)) + continue; + url = camel_url_new (a->source->url, NULL); + add_gw_esource (source_list, a->name, _("Notes"), url, gconf_client); + camel_url_free (url); + } + g_object_unref (al); + g_object_unref (gconf_client); + } + + e_source_list_sync (source_list, NULL); + retval = TRUE; + + if (on_this_computer) + g_object_unref (on_this_computer); + if (on_the_web) + g_object_unref (on_the_web); + if (personal_source) + g_object_unref (personal_source); + + return retval; +} diff --git a/modules/calendar/e-memo-shell-migrate.h b/modules/calendar/e-memo-shell-migrate.h new file mode 100644 index 0000000000..ba163c6950 --- /dev/null +++ b/modules/calendar/e-memo-shell-migrate.h @@ -0,0 +1,38 @@ +/* + * e-memo-shell-backend-migrate.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MEMO_SHELL_BACKEND_MIGRATE_H +#define E_MEMO_SHELL_BACKEND_MIGRATE_H + +#include +#include + +G_BEGIN_DECLS + +gboolean e_memo_shell_backend_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint micro, + GError **error); + +G_END_DECLS + +#endif /* E_MEMO_SHELL_BACKEND_MIGRATE_H */ diff --git a/modules/calendar/e-memo-shell-sidebar.c b/modules/calendar/e-memo-shell-sidebar.c new file mode 100644 index 0000000000..ca5d05c40b --- /dev/null +++ b/modules/calendar/e-memo-shell-sidebar.c @@ -0,0 +1,718 @@ +/* + * e-memo-shell-sidebar.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-memo-shell-sidebar.h" + +#include +#include +#include + +#include "e-util/e-error.h" +#include "e-util/e-util.h" +#include "calendar/common/authentication.h" +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/e-memo-list-selector.h" +#include "calendar/gui/misc.h" + +#include "e-memo-shell-view.h" +#include "e-memo-shell-backend.h" + +#define E_MEMO_SHELL_SIDEBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MEMO_SHELL_SIDEBAR, EMemoShellSidebarPrivate)) + +struct _EMemoShellSidebarPrivate { + GtkWidget *selector; + + /* UID -> Client */ + GHashTable *client_table; +}; + +enum { + PROP_0, + PROP_SELECTOR +}; + +enum { + CLIENT_ADDED, + CLIENT_REMOVED, + STATUS_MESSAGE, + LAST_SIGNAL +}; + +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; +static GType memo_shell_sidebar_type; + +static void +memo_shell_sidebar_emit_client_added (EMemoShellSidebar *memo_shell_sidebar, + ECal *client) +{ + guint signal_id = signals[CLIENT_ADDED]; + + g_signal_emit (memo_shell_sidebar, signal_id, 0, client); +} + +static void +memo_shell_sidebar_emit_client_removed (EMemoShellSidebar *memo_shell_sidebar, + ECal *client) +{ + guint signal_id = signals[CLIENT_REMOVED]; + + g_signal_emit (memo_shell_sidebar, signal_id, 0, client); +} + +static void +memo_shell_sidebar_emit_status_message (EMemoShellSidebar *memo_shell_sidebar, + const gchar *status_message) +{ + guint signal_id = signals[STATUS_MESSAGE]; + + g_signal_emit (memo_shell_sidebar, signal_id, 0, status_message, -1.0); +} + +static void +memo_shell_sidebar_update_timezone (EMemoShellSidebar *memo_shell_sidebar) +{ + GHashTable *client_table; + icaltimezone *zone; + GList *values; + + zone = calendar_config_get_icaltimezone (); + client_table = memo_shell_sidebar->priv->client_table; + values = g_hash_table_get_values (client_table); + + while (values != NULL) { + ECal *client = values->data; + + if (e_cal_get_load_state (client) == E_CAL_LOAD_LOADED) + e_cal_set_default_timezone (client, zone, NULL); + + values = g_list_delete_link (values, values); + } + + /* XXX Need to call e_cal_component_preview_set_default_timezone() + * here but the sidebar is not really supposed to access content + * stuff. I guess we could emit an "update-timezone" signal + * here, but that feels wrong. Maybe this whole thing should + * be in EMemoShellView instead. */ +} + +static void +memo_shell_sidebar_backend_died_cb (EMemoShellSidebar *memo_shell_sidebar, + ECal *client) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + GHashTable *client_table; + ESource *source; + const gchar *uid; + + client_table = memo_shell_sidebar->priv->client_table; + + shell_sidebar = E_SHELL_SIDEBAR (memo_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + source = e_cal_get_source (client); + uid = e_source_peek_uid (source); + + g_object_ref (source); + + g_hash_table_remove (client_table, uid); + memo_shell_sidebar_emit_status_message (memo_shell_sidebar, NULL); + + e_error_run ( + GTK_WINDOW (shell_window), + "calendar:memos-crashed", NULL); + + g_object_unref (source); +} + +static void +memo_shell_sidebar_backend_error_cb (EMemoShellSidebar *memo_shell_sidebar, + const gchar *message, + ECal *client) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + GtkWidget *dialog; + const gchar *uri; + gchar *uri_no_passwd; + + shell_sidebar = E_SHELL_SIDEBAR (memo_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + uri = e_cal_get_uri (client); + uri_no_passwd = get_uri_without_password (uri); + + dialog = gtk_message_dialog_new ( + GTK_WINDOW (shell_window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, + _("Error on %s\n%s"), + uri_no_passwd, message); + + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + + g_free (uri_no_passwd); +} + +static void +memo_shell_sidebar_client_opened_cb (EMemoShellSidebar *memo_shell_sidebar, + ECalendarStatus status, + ECal *client) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + ESource *source; + + source = e_cal_get_source (client); + + shell_sidebar = E_SHELL_SIDEBAR (memo_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + if (status == E_CALENDAR_STATUS_AUTHENTICATION_FAILED || + status == E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED) + auth_cal_forget_password (client); + + switch (status) { + case E_CALENDAR_STATUS_OK: + g_signal_handlers_disconnect_matched ( + client, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, + memo_shell_sidebar_client_opened_cb, NULL); + + memo_shell_sidebar_emit_status_message ( + memo_shell_sidebar, _("Loading memos")); + memo_shell_sidebar_emit_client_added ( + memo_shell_sidebar, client); + memo_shell_sidebar_emit_status_message ( + memo_shell_sidebar, NULL); + break; + + case E_CALENDAR_STATUS_AUTHENTICATION_FAILED: + e_cal_open_async (client, FALSE); + break; + + case E_CALENDAR_STATUS_BUSY: + break; + + case E_CALENDAR_STATUS_REPOSITORY_OFFLINE: + e_error_run ( + GTK_WINDOW (shell_window), + "calendar:prompt-no-contents-offline-memos", + NULL); + break; + + default: + memo_shell_sidebar_emit_client_removed ( + memo_shell_sidebar, client); + break; + } +} + +static void +memo_shell_sidebar_row_changed_cb (EMemoShellSidebar *memo_shell_sidebar, + GtkTreePath *tree_path, + GtkTreeIter *tree_iter, + GtkTreeModel *tree_model) +{ + ESourceSelector *selector; + ESource *source; + + /* XXX ESourceSelector's underlying tree store has only one + * column: ESource objects. While we're not supposed to + * know this, listening for "row-changed" signals from + * the model is easier to deal with than the selector's + * "selection-changed" signal, which doesn't tell you + * _which_ row changed. */ + + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + gtk_tree_model_get (tree_model, tree_iter, 0, &source, -1); + + /* XXX This signal gets emitted a lot while the model is being + * rebuilt, during which time we won't get a valid ESource. + * ESourceSelector should probably block this signal while + * rebuilding the model, but we'll be forgiving and not + * emit a warning. */ + if (!E_IS_SOURCE (source)) + return; + + if (e_source_selector_source_is_selected (selector, source)) + e_memo_shell_sidebar_add_source (memo_shell_sidebar, source); + else + e_memo_shell_sidebar_remove_source (memo_shell_sidebar, source); +} + +static void +memo_shell_sidebar_selection_changed_cb (EMemoShellSidebar *memo_shell_sidebar, + ESourceSelector *selector) +{ + GSList *list, *iter; + + /* This signal is emitted less frequently than "row-changed", + * especially when the model is being rebuilt. So we'll take + * it easy on poor GConf. */ + + list = e_source_selector_get_selection (selector); + + for (iter = list; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + + iter->data = (gpointer) e_source_peek_uid (source); + g_object_unref (source); + } + + calendar_config_set_memos_selected (list); + + g_slist_free (list); +} + +static void +memo_shell_sidebar_primary_selection_changed_cb (EMemoShellSidebar *memo_shell_sidebar, + ESourceSelector *selector) +{ + ESource *source; + const gchar *uid; + + /* XXX ESourceSelector needs a "primary-selection-uid" property + * so we can just bind the property with GConfBridge. */ + + source = e_source_selector_peek_primary_selection (selector); + if (source == NULL) + return; + + uid = e_source_peek_uid (source); + calendar_config_set_primary_memos (uid); +} + +static void +memo_shell_sidebar_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SELECTOR: + g_value_set_object ( + value, e_memo_shell_sidebar_get_selector ( + E_MEMO_SHELL_SIDEBAR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +memo_shell_sidebar_dispose (GObject *object) +{ + EMemoShellSidebarPrivate *priv; + + priv = E_MEMO_SHELL_SIDEBAR_GET_PRIVATE (object); + + if (priv->selector != NULL) { + g_object_unref (priv->selector); + priv->selector = NULL; + } + + g_hash_table_remove_all (priv->client_table); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +memo_shell_sidebar_finalize (GObject *object) +{ + EMemoShellSidebarPrivate *priv; + + priv = E_MEMO_SHELL_SIDEBAR_GET_PRIVATE (object); + + g_hash_table_destroy (priv->client_table); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +memo_shell_sidebar_constructed (GObject *object) +{ + EMemoShellSidebarPrivate *priv; + EShellView *shell_view; + EShellBackend *shell_backend; + EShellSidebar *shell_sidebar; + ESourceSelector *selector; + ESourceList *source_list; + ESource *source; + GtkContainer *container; + GtkTreeModel *model; + GtkWidget *widget; + AtkObject *a11y; + GSList *list, *iter; + gchar *uid; + + priv = E_MEMO_SHELL_SIDEBAR_GET_PRIVATE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_sidebar = E_SHELL_SIDEBAR (object); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + source_list = e_memo_shell_backend_get_source_list ( + E_MEMO_SHELL_BACKEND (shell_backend)); + + container = GTK_CONTAINER (shell_sidebar); + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_container_add (container, widget); + gtk_widget_show (widget); + + container = GTK_CONTAINER (widget); + + widget = e_memo_list_selector_new (source_list); + e_source_selector_set_select_new (E_SOURCE_SELECTOR (widget), TRUE); + gtk_container_add (container, widget); + a11y = gtk_widget_get_accessible (widget); + atk_object_set_name (a11y, _("Memo List Selector")); + priv->selector = g_object_ref (widget); + gtk_widget_show (widget); + + /* Restore the selector state from the last session. */ + + selector = E_SOURCE_SELECTOR (priv->selector); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); + + g_signal_connect_swapped ( + model, "row-changed", + G_CALLBACK (memo_shell_sidebar_row_changed_cb), + object); + + source = NULL; + uid = calendar_config_get_primary_memos (); + if (uid != NULL) + source = e_source_list_peek_source_by_uid (source_list, uid); + if (source == NULL) + source = e_source_list_peek_source_any (source_list); + if (source != NULL) + e_source_selector_set_primary_selection (selector, source); + g_free (uid); + + list = calendar_config_get_memos_selected (); + for (iter = list; iter != NULL; iter = iter->next) { + uid = iter->data; + source = e_source_list_peek_source_by_uid (source_list, uid); + g_free (uid); + + if (source == NULL) + continue; + + e_source_selector_select_source (selector, source); + } + g_slist_free (list); + + /* Listen for subsequent changes to the selector. */ + + g_signal_connect_swapped ( + widget, "selection-changed", + G_CALLBACK (memo_shell_sidebar_selection_changed_cb), + object); + + g_signal_connect_swapped ( + widget, "primary-selection-changed", + G_CALLBACK (memo_shell_sidebar_primary_selection_changed_cb), + object); +} + +static guint32 +memo_shell_sidebar_check_state (EShellSidebar *shell_sidebar) +{ + EMemoShellSidebar *memo_shell_sidebar; + ESourceSelector *selector; + ESource *source; + gboolean is_system = FALSE; + guint32 state = 0; + + memo_shell_sidebar = E_MEMO_SHELL_SIDEBAR (shell_sidebar); + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + + if (source != NULL) { + const gchar *uri; + + uri = e_source_peek_relative_uri (source); + is_system = (uri == NULL || strcmp (uri, "system") == 0); + } + + if (source != NULL) + state |= E_MEMO_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE; + if (is_system) + state |= E_MEMO_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM; + + return state; +} + +static void +memo_shell_sidebar_client_added (EMemoShellSidebar *memo_shell_sidebar, + ECal *client) +{ + memo_shell_sidebar_update_timezone (memo_shell_sidebar); +} + +static void +memo_shell_sidebar_client_removed (EMemoShellSidebar *memo_shell_sidebar, + ECal *client) +{ + ESourceSelector *selector; + GHashTable *client_table; + ESource *source; + const gchar *uid; + + client_table = memo_shell_sidebar->priv->client_table; + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + + g_signal_handlers_disconnect_matched ( + client, G_SIGNAL_MATCH_DATA, 0, 0, + NULL, NULL, memo_shell_sidebar); + + source = e_cal_get_source (client); + e_source_selector_unselect_source (selector, source); + + uid = e_source_peek_uid (source); + g_hash_table_remove (client_table, uid); + + memo_shell_sidebar_emit_status_message (memo_shell_sidebar, NULL); +} + +static void +memo_shell_sidebar_class_init (EMemoShellSidebarClass *class) +{ + GObjectClass *object_class; + EShellSidebarClass *shell_sidebar_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMemoShellSidebarPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->get_property = memo_shell_sidebar_get_property; + object_class->dispose = memo_shell_sidebar_dispose; + object_class->finalize = memo_shell_sidebar_finalize; + object_class->constructed = memo_shell_sidebar_constructed; + + shell_sidebar_class = E_SHELL_SIDEBAR_CLASS (class); + shell_sidebar_class->check_state = memo_shell_sidebar_check_state; + + class->client_added = memo_shell_sidebar_client_added; + class->client_removed = memo_shell_sidebar_client_removed; + + g_object_class_install_property ( + object_class, + PROP_SELECTOR, + g_param_spec_object ( + "selector", + _("Source Selector Widget"), + _("This widget displays groups of memo lists"), + E_TYPE_SOURCE_SELECTOR, + G_PARAM_READABLE)); + + signals[CLIENT_ADDED] = g_signal_new ( + "client-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMemoShellSidebarClass, client_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CAL); + + signals[CLIENT_REMOVED] = g_signal_new ( + "client-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMemoShellSidebarClass, client_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CAL); + + signals[STATUS_MESSAGE] = g_signal_new ( + "status-message", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EMemoShellSidebarClass, status_message), + NULL, NULL, + e_marshal_VOID__STRING_DOUBLE, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_DOUBLE); +} + +static void +memo_shell_sidebar_init (EMemoShellSidebar *memo_shell_sidebar) +{ + GHashTable *client_table; + + client_table = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_object_unref); + + memo_shell_sidebar->priv = + E_MEMO_SHELL_SIDEBAR_GET_PRIVATE (memo_shell_sidebar); + + memo_shell_sidebar->priv->client_table = client_table; + + /* Postpone widget construction until we have a shell view. */ +} + +GType +e_memo_shell_sidebar_get_type (void) +{ + return memo_shell_sidebar_type; +} + +void +e_memo_shell_sidebar_register_type (GTypeModule *type_module) +{ + static const GTypeInfo type_info = { + sizeof (EMemoShellSidebarClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) memo_shell_sidebar_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMemoShellSidebar), + 0, /* n_preallocs */ + (GInstanceInitFunc) memo_shell_sidebar_init, + NULL /* value_table */ + }; + + memo_shell_sidebar_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_SIDEBAR, + "EMemoShellSidebar", &type_info, 0); +} + +GtkWidget * +e_memo_shell_sidebar_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_MEMO_SHELL_SIDEBAR, + "shell-view", shell_view, NULL); +} + +ESourceSelector * +e_memo_shell_sidebar_get_selector (EMemoShellSidebar *memo_shell_sidebar) +{ + g_return_val_if_fail ( + E_IS_MEMO_SHELL_SIDEBAR (memo_shell_sidebar), NULL); + + return E_SOURCE_SELECTOR (memo_shell_sidebar->priv->selector); +} + +void +e_memo_shell_sidebar_add_source (EMemoShellSidebar *memo_shell_sidebar, + ESource *source) +{ + ESourceSelector *selector; + GHashTable *client_table; + ECal *client; + const gchar *uid; + const gchar *uri; + gchar *message; + + g_return_if_fail (E_IS_MEMO_SHELL_SIDEBAR (memo_shell_sidebar)); + g_return_if_fail (E_IS_SOURCE (source)); + + client_table = memo_shell_sidebar->priv->client_table; + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + + uid = e_source_peek_uid (source); + client = g_hash_table_lookup (client_table, uid); + + if (client != NULL) + return; + + client = auth_new_cal_from_source (source, E_CAL_SOURCE_TYPE_JOURNAL); + g_return_if_fail (client != NULL); + + g_signal_connect_swapped ( + client, "backend-died", + G_CALLBACK (memo_shell_sidebar_backend_died_cb), + memo_shell_sidebar); + + g_signal_connect_swapped ( + client, "backend-error", + G_CALLBACK (memo_shell_sidebar_backend_error_cb), + memo_shell_sidebar); + + g_hash_table_insert (client_table, g_strdup (uid), client); + e_source_selector_select_source (selector, source); + + uri = e_cal_get_uri (client); + message = g_strdup_printf (_("Opening memos at %s"), uri); + memo_shell_sidebar_emit_status_message (memo_shell_sidebar, message); + g_free (message); + + g_signal_connect_swapped ( + client, "cal-opened", + G_CALLBACK (memo_shell_sidebar_client_opened_cb), + memo_shell_sidebar); + + e_cal_open_async (client, FALSE); +} + +void +e_memo_shell_sidebar_remove_source (EMemoShellSidebar *memo_shell_sidebar, + ESource *source) +{ + ESourceSelector *selector; + GHashTable *client_table; + ECal *client; + const gchar *uid; + + g_return_if_fail (E_IS_MEMO_SHELL_SIDEBAR (memo_shell_sidebar)); + g_return_if_fail (E_IS_SOURCE (source)); + + client_table = memo_shell_sidebar->priv->client_table; + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + + uid = e_source_peek_uid (source); + client = g_hash_table_lookup (client_table, uid); + + if (client == NULL) + return; + + memo_shell_sidebar_emit_client_removed (memo_shell_sidebar, client); +} diff --git a/modules/calendar/e-memo-shell-sidebar.h b/modules/calendar/e-memo-shell-sidebar.h new file mode 100644 index 0000000000..665c8f218a --- /dev/null +++ b/modules/calendar/e-memo-shell-sidebar.h @@ -0,0 +1,95 @@ +/* + * e-memo-shell-sidebar.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MEMO_SHELL_SIDEBAR_H +#define E_MEMO_SHELL_SIDEBAR_H + +#include +#include + +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_MEMO_SHELL_SIDEBAR \ + (e_memo_shell_sidebar_get_type ()) +#define E_MEMO_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MEMO_SHELL_SIDEBAR, EMemoShellSidebar)) +#define E_MEMO_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MEMO_SHELL_SIDEBAR, EMemoShellSidebarClass)) +#define E_IS_MEMO_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MEMO_SHELL_SIDEBAR)) +#define E_IS_MEMO_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MEMO_SHELL_SIDEBAR)) +#define E_MEMO_SHELL_SIDEBAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MEMO_SHELL_SIDEBAR, EMemoShellSidebarClass)) + +G_BEGIN_DECLS + +typedef struct _EMemoShellSidebar EMemoShellSidebar; +typedef struct _EMemoShellSidebarClass EMemoShellSidebarClass; +typedef struct _EMemoShellSidebarPrivate EMemoShellSidebarPrivate; + +enum { + E_MEMO_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE = 1 << 0, + E_MEMO_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM = 1 << 1 +}; + +struct _EMemoShellSidebar { + EShellSidebar parent; + EMemoShellSidebarPrivate *priv; +}; + +struct _EMemoShellSidebarClass { + EShellSidebarClass parent_class; + + /* Signals */ + void (*client_added) (EMemoShellSidebar *memo_shell_sidebar, + ECal *client); + void (*client_removed) (EMemoShellSidebar *memo_shell_sidebar, + ECal *client); + void (*status_message) (EMemoShellSidebar *memo_shell_sidebar, + const gchar *status_message, + gdouble percent); +}; + +GType e_memo_shell_sidebar_get_type (void); +void e_memo_shell_sidebar_register_type + (GTypeModule *type_module); +GtkWidget * e_memo_shell_sidebar_new(EShellView *shell_view); +ESourceSelector * + e_memo_shell_sidebar_get_selector + (EMemoShellSidebar *memo_shell_sidebar); +void e_memo_shell_sidebar_add_source + (EMemoShellSidebar *memo_shell_sidebar, + ESource *source); +void e_memo_shell_sidebar_remove_source + (EMemoShellSidebar *memo_shell_sidebar, + ESource *source); + +G_END_DECLS + +#endif /* E_MEMO_SHELL_SIDEBAR_H */ diff --git a/modules/calendar/e-memo-shell-view-actions.c b/modules/calendar/e-memo-shell-view-actions.c new file mode 100644 index 0000000000..1736606abe --- /dev/null +++ b/modules/calendar/e-memo-shell-view-actions.c @@ -0,0 +1,949 @@ +/* + * e-memo-shell-view-actions.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-memo-shell-view-private.h" + +static void +action_gal_save_custom_view_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EShellView *shell_view; + GalViewInstance *view_instance; + + /* All shell views respond to the activation of this action, + * which is defined by EShellWindow. But only the currently + * active shell view proceeds with saving the custom view. */ + shell_view = E_SHELL_VIEW (memo_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + view_instance = e_memo_shell_content_get_view_instance (memo_shell_content); + gal_view_instance_save_as (view_instance); +} + +static void +action_memo_clipboard_copy_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + e_memo_table_copy_clipboard (memo_table); +} + +static void +action_memo_clipboard_cut_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + e_memo_table_cut_clipboard (memo_table); +} + +static void +action_memo_clipboard_paste_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + e_memo_table_paste_clipboard (memo_table); +} + +static void +action_memo_delete_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + ECalComponentPreview *memo_preview; + EMemoTable *memo_table; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + memo_preview = e_memo_shell_content_get_memo_preview (memo_shell_content); + + e_memo_shell_view_set_status_message ( + memo_shell_view, _("Deleting selected memos..."), -1.0); + e_memo_table_delete_selected (memo_table); + e_memo_shell_view_set_status_message (memo_shell_view, NULL, -1.0); + + e_cal_component_preview_clear (memo_preview); +} + +static void +action_memo_forward_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + ECalComponent *comp; + icalcomponent *clone; + GSList *list; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only forward the first selected memo. */ + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_component_set_icalcomponent (comp, clone); + itip_send_comp ( + E_CAL_COMPONENT_METHOD_PUBLISH, comp, + comp_data->client, NULL, NULL, NULL, TRUE); + g_object_unref (comp); +} + +static void +action_memo_list_copy_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellSidebar *memo_shell_sidebar; + EShellWindow *shell_window; + EShellView *shell_view; + ESourceSelector *selector; + ESource *source; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (E_IS_SOURCE (source)); + + copy_source_dialog ( + GTK_WINDOW (shell_window), + source, E_CAL_SOURCE_TYPE_JOURNAL); +} + +static void +action_memo_list_delete_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellBackend *memo_shell_backend; + EMemoShellContent *memo_shell_content; + EMemoShellSidebar *memo_shell_sidebar; + EShellWindow *shell_window; + EShellView *shell_view; + EMemoTable *memo_table; + ECal *client; + ECalModel *model; + ESourceSelector *selector; + ESourceGroup *source_group; + ESourceList *source_list; + ESource *source; + gint response; + gchar *uri; + GError *error = NULL; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + memo_shell_backend = memo_shell_view->priv->memo_shell_backend; + source_list = e_memo_shell_backend_get_source_list (memo_shell_backend); + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + model = e_memo_table_get_model (memo_table); + + memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (E_IS_SOURCE (source)); + + /* Ask for confirmation. */ + response = e_error_run ( + GTK_WINDOW (shell_window), + "calendar:prompt-delete-memo-list", + e_source_peek_name (source)); + if (response != GTK_RESPONSE_YES) + return; + + uri = e_source_get_uri (source); + client = e_cal_model_get_client_for_uri (model, uri); + if (client == NULL) + client = e_cal_new_from_uri (uri, E_CAL_SOURCE_TYPE_JOURNAL); + g_free (uri); + + g_return_if_fail (client != NULL); + + if (!e_cal_remove (client, &error)) { + g_warning ("%s", error->message); + g_error_free (error); + return; + } + + if (e_source_selector_source_is_selected (selector, source)) { + e_memo_shell_sidebar_remove_source ( + memo_shell_sidebar, source); + e_source_selector_unselect_source (selector, source); + } + + source_group = e_source_peek_group (source); + e_source_group_remove_source (source_group, source); + + if (!e_source_list_sync (source_list, &error)) { + g_warning ("%s", error->message); + g_error_free (error); + } +} + +static void +action_memo_list_new_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + calendar_setup_new_memo_list (GTK_WINDOW (shell_window)); +} + +static void +action_memo_list_print_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ETable *table; + GtkPrintOperationAction print_action; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + table = e_memo_table_get_table (memo_table); + + print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; + print_table (table, _("Print Memos"), _("Memos"), print_action); +} + +static void +action_memo_list_print_preview_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ETable *table; + GtkPrintOperationAction print_action; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + table = e_memo_table_get_table (memo_table); + + print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW; + print_table (table, _("Print Memos"), _("Memos"), print_action); +} + +static void +action_memo_list_properties_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellSidebar *memo_shell_sidebar; + EShellView *shell_view; + EShellWindow *shell_window; + ESource *source; + ESourceSelector *selector; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (E_IS_SOURCE (source)); + + calendar_setup_edit_memo_list (GTK_WINDOW (shell_window), source); +} + +static void +action_memo_list_rename_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellSidebar *memo_shell_sidebar; + ESourceSelector *selector; + + memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + + e_source_selector_edit_primary_selection (selector); +} + +static void +action_memo_list_select_one_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellSidebar *memo_shell_sidebar; + ESourceSelector *selector; + ESource *primary; + GSList *list, *iter; + + /* XXX ESourceSelector should provide a function for this. */ + + memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + primary = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (primary != NULL); + + list = e_source_selector_get_selection (selector); + for (iter = list; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + + if (source == primary) + continue; + + e_source_selector_unselect_source (selector, source); + } + e_source_selector_free_selection (list); + + e_source_selector_select_source (selector, primary); +} + +static void +action_memo_new_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + ECal *client; + ECalComponent *comp; + CompEditor *editor; + GSList *list; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + client = comp_data->client; + editor = memo_editor_new (client, shell, COMP_EDITOR_NEW_ITEM); + comp = cal_comp_memo_new_with_defaults (client); + comp_editor_edit_comp (editor, comp); + + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (comp); + g_object_unref (client); +} + +static void +action_memo_open_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + GSList *list; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only open the first selected memo. */ + e_memo_shell_view_open_memo (memo_shell_view, comp_data); +} + +static void +action_memo_open_url_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + icalproperty *prop; + const gchar *uri; + GSList *list; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only open the URI of the first selected memo. */ + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_URL_PROPERTY); + g_return_if_fail (prop == NULL); + + uri = icalproperty_get_url (prop); + e_show_uri (GTK_WINDOW (shell_window), uri); +} + +static void +action_memo_preview_cb (GtkToggleAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + gboolean visible; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + visible = gtk_toggle_action_get_active (action); + e_memo_shell_content_set_preview_visible (memo_shell_content, visible); +} + +static void +action_memo_print_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + ECalComponent *comp; + icalcomponent *clone; + GtkPrintOperationAction print_action; + GSList *list; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only print the first selected memo. */ + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; + e_cal_component_set_icalcomponent (comp, clone); + print_comp (comp, comp_data->client, print_action); + g_object_unref (comp); +} + +static void +action_memo_save_as_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + GSList *list; + gchar *filename; + gchar *string; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + filename = e_file_dialog_save (_("Save as..."), NULL); + if (filename == NULL) + return; + + /* XXX We only save the first selected memo. */ + string = e_cal_get_component_as_string ( + comp_data->client, comp_data->icalcomp); + if (string == NULL) { + g_warning ("Could not convert memo to a string"); + return; + } + + e_write_file_uri (filename, string); + + g_free (filename); + g_free (string); +} + +static void +action_memo_search_cb (GtkRadioAction *action, + GtkRadioAction *current, + EMemoShellView *memo_shell_view) +{ + EShellView *shell_view; + EShellContent *shell_content; + const gchar *search_hint; + + /* XXX Figure out a way to handle this in EShellContent + * instead of every shell view having to handle it. + * The problem is EShellContent does not know what + * the search option actions are for this view. It + * would have to dig up the popup menu and retrieve + * the action for each menu item. Seems messy. */ + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + + search_hint = gtk_action_get_label (GTK_ACTION (current)); + e_shell_content_set_search_hint (shell_content, search_hint); +} + +static void +action_search_execute_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EShellView *shell_view; + + /* All shell views respond to the activation of this action, + * which is defined by EShellWindow. But only the currently + * active shell view proceeds with executing the search. */ + shell_view = E_SHELL_VIEW (memo_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + e_memo_shell_view_execute_search (memo_shell_view); +} + +static void +action_search_filter_cb (GtkRadioAction *action, + GtkRadioAction *current, + EMemoShellView *memo_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + gtk_action_activate (ACTION (SEARCH_EXECUTE)); +} + +static GtkActionEntry memo_entries[] = { + + { "memo-clipboard-copy", + GTK_STOCK_COPY, + NULL, + NULL, + N_("Copy selected memo"), + G_CALLBACK (action_memo_clipboard_copy_cb) }, + + { "memo-clipboard-cut", + GTK_STOCK_CUT, + NULL, + NULL, + N_("Cut selected memo"), + G_CALLBACK (action_memo_clipboard_cut_cb) }, + + { "memo-clipboard-paste", + GTK_STOCK_PASTE, + NULL, + NULL, + N_("Paste memo from the clipboard"), + G_CALLBACK (action_memo_clipboard_paste_cb) }, + + { "memo-delete", + GTK_STOCK_DELETE, + N_("_Delete Memo"), + NULL, + N_("Delete selected memos"), + G_CALLBACK (action_memo_delete_cb) }, + + { "memo-forward", + "mail-forward", + N_("_Forward as iCalendar..."), + "f", + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_memo_forward_cb) }, + + { "memo-list-copy", + GTK_STOCK_COPY, + N_("_Copy..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_memo_list_copy_cb) }, + + { "memo-list-delete", + GTK_STOCK_DELETE, + N_("_Delete"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_memo_list_delete_cb) }, + + { "memo-list-new", + "stock_notes", + N_("_New Memo List"), + NULL, + N_("Create a new memo list"), + G_CALLBACK (action_memo_list_new_cb) }, + + { "memo-list-properties", + GTK_STOCK_PROPERTIES, + NULL, + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_memo_list_properties_cb) }, + + { "memo-list-rename", + NULL, + N_("_Rename..."), + "F2", + N_("Rename the selected memo list"), + G_CALLBACK (action_memo_list_rename_cb) }, + + { "memo-list-select-one", + "stock_check-filled", + N_("Show _Only This Memo List"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_memo_list_select_one_cb) }, + + { "memo-new", + "stock_insert-note", + N_("New _Memo"), + NULL, + N_("Create a new memo"), + G_CALLBACK (action_memo_new_cb) }, + + { "memo-open", + GTK_STOCK_OPEN, + N_("_Open Memo"), + "o", + N_("View the selected memo"), + G_CALLBACK (action_memo_open_cb) }, + + { "memo-open-url", + "applications-internet", + N_("Open _Web Page"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_memo_open_url_cb) }, + + { "memo-save-as", + GTK_STOCK_SAVE_AS, + N_("_Save as iCalendar..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_memo_save_as_cb) } +}; + +static EPopupActionEntry memo_popup_entries[] = { + + { "memo-list-popup-copy", + NULL, + "memo-list-copy" }, + + { "memo-list-popup-delete", + NULL, + "memo-list-delete" }, + + { "memo-list-popup-properties", + NULL, + "memo-list-properties" }, + + { "memo-list-popup-rename", + NULL, + "memo-list-rename" }, + + { "memo-list-popup-select-one", + NULL, + "memo-list-select-one" }, + + { "memo-popup-clipboard-copy", + NULL, + "memo-clipboard-copy" }, + + { "memo-popup-clipboard-cut", + NULL, + "memo-clipboard-cut" }, + + { "memo-popup-clipboard-paste", + NULL, + "memo-clipboard-paste" }, + + { "memo-popup-delete", + NULL, + "memo-delete" }, + + { "memo-popup-forward", + NULL, + "memo-forward" }, + + { "memo-popup-open", + NULL, + "memo-open" }, + + { "memo-popup-open-url", + NULL, + "memo-open-url" }, + + { "memo-popup-save-as", + NULL, + "memo-save-as" } +}; + +static GtkToggleActionEntry memo_toggle_entries[] = { + + { "memo-preview", + NULL, + N_("Memo _Preview"), + "m", + N_("Show memo preview pane"), + G_CALLBACK (action_memo_preview_cb), + TRUE } +}; + +static GtkRadioActionEntry memo_filter_entries[] = { + + { "memo-filter-any-category", + NULL, + N_("Any Category"), + NULL, + NULL, + MEMO_FILTER_ANY_CATEGORY }, + + { "memo-filter-unmatched", + NULL, + N_("Unmatched"), + NULL, + NULL, + MEMO_FILTER_UNMATCHED } +}; + +static GtkRadioActionEntry memo_search_entries[] = { + + { "memo-search-any-field-contains", + NULL, + N_("Any field contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + MEMO_SEARCH_ANY_FIELD_CONTAINS }, + + { "memo-search-description-contains", + NULL, + N_("Description contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + MEMO_SEARCH_DESCRIPTION_CONTAINS }, + + { "memo-search-summary-contains", + NULL, + N_("Summary contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + MEMO_SEARCH_SUMMARY_CONTAINS } +}; + +static GtkActionEntry lockdown_printing_entries[] = { + + { "memo-list-print", + GTK_STOCK_PRINT, + NULL, + "p", + N_("Print the list of memos"), + G_CALLBACK (action_memo_list_print_cb) }, + + { "memo-list-print-preview", + GTK_STOCK_PRINT_PREVIEW, + NULL, + NULL, + N_("Preview the list of memos to be printed"), + G_CALLBACK (action_memo_list_print_preview_cb) }, + + { "memo-print", + GTK_STOCK_PRINT, + NULL, + NULL, + N_("Print the selected memo"), + G_CALLBACK (action_memo_print_cb) } +}; + +static EPopupActionEntry lockdown_printing_popup_entries[] = { + + { "memo-popup-print", + NULL, + "memo-print" } +}; + +void +e_memo_shell_view_actions_init (EMemoShellView *memo_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkActionGroup *action_group; + GConfBridge *bridge; + GtkAction *action; + GObject *object; + const gchar *key; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + /* Memo Actions */ + action_group = ACTION_GROUP (MEMOS); + gtk_action_group_add_actions ( + action_group, memo_entries, + G_N_ELEMENTS (memo_entries), memo_shell_view); + e_action_group_add_popup_actions ( + action_group, memo_popup_entries, + G_N_ELEMENTS (memo_popup_entries)); + gtk_action_group_add_toggle_actions ( + action_group, memo_toggle_entries, + G_N_ELEMENTS (memo_toggle_entries), memo_shell_view); + gtk_action_group_add_radio_actions ( + action_group, memo_search_entries, + G_N_ELEMENTS (memo_search_entries), + MEMO_SEARCH_SUMMARY_CONTAINS, + G_CALLBACK (action_memo_search_cb), memo_shell_view); + + /* Lockdown Printing Actions */ + action_group = ACTION_GROUP (LOCKDOWN_PRINTING); + gtk_action_group_add_actions ( + action_group, lockdown_printing_entries, + G_N_ELEMENTS (lockdown_printing_entries), memo_shell_view); + e_action_group_add_popup_actions ( + action_group, lockdown_printing_popup_entries, + G_N_ELEMENTS (lockdown_printing_popup_entries)); + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (ACTION (MEMO_PREVIEW)); + key = "/apps/evolution/calendar/display/show_memo_preview"; + gconf_bridge_bind_property (bridge, key, object, "active"); + + /* Fine tuning. */ + + action = ACTION (MEMO_DELETE); + g_object_set (action, "short-label", _("Delete"), NULL); + + g_signal_connect ( + ACTION (GAL_SAVE_CUSTOM_VIEW), "activate", + G_CALLBACK (action_gal_save_custom_view_cb), memo_shell_view); + + g_signal_connect ( + ACTION (SEARCH_EXECUTE), "activate", + G_CALLBACK (action_search_execute_cb), memo_shell_view); +} + +void +e_memo_shell_view_update_search_filter (EMemoShellView *memo_shell_view) +{ + EShellContent *shell_content; + EShellWindow *shell_window; + EShellView *shell_view; + GtkActionGroup *action_group; + GtkRadioAction *radio_action; + GList *list, *iter; + GSList *group; + gint ii; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + action_group = ACTION_GROUP (MEMOS_FILTER); + e_action_group_remove_all_actions (action_group); + + /* Add the standard filter actions. */ + gtk_action_group_add_radio_actions ( + action_group, memo_filter_entries, + G_N_ELEMENTS (memo_filter_entries), + MEMO_FILTER_ANY_CATEGORY, + G_CALLBACK (action_search_filter_cb), + memo_shell_view); + + /* Retrieve the radio group from an action we just added. */ + list = gtk_action_group_list_actions (action_group); + radio_action = GTK_RADIO_ACTION (list->data); + group = gtk_radio_action_get_group (radio_action); + g_list_free (list); + + /* Build the category actions. */ + + list = e_categories_get_list (); + for (iter = list, ii = 0; iter != NULL; iter = iter->next, ii++) { + const gchar *category_name = iter->data; + const gchar *filename; + GtkAction *action; + gchar *action_name; + + action_name = g_strdup_printf ( + "memo-filter-category-%d", ii); + radio_action = gtk_radio_action_new ( + action_name, category_name, NULL, NULL, ii); + g_free (action_name); + + /* Convert the category icon file to a themed icon name. */ + filename = e_categories_get_icon_file_for (category_name); + if (filename != NULL && *filename != '\0') { + gchar *basename; + gchar *cp; + + basename = g_path_get_basename (filename); + + /* Lose the file extension. */ + if ((cp = strrchr (basename, '.')) != NULL) + *cp = '\0'; + + g_object_set ( + radio_action, "icon-name", basename, NULL); + + g_free (basename); + } + + gtk_radio_action_set_group (radio_action, group); + group = gtk_radio_action_get_group (radio_action); + + /* The action group takes ownership of the action. */ + action = GTK_ACTION (radio_action); + gtk_action_group_add_action (action_group, action); + g_object_unref (radio_action); + } + g_list_free (list); + + /* Use any action in the group; doesn't matter which. */ + e_shell_content_set_filter_action (shell_content, radio_action); + + ii = MEMO_FILTER_UNMATCHED; + e_shell_content_add_filter_separator_after (shell_content, ii); +} diff --git a/modules/calendar/e-memo-shell-view-actions.h b/modules/calendar/e-memo-shell-view-actions.h new file mode 100644 index 0000000000..d6fd3ca514 --- /dev/null +++ b/modules/calendar/e-memo-shell-view-actions.h @@ -0,0 +1,87 @@ +/* + * e-memo-shell-view-actions.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MEMO_SHELL_VIEW_ACTIONS_H +#define E_MEMO_SHELL_VIEW_ACTIONS_H + +#include + +/* Memo Actions */ +#define E_SHELL_WINDOW_ACTION_MEMO_CLIPBOARD_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-clipboard-copy") +#define E_SHELL_WINDOW_ACTION_MEMO_CLIPBOARD_CUT(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-clipboard-cut") +#define E_SHELL_WINDOW_ACTION_MEMO_CLIPBOARD_PASTE(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-clipboard-paste") +#define E_SHELL_WINDOW_ACTION_MEMO_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-delete") +#define E_SHELL_WINDOW_ACTION_MEMO_FORWARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-forward") +#define E_SHELL_WINDOW_ACTION_MEMO_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-new") +#define E_SHELL_WINDOW_ACTION_MEMO_OPEN(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-open") +#define E_SHELL_WINDOW_ACTION_MEMO_OPEN_URL(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-open-url") +#define E_SHELL_WINDOW_ACTION_MEMO_PREVIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-preview") +#define E_SHELL_WINDOW_ACTION_MEMO_PRINT(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-print") +#define E_SHELL_WINDOW_ACTION_MEMO_SAVE_AS(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-save-as") + +/* Memo List Actions */ +#define E_SHELL_WINDOW_ACTION_MEMO_LIST_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-list-copy") +#define E_SHELL_WINDOW_ACTION_MEMO_LIST_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-list-delete") +#define E_SHELL_WINDOW_ACTION_MEMO_LIST_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-list-new") +#define E_SHELL_WINDOW_ACTION_MEMO_LIST_PRINT(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-list-print") +#define E_SHELL_WINDOW_ACTION_MEMO_LIST_PRINT_PREVIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-list-print-preview") +#define E_SHELL_WINDOW_ACTION_MEMO_LIST_PROPERTIES(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-list-properties") +#define E_SHELL_WINDOW_ACTION_MEMO_LIST_RENAME(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-list-rename") +#define E_SHELL_WINDOW_ACTION_MEMO_LIST_SELECT_ONE(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-list-select-one") + +/* Memo Query Actions */ +#define E_SHELL_WINDOW_ACTION_MEMO_FILTER_ANY_CATEGORY(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-filter-any-category") +#define E_SHELL_WINDOW_ACTION_MEMO_FILTER_UNMATCHED(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-filter-unmatched") +#define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_ANY_FIELD_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-search-any-field-contains") +#define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_DESCRIPTION_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-search-description-contains") +#define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_SUMMARY_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-search-summary-contains") + +/* Action Groups */ +#define E_SHELL_WINDOW_ACTION_GROUP_MEMOS(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "memos") +#define E_SHELL_WINDOW_ACTION_GROUP_MEMOS_FILTER(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "memos-filter") + +#endif /* E_MEMO_SHELL_VIEW_ACTIONS_H */ diff --git a/modules/calendar/e-memo-shell-view-private.c b/modules/calendar/e-memo-shell-view-private.c new file mode 100644 index 0000000000..69d6c0afe2 --- /dev/null +++ b/modules/calendar/e-memo-shell-view-private.c @@ -0,0 +1,524 @@ +/* + * e-memo-shell-view-private.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-memo-shell-view-private.h" + +#include "widgets/menus/gal-view-factory-etable.h" + +static void +memo_shell_view_table_popup_event_cb (EShellView *shell_view, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/memo-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); +} + +static void +memo_shell_view_table_user_created_cb (EMemoShellView *memo_shell_view, + EMemoTable *memo_table) +{ + EMemoShellSidebar *memo_shell_sidebar; + ECalModel *model; + ECal *client; + ESource *source; + + /* This is the "Click to Add" handler. */ + + model = e_memo_table_get_model (memo_table); + client = e_cal_model_get_default_client (model); + source = e_cal_get_source (client); + + memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; + e_memo_shell_sidebar_add_source (memo_shell_sidebar, source); + + e_cal_model_add_client (model, client); +} + +static void +memo_shell_view_selector_client_added_cb (EMemoShellView *memo_shell_view, + ECal *client) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ECalModel *model; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + model = e_memo_table_get_model (memo_table); + + e_cal_model_add_client (model, client); +} + +static void +memo_shell_view_selector_client_removed_cb (EMemoShellView *memo_shell_view, + ECal *client) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ECalModel *model; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + model = e_memo_table_get_model (memo_table); + + e_cal_model_remove_client (model, client); +} + +static gboolean +memo_shell_view_selector_popup_event_cb (EShellView *shell_view, + ESource *primary_source, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/memo-list-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); + + return TRUE; +} + +static void +memo_shell_view_load_view_collection (EShellViewClass *shell_view_class) +{ + GalViewCollection *collection; + GalViewFactory *factory; + ETableSpecification *spec; + const gchar *base_dir; + gchar *filename; + + collection = shell_view_class->view_collection; + + base_dir = EVOLUTION_ETSPECDIR; + spec = e_table_specification_new (); + filename = g_build_filename (base_dir, ETSPEC_FILENAME, NULL); + if (!e_table_specification_load_from_file (spec, filename)) + g_critical ("Unable to load ETable specification file " + "for memos"); + g_free (filename); + + factory = gal_view_factory_etable_new (spec); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + g_object_unref (spec); + + gal_view_collection_load (collection); +} + +static void +memo_shell_view_notify_view_id_cb (EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + GalViewInstance *view_instance; + const gchar *view_id; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + view_instance = + e_memo_shell_content_get_view_instance (memo_shell_content); + view_id = e_shell_view_get_view_id (E_SHELL_VIEW (memo_shell_view)); + + /* A NULL view ID implies we're in a custom view. But you can + * only get to a custom view via the "Define Views" dialog, which + * would have already modified the view instance appropriately. + * Furthermore, there's no way to refer to a custom view by ID + * anyway, since custom views have no IDs. */ + if (view_id == NULL) + return; + + gal_view_instance_set_current_view_id (view_instance, view_id); +} + +void +e_memo_shell_view_private_init (EMemoShellView *memo_shell_view, + EShellViewClass *shell_view_class) +{ + if (!gal_view_collection_loaded (shell_view_class->view_collection)) + memo_shell_view_load_view_collection (shell_view_class); + + g_signal_connect ( + memo_shell_view, "notify::view-id", + G_CALLBACK (memo_shell_view_notify_view_id_cb), NULL); +} + +void +e_memo_shell_view_private_constructed (EMemoShellView *memo_shell_view) +{ + EMemoShellViewPrivate *priv = memo_shell_view->priv; + EMemoShellContent *memo_shell_content; + EMemoShellSidebar *memo_shell_sidebar; + EShellView *shell_view; + EShellBackend *shell_backend; + EShellContent *shell_content; + EShellSidebar *shell_sidebar; + EShellWindow *shell_window; + EMemoTable *memo_table; + ECalModel *model; + ETable *table; + ESourceSelector *selector; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + e_shell_window_add_action_group (shell_window, "memos"); + e_shell_window_add_action_group (shell_window, "memos-filter"); + + /* Cache these to avoid lots of awkward casting. */ + priv->memo_shell_backend = g_object_ref (shell_backend); + priv->memo_shell_content = g_object_ref (shell_content); + priv->memo_shell_sidebar = g_object_ref (shell_sidebar); + + memo_shell_content = E_MEMO_SHELL_CONTENT (shell_content); + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + model = e_memo_table_get_model (memo_table); + table = e_memo_table_get_table (memo_table); + + memo_shell_sidebar = E_MEMO_SHELL_SIDEBAR (shell_sidebar); + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + + g_signal_connect_swapped ( + memo_table, "open-component", + G_CALLBACK (e_memo_shell_view_open_memo), + memo_shell_view); + + g_signal_connect_swapped ( + memo_table, "popup-event", + G_CALLBACK (memo_shell_view_table_popup_event_cb), + memo_shell_view); + + g_signal_connect_swapped ( + memo_table, "status-message", + G_CALLBACK (e_memo_shell_view_set_status_message), + memo_shell_view); + + g_signal_connect_swapped ( + memo_table, "user-created", + G_CALLBACK (memo_shell_view_table_user_created_cb), + memo_shell_view); + + g_signal_connect_swapped ( + model, "model-changed", + G_CALLBACK (e_memo_shell_view_update_sidebar), + memo_shell_view); + + g_signal_connect_swapped ( + model, "model-rows-deleted", + G_CALLBACK (e_memo_shell_view_update_sidebar), + memo_shell_view); + + g_signal_connect_swapped ( + model, "model-rows-inserted", + G_CALLBACK (e_memo_shell_view_update_sidebar), + memo_shell_view); + + g_signal_connect_swapped ( + table, "selection-change", + G_CALLBACK (e_memo_shell_view_update_sidebar), + memo_shell_view); + + g_signal_connect_swapped ( + memo_shell_sidebar, "client-added", + G_CALLBACK (memo_shell_view_selector_client_added_cb), + memo_shell_view); + + g_signal_connect_swapped ( + memo_shell_sidebar, "client-removed", + G_CALLBACK (memo_shell_view_selector_client_removed_cb), + memo_shell_view); + + g_signal_connect_swapped ( + memo_shell_sidebar, "status-message", + G_CALLBACK (e_memo_shell_view_set_status_message), + memo_shell_view); + + g_signal_connect_swapped ( + selector, "popup-event", + G_CALLBACK (memo_shell_view_selector_popup_event_cb), + memo_shell_view); + + g_signal_connect_swapped ( + selector, "primary-selection-changed", + G_CALLBACK (e_shell_view_update_actions), + memo_shell_view); + + e_categories_register_change_listener ( + G_CALLBACK (e_memo_shell_view_update_search_filter), + memo_shell_view); + + e_memo_shell_view_actions_init (memo_shell_view); + e_memo_shell_view_update_sidebar (memo_shell_view); + e_memo_shell_view_update_search_filter (memo_shell_view); + + e_memo_shell_view_execute_search (memo_shell_view); +} + +void +e_memo_shell_view_private_dispose (EMemoShellView *memo_shell_view) +{ + EMemoShellViewPrivate *priv = memo_shell_view->priv; + + DISPOSE (priv->memo_shell_backend); + DISPOSE (priv->memo_shell_content); + DISPOSE (priv->memo_shell_sidebar); + + if (memo_shell_view->priv->activity != NULL) { + /* XXX Activity is not cancellable. */ + e_activity_complete (memo_shell_view->priv->activity); + g_object_unref (memo_shell_view->priv->activity); + memo_shell_view->priv->activity = NULL; + } +} + +void +e_memo_shell_view_private_finalize (EMemoShellView *memo_shell_view) +{ + /* XXX Nothing to do? */ +} + +void +e_memo_shell_view_execute_search (EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EShellView *shell_view; + EShellWindow *shell_window; + EShellContent *shell_content; + GtkAction *action; + GString *string; + ECalComponentPreview *memo_preview; + EMemoTable *memo_table; + ECalModel *model; + FilterRule *rule; + const gchar *format; + const gchar *text; + gchar *query; + gchar *temp; + gint value; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + text = e_shell_content_get_search_text (shell_content); + + shell_window = e_shell_view_get_shell_window (shell_view); + action = ACTION (MEMO_SEARCH_ANY_FIELD_CONTAINS); + value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + + if (text == NULL || *text == '\0') { + text = ""; + value = MEMO_SEARCH_SUMMARY_CONTAINS; + } + + switch (value) { + default: + text = ""; + /* fall through */ + + case MEMO_SEARCH_SUMMARY_CONTAINS: + format = "(contains? \"summary\" %s)"; + break; + + case MEMO_SEARCH_DESCRIPTION_CONTAINS: + format = "(contains? \"description\" %s)"; + break; + + case MEMO_SEARCH_ANY_FIELD_CONTAINS: + format = "(contains? \"any\" %s)"; + break; + } + + /* Build the query. */ + string = g_string_new (""); + e_sexp_encode_string (string, text); + query = g_strdup_printf (format, string->str); + g_string_free (string, TRUE); + + /* Apply selected filter. */ + value = e_shell_content_get_filter_value (shell_content); + switch (value) { + case MEMO_FILTER_ANY_CATEGORY: + break; + + case MEMO_FILTER_UNMATCHED: + temp = g_strdup_printf ( + "(and (has-categories? #f) %s", query); + g_free (query); + query = temp; + break; + + default: + { + GList *categories; + const gchar *category_name; + + categories = e_categories_get_list (); + category_name = g_list_nth_data (categories, value); + g_list_free (categories); + + temp = g_strdup_printf ( + "(and (has-categories? \"%s\") %s)", + category_name, query); + g_free (query); + query = temp; + } + } + + /* XXX This is wrong. We need to programmatically construct a + * FilterRule, tell it to build code, and pass the resulting + * expression string to ECalModel. */ + rule = filter_rule_new (); + e_shell_content_set_search_rule (shell_content, rule); + g_object_unref (rule); + + /* Submit the query. */ + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + model = e_memo_table_get_model (memo_table); + e_cal_model_set_search_query (model, query); + g_free (query); + + memo_preview = + e_memo_shell_content_get_memo_preview (memo_shell_content); + e_cal_component_preview_clear (memo_preview); +} + +void +e_memo_shell_view_open_memo (EMemoShellView *memo_shell_view, + ECalModelComponent *comp_data) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + CompEditor *editor; + CompEditorFlags flags = 0; + ECalComponent *comp; + icalcomponent *clone; + const gchar *uid; + + g_return_if_fail (E_IS_MEMO_SHELL_VIEW (memo_shell_view)); + g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data)); + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + + uid = icalcomponent_get_uid (comp_data->icalcomp); + editor = comp_editor_find_instance (uid); + + if (editor != NULL) + goto exit; + + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_component_set_icalcomponent (comp, clone); + + if (e_cal_component_has_organizer (comp)) + flags |= COMP_EDITOR_IS_SHARED; + + if (itip_organizer_is_user (comp, comp_data->client)) + flags |= COMP_EDITOR_USER_ORG; + + editor = memo_editor_new (comp_data->client, shell, flags); + comp_editor_edit_comp (editor, comp); + + g_object_unref (comp); + +exit: + gtk_window_present (GTK_WINDOW (editor)); +} + +void +e_memo_shell_view_set_status_message (EMemoShellView *memo_shell_view, + const gchar *status_message, + gdouble percent) +{ + EActivity *activity; + EShellView *shell_view; + EShellBackend *shell_backend; + + g_return_if_fail (E_IS_MEMO_SHELL_VIEW (memo_shell_view)); + + activity = memo_shell_view->priv->activity; + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + if (status_message == NULL || *status_message == '\0') { + if (activity != NULL) { + e_activity_complete (activity); + g_object_unref (activity); + activity = NULL; + } + + } else if (activity == NULL) { + activity = e_activity_new (status_message); + e_activity_set_percent (activity, percent); + e_shell_backend_add_activity (shell_backend, activity); + + } else { + e_activity_set_percent (activity, percent); + e_activity_set_primary_text (activity, status_message); + } + + memo_shell_view->priv->activity = activity; +} + +void +e_memo_shell_view_update_sidebar (EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EShellView *shell_view; + EShellSidebar *shell_sidebar; + EMemoTable *memo_table; + ECalModel *model; + ETable *table; + GString *string; + const gchar *format; + gint n_rows; + gint n_selected; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + model = e_memo_table_get_model (memo_table); + table = e_memo_table_get_table (memo_table); + + n_rows = e_table_model_row_count (E_TABLE_MODEL (model)); + n_selected = e_table_selected_count (table); + + string = g_string_sized_new (64); + + format = ngettext ("%d memo", "%d memos", n_rows); + g_string_append_printf (string, format, n_rows); + + if (n_selected > 0) { + format = _("%d selected"); + g_string_append_len (string, ", ", 2); + g_string_append_printf (string, format, n_selected); + } + + e_shell_sidebar_set_secondary_text (shell_sidebar, string->str); + + g_string_free (string, TRUE); +} diff --git a/modules/calendar/e-memo-shell-view-private.h b/modules/calendar/e-memo-shell-view-private.h new file mode 100644 index 0000000000..c41eaed7c0 --- /dev/null +++ b/modules/calendar/e-memo-shell-view-private.h @@ -0,0 +1,126 @@ +/* + * e-memo-shell-view-private.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MEMO_SHELL_VIEW_PRIVATE_H +#define E_MEMO_SHELL_VIEW_PRIVATE_H + +#include "e-memo-shell-view.h" + +#include +#include +#include +#include + +#include "e-util/e-dialog-utils.h" +#include "e-util/e-error.h" +#include "e-util/e-util.h" +#include "e-util/gconf-bridge.h" +#include "widgets/misc/e-popup-action.h" + +#include "calendar/gui/comp-util.h" +#include "calendar/gui/e-cal-component-preview.h" +#include "calendar/gui/e-calendar-selector.h" +#include "calendar/gui/print.h" +#include "calendar/gui/dialogs/calendar-setup.h" +#include "calendar/gui/dialogs/copy-source-dialog.h" +#include "calendar/gui/dialogs/memo-editor.h" + +#include "e-memo-shell-backend.h" +#include "e-memo-shell-content.h" +#include "e-memo-shell-sidebar.h" +#include "e-memo-shell-view-actions.h" + +#define E_MEMO_SHELL_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MEMO_SHELL_VIEW, EMemoShellViewPrivate)) + +/* Shorthand, requires a variable named "shell_window". */ +#define ACTION(name) \ + (E_SHELL_WINDOW_ACTION_##name (shell_window)) +#define ACTION_GROUP(name) \ + (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) + +/* For use in dispose() methods. */ +#define DISPOSE(obj) \ + G_STMT_START { \ + if ((obj) != NULL) { g_object_unref (obj); (obj) = NULL; } \ + } G_STMT_END + +/* ETable Specifications */ +#define ETSPEC_FILENAME "e-memo-table.etspec" + +G_BEGIN_DECLS + +/* Filter items are displayed in ascending order. + * Non-negative values are reserved for categories. */ +enum { + MEMO_FILTER_ANY_CATEGORY = -2, + MEMO_FILTER_UNMATCHED = -1 +}; + +/* Search items are displayed in ascending order. */ +enum { + MEMO_SEARCH_SUMMARY_CONTAINS, + MEMO_SEARCH_DESCRIPTION_CONTAINS, + MEMO_SEARCH_ANY_FIELD_CONTAINS +}; + +struct _EMemoShellViewPrivate { + + /* These are just for convenience. */ + EMemoShellBackend *memo_shell_backend; + EMemoShellContent *memo_shell_content; + EMemoShellSidebar *memo_shell_sidebar; + + EActivity *activity; +}; + +void e_memo_shell_view_private_init + (EMemoShellView *memo_shell_view, + EShellViewClass *shell_view_class); +void e_memo_shell_view_private_constructed + (EMemoShellView *memo_shell_view); +void e_memo_shell_view_private_dispose + (EMemoShellView *memo_shell_view); +void e_memo_shell_view_private_finalize + (EMemoShellView *memo_shell_view); + +/* Private Utilities */ + +void e_memo_shell_view_actions_init + (EMemoShellView *memo_shell_view); +void e_memo_shell_view_execute_search + (EMemoShellView *memo_shell_view); +void e_memo_shell_view_open_memo + (EMemoShellView *memo_shell_view, + ECalModelComponent *comp_data); +void e_memo_shell_view_set_status_message + (EMemoShellView *memo_shell_view, + const gchar *status_message, + gdouble percent); +void e_memo_shell_view_update_sidebar + (EMemoShellView *memo_shell_view); +void e_memo_shell_view_update_search_filter + (EMemoShellView *memo_shell_view); + +G_END_DECLS + +#endif /* E_MEMO_SHELL_VIEW_PRIVATE_H */ diff --git a/modules/calendar/e-memo-shell-view.c b/modules/calendar/e-memo-shell-view.c new file mode 100644 index 0000000000..e2964b061c --- /dev/null +++ b/modules/calendar/e-memo-shell-view.c @@ -0,0 +1,222 @@ +/* + * e-memo-shell-view.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-memo-shell-view-private.h" + +static gpointer parent_class; +static GType memo_shell_view_type; + +static void +memo_shell_view_dispose (GObject *object) +{ + e_memo_shell_view_private_dispose (E_MEMO_SHELL_VIEW (object)); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +memo_shell_view_finalize (GObject *object) +{ + e_memo_shell_view_private_finalize (E_MEMO_SHELL_VIEW (object)); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +memo_shell_view_constructed (GObject *object) +{ + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + e_memo_shell_view_private_constructed (E_MEMO_SHELL_VIEW (object)); +} + +static void +memo_shell_view_update_actions (EShellView *shell_view) +{ + EMemoShellViewPrivate *priv; + EShellContent *shell_content; + EShellSidebar *shell_sidebar; + EShellWindow *shell_window; + GtkAction *action; + const gchar *label; + gboolean sensitive; + guint32 state; + + /* Be descriptive. */ + gboolean any_memos_selected; + gboolean has_primary_source; + gboolean multiple_memos_selected; + gboolean primary_source_is_system; + gboolean selection_has_url; + gboolean single_memo_selected; + gboolean sources_are_editable; + + priv = E_MEMO_SHELL_VIEW_GET_PRIVATE (shell_view); + + shell_window = e_shell_view_get_shell_window (shell_view); + + shell_content = e_shell_view_get_shell_content (shell_view); + state = e_shell_content_check_state (shell_content); + + single_memo_selected = + (state & E_MEMO_SHELL_CONTENT_SELECTION_SINGLE); + multiple_memos_selected = + (state & E_MEMO_SHELL_CONTENT_SELECTION_MULTIPLE); + sources_are_editable = + (state & E_MEMO_SHELL_CONTENT_SELECTION_CAN_EDIT); + selection_has_url = + (state & E_MEMO_SHELL_CONTENT_SELECTION_HAS_URL); + + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + state = e_shell_sidebar_check_state (shell_sidebar); + + has_primary_source = + (state & E_MEMO_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE); + primary_source_is_system = + (state & E_MEMO_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM); + + any_memos_selected = + (single_memo_selected || multiple_memos_selected); + + action = ACTION (MEMO_CLIPBOARD_COPY); + sensitive = any_memos_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_CLIPBOARD_CUT); + sensitive = any_memos_selected && sources_are_editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_CLIPBOARD_PASTE); + sensitive = sources_are_editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_DELETE); + sensitive = any_memos_selected && sources_are_editable; + gtk_action_set_sensitive (action, sensitive); + if (multiple_memos_selected) + label = _("Delete Memos"); + else + label = _("Delete Memo"); + g_object_set (action, "label", label, NULL); + + action = ACTION (MEMO_FORWARD); + sensitive = single_memo_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_LIST_COPY); + sensitive = has_primary_source; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_LIST_DELETE); + sensitive = has_primary_source && !primary_source_is_system; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_LIST_PROPERTIES); + sensitive = has_primary_source; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_LIST_RENAME); + sensitive = has_primary_source; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_OPEN); + sensitive = single_memo_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_OPEN_URL); + sensitive = single_memo_selected && selection_has_url; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_PRINT); + sensitive = single_memo_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_SAVE_AS); + sensitive = single_memo_selected; + gtk_action_set_sensitive (action, sensitive); +} + +static void +memo_shell_view_class_init (EMemoShellViewClass *class, + GTypeModule *type_module) +{ + GObjectClass *object_class; + EShellViewClass *shell_view_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMemoShellViewPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->dispose = memo_shell_view_dispose; + object_class->finalize = memo_shell_view_finalize; + object_class->constructed = memo_shell_view_constructed; + + shell_view_class = E_SHELL_VIEW_CLASS (class); + shell_view_class->label = _("Memos"); + shell_view_class->icon_name = "evolution-memos"; + shell_view_class->ui_definition = "evolution-memos.ui"; + shell_view_class->ui_manager_id = "org.gnome.evolution.memos"; + shell_view_class->search_options = "/memo-search-options"; + shell_view_class->search_rules = "memotypes.xml"; + shell_view_class->new_shell_content = e_memo_shell_content_new; + shell_view_class->new_shell_sidebar = e_memo_shell_sidebar_new; + shell_view_class->update_actions = memo_shell_view_update_actions; +} + +static void +memo_shell_view_init (EMemoShellView *memo_shell_view, + EShellViewClass *shell_view_class) +{ + memo_shell_view->priv = + E_MEMO_SHELL_VIEW_GET_PRIVATE (memo_shell_view); + + e_memo_shell_view_private_init (memo_shell_view, shell_view_class); +} + +GType +e_memo_shell_view_get_type (void) +{ + return memo_shell_view_type; +} + +void +e_memo_shell_view_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (EMemoShellViewClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) memo_shell_view_class_init, + (GClassFinalizeFunc) NULL, + type_module, + sizeof (EMemoShellView), + 0, /* n_preallocs */ + (GInstanceInitFunc) memo_shell_view_init, + NULL /* value_table */ + }; + + memo_shell_view_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_VIEW, + "EMemoShellView", &type_info, 0); +} diff --git a/modules/calendar/e-memo-shell-view.h b/modules/calendar/e-memo-shell-view.h new file mode 100644 index 0000000000..686ae734c9 --- /dev/null +++ b/modules/calendar/e-memo-shell-view.h @@ -0,0 +1,67 @@ +/* + * e-memo-shell-view.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MEMO_SHELL_VIEW_H +#define E_MEMO_SHELL_VIEW_H + +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_MEMO_SHELL_VIEW \ + (e_memo_shell_view_get_type ()) +#define E_MEMO_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MEMO_SHELL_VIEW, EMemoShellView)) +#define E_MEMO_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MEMO_SHELL_VIEW, EMemoShellViewClass)) +#define E_IS_MEMO_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MEMO_SHELL_VIEW)) +#define E_IS_MEMO_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MEMO_SHELL_VIEW)) +#define E_MEMO_SHELL_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MEMO_SHELL_VIEW, EMemoShellViewClass)) + +G_BEGIN_DECLS + +typedef struct _EMemoShellView EMemoShellView; +typedef struct _EMemoShellViewClass EMemoShellViewClass; +typedef struct _EMemoShellViewPrivate EMemoShellViewPrivate; + +struct _EMemoShellView { + EShellView parent; + EMemoShellViewPrivate *priv; +}; + +struct _EMemoShellViewClass { + EShellViewClass parent_class; +}; + +GType e_memo_shell_view_get_type (void); +void e_memo_shell_view_register_type (GTypeModule *type_module); + +G_END_DECLS + +#endif /* E_MEMO_SHELL_VIEW_H */ diff --git a/modules/calendar/e-task-shell-backend.c b/modules/calendar/e-task-shell-backend.c new file mode 100644 index 0000000000..6bded3e412 --- /dev/null +++ b/modules/calendar/e-task-shell-backend.c @@ -0,0 +1,621 @@ +/* + * e-task-shell-backend.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-task-shell-backend.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "shell/e-shell.h" +#include "shell/e-shell-backend.h" +#include "shell/e-shell-window.h" + +#include "calendar/common/authentication.h" +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/comp-util.h" +#include "calendar/gui/dialogs/calendar-setup.h" +#include "calendar/gui/dialogs/task-editor.h" + +#include "e-task-shell-content.h" +#include "e-task-shell-migrate.h" +#include "e-task-shell-sidebar.h" +#include "e-task-shell-view.h" + +#define E_TASK_SHELL_BACKEND_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_TASK_SHELL_BACKEND, ETaskShellBackendPrivate)) + +#define WEB_BASE_URI "webcal://" +#define PERSONAL_RELATIVE_URI "system" + +struct _ETaskShellBackendPrivate { + ESourceList *source_list; +}; + +enum { + PROP_0, + PROP_SOURCE_LIST +}; + +static gpointer parent_class; +static GType task_shell_backend_type; + +static void +task_module_ensure_sources (EShellBackend *shell_backend) +{ + /* XXX This is basically the same algorithm across all modules. + * Maybe we could somehow integrate this into EShellBackend? */ + + ETaskShellBackendPrivate *priv; + ESourceGroup *on_this_computer; + ESourceGroup *on_the_web; + ESource *personal; + GSList *groups, *iter; + const gchar *data_dir; + const gchar *name; + gchar *base_uri; + gchar *filename; + + on_this_computer = NULL; + on_the_web = NULL; + personal = NULL; + + priv = E_TASK_SHELL_BACKEND_GET_PRIVATE (shell_backend); + + if (!e_cal_get_sources (&priv->source_list, E_CAL_SOURCE_TYPE_TODO, NULL)) { + g_warning ("Could not get task sources from GConf!"); + return; + } + + data_dir = e_shell_backend_get_data_dir (shell_backend); + filename = g_build_filename (data_dir, "local", NULL); + base_uri = g_filename_to_uri (filename, NULL, NULL); + g_free (filename); + + groups = e_source_list_peek_groups (priv->source_list); + for (iter = groups; iter != NULL; iter = iter->next) { + ESourceGroup *source_group = iter->data; + const gchar *group_base_uri; + + group_base_uri = e_source_group_peek_base_uri (source_group); + + /* Compare only "file://" part. If the user's home + * changes, we do not want to create another group. */ + if (on_this_computer == NULL && + strncmp (base_uri, group_base_uri, 7) == 0) + on_this_computer = source_group; + + else if (on_the_web == NULL && + strcmp (WEB_BASE_URI, group_base_uri) == 0) + on_the_web = source_group; + } + + name = _("On This Computer"); + + if (on_this_computer != NULL) { + GSList *sources; + const gchar *group_base_uri; + + /* Force the group name to the current locale. */ + e_source_group_set_name (on_this_computer, name); + + sources = e_source_group_peek_sources (on_this_computer); + group_base_uri = e_source_group_peek_base_uri (on_this_computer); + + /* Make sure this group includes a "Personal" source. */ + for (iter = sources; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + const gchar *relative_uri; + + relative_uri = e_source_peek_relative_uri (source); + if (relative_uri == NULL) + continue; + + if (strcmp (PERSONAL_RELATIVE_URI, relative_uri) != 0) + continue; + + personal = source; + break; + } + + /* Make sure we have the correct base URI. This can + * change when the user's home directory changes. */ + if (strcmp (base_uri, group_base_uri) != 0) { + e_source_group_set_base_uri ( + on_this_computer, base_uri); + + /* XXX We shouldn't need this sync call here as + * set_base_uri() results in synching to GConf, + * but that happens in an idle loop and too late + * to prevent the user from seeing a "Cannot + * Open ... because of invalid URI" error. */ + e_source_list_sync (priv->source_list, NULL); + } + + } else { + ESourceGroup *source_group; + + source_group = e_source_group_new (name, base_uri); + e_source_list_add_group (priv->source_list, source_group, -1); + g_object_unref (source_group); + } + + name = _("Personal"); + + if (personal == NULL) { + ESource *source; + GSList *selected; + gchar *primary; + + source = e_source_new (name, PERSONAL_RELATIVE_URI); + e_source_group_add_source (on_this_computer, source, -1); + g_object_unref (source); + + primary = calendar_config_get_primary_tasks (); + selected = calendar_config_get_tasks_selected (); + + if (primary == NULL && selected == NULL) { + const gchar *uid; + + uid = e_source_peek_uid (source); + selected = g_slist_prepend (NULL, g_strdup (uid)); + + calendar_config_set_primary_tasks (uid); + calendar_config_set_tasks_selected (selected); + } + + g_slist_foreach (selected, (GFunc) g_free, NULL); + g_slist_free (selected); + g_free (primary); + } else { + /* Force the source name to the current locale. */ + e_source_set_name (personal, name); + } + + name = _("On The Web"); + + if (on_the_web == NULL) { + ESourceGroup *source_group; + + source_group = e_source_group_new (name, WEB_BASE_URI); + e_source_list_add_group (priv->source_list, source_group, -1); + g_object_unref (source_group); + } else { + /* Force the group name to the current locale. */ + e_source_group_set_name (on_the_web, name); + } + + g_free (base_uri); +} + +static void +task_module_cal_opened_cb (ECal *cal, + ECalendarStatus status, + GtkAction *action) +{ + EShell *shell; + ECalComponent *comp; + CompEditor *editor; + CompEditorFlags flags = 0; + const gchar *action_name; + + /* FIXME Pass this in. */ + shell = e_shell_get_default (); + + /* XXX Handle errors better. */ + if (status != E_CALENDAR_STATUS_OK) + return; + + action_name = gtk_action_get_name (action); + + flags |= COMP_EDITOR_NEW_ITEM; + if (strcmp (action_name, "task-assigned-new") == 0) { + flags |= COMP_EDITOR_IS_ASSIGNED; + flags |= COMP_EDITOR_USER_ORG; + } + + editor = task_editor_new (cal, shell, flags); + comp = cal_comp_task_new_with_defaults (cal); + comp_editor_edit_comp (editor, comp); + + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (comp); + g_object_unref (cal); +} + +static void +action_task_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + ECal *cal = NULL; + ECalSourceType source_type; + ESourceList *source_list; + gchar *uid; + + /* This callback is used for both tasks and assigned tasks. */ + + source_type = E_CAL_SOURCE_TYPE_TODO; + + if (!e_cal_get_sources (&source_list, source_type, NULL)) { + g_warning ("Could not get task sources from GConf!"); + return; + } + + uid = calendar_config_get_primary_tasks (); + + if (uid != NULL) { + ESource *source; + + source = e_source_list_peek_source_by_uid (source_list, uid); + if (source != NULL) + cal = auth_new_cal_from_source (source, source_type); + g_free (uid); + } + + if (cal == NULL) + cal = auth_new_cal_from_default (source_type); + + g_return_if_fail (cal != NULL); + + g_signal_connect ( + cal, "cal-opened", + G_CALLBACK (task_module_cal_opened_cb), action); + + e_cal_open_async (cal, FALSE); +} + +static void +action_task_list_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + calendar_setup_new_task_list (GTK_WINDOW (shell_window)); +} + +static GtkActionEntry item_entries[] = { + + { "task-new", + "stock_task", + NC_("New", "_Task"), + "t", + N_("Create a new task"), + G_CALLBACK (action_task_new_cb) }, + + { "task-assigned-new", + "stock_task", + N_("Assigne_d Task"), + NULL, + N_("Create a new assigned task"), + G_CALLBACK (action_task_new_cb) } +}; + +static GtkActionEntry source_entries[] = { + + { "task-list-new", + "stock_todo", + NC_("New", "Tas_k List"), + NULL, + N_("Create a new task list"), + G_CALLBACK (action_task_list_new_cb) } +}; + +static gboolean +task_module_handle_uri_cb (EShellBackend *shell_backend, + const gchar *uri) +{ + EShell *shell; + CompEditor *editor; + CompEditorFlags flags = 0; + ECal *client; + ECalComponent *comp; + ESource *source; + ESourceList *source_list; + ECalSourceType source_type; + EUri *euri; + icalcomponent *icalcomp; + icalproperty *icalprop; + const gchar *cp; + gchar *source_uid = NULL; + gchar *comp_uid = NULL; + gchar *comp_rid = NULL; + gboolean handled = FALSE; + GError *error = NULL; + + source_type = E_CAL_SOURCE_TYPE_TODO; + shell = e_shell_backend_get_shell (shell_backend); + + if (strncmp (uri, "task:", 5) != 0) + return FALSE; + + euri = e_uri_new (uri); + cp = euri->query; + if (cp == NULL) + goto exit; + + while (*cp != '\0') { + gchar *header; + gchar *content; + gsize header_len; + gsize content_len; + + header_len = strcspn (cp, "=&"); + + /* If it's malformed, give up. */ + if (cp[header_len] != '=') + break; + + header = (gchar *) cp; + header[header_len] = '\0'; + cp += header_len + 1; + + content_len = strcspn (cp, "&"); + + content = g_strndup (cp, content_len); + if (g_ascii_strcasecmp (header, "source-uid") == 0) + source_uid = g_strdup (content); + else if (g_ascii_strcasecmp (header, "comp-uid") == 0) + comp_uid = g_strdup (content); + else if (g_ascii_strcasecmp (header, "comp-rid") == 0) + comp_rid = g_strdup (content); + g_free (content); + + cp += content_len; + if (*cp == '&') { + cp++; + if (strcmp (cp, "amp;") == 0) + cp += 4; + } + } + + if (source_uid != NULL || comp_uid != NULL) + goto exit; + + /* URI is valid, so consider it handled. Whether + * we successfully open it is another matter... */ + handled = TRUE; + + if (!e_cal_get_sources (&source_list, source_type, NULL)) { + g_printerr ("Could not get task sources from GConf!\n"); + goto exit; + } + + source = e_source_list_peek_source_by_uid (source_list, source_uid); + if (source == NULL) { + g_printerr ("No source for UID `%s'\n", source_uid); + g_object_unref (source_list); + goto exit; + } + + client = auth_new_cal_from_source (source, source_type); + if (client == NULL || !e_cal_open (client, TRUE, &error)) { + g_printerr ("%s\n", error->message); + g_object_unref (source_list); + g_error_free (error); + goto exit; + } + + /* XXX Copied from e_task_shell_view_open_task(). + * Clearly a new utility function is needed. */ + + editor = comp_editor_find_instance (comp_uid); + + if (editor != NULL) + goto present; + + if (!e_cal_get_object (client, comp_uid, comp_rid, &icalcomp, &error)) { + g_printerr ("%s\n", error->message); + g_object_unref (source_list); + g_error_free (error); + goto exit; + } + + comp = e_cal_component_new (); + e_cal_component_set_icalcomponent (comp, icalcomp); + + icalprop = icalcomponent_get_first_property ( + icalcomp, ICAL_ATTENDEE_PROPERTY); + if (icalprop != NULL) + flags |= COMP_EDITOR_IS_ASSIGNED; + + if (itip_organizer_is_user (comp, client)) + flags |= COMP_EDITOR_USER_ORG; + + if (!e_cal_component_has_attendees (comp)) + flags |= COMP_EDITOR_USER_ORG; + + editor = task_editor_new (client, shell, flags); + comp_editor_edit_comp (editor, comp); + + g_object_unref (comp); + +present: + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (source_list); + g_object_unref (client); + +exit: + g_free (source_uid); + g_free (comp_uid); + g_free (comp_rid); + + e_uri_free (euri); + + return handled; +} + +static void +task_module_window_created_cb (EShellBackend *shell_backend, + GtkWindow *window) +{ + const gchar *module_name; + + if (!E_IS_SHELL_WINDOW (window)) + return; + + module_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name; + + e_shell_window_register_new_item_actions ( + E_SHELL_WINDOW (window), module_name, + item_entries, G_N_ELEMENTS (item_entries)); + + e_shell_window_register_new_source_actions ( + E_SHELL_WINDOW (window), module_name, + source_entries, G_N_ELEMENTS (source_entries)); +} + +static void +task_shell_backend_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SOURCE_LIST: + g_value_set_object ( + value, + e_task_shell_backend_get_source_list ( + E_TASK_SHELL_BACKEND (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +task_shell_backend_dispose (GObject *object) +{ + ETaskShellBackendPrivate *priv; + + priv = E_TASK_SHELL_BACKEND_GET_PRIVATE (object); + + if (priv->source_list != NULL) { + g_object_unref (priv->source_list); + priv->source_list = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +task_shell_backend_constructed (GObject *object) +{ + EShell *shell; + EShellBackend *shell_backend; + + shell_backend = E_SHELL_BACKEND (object); + shell = e_shell_backend_get_shell (shell_backend); + + task_module_ensure_sources (shell_backend); + + g_signal_connect_swapped ( + shell, "handle-uri", + G_CALLBACK (task_module_handle_uri_cb), shell_backend); + + g_signal_connect_swapped ( + shell, "window-created", + G_CALLBACK (task_module_window_created_cb), shell_backend); +} + +static void +task_shell_backend_class_init (ETaskShellBackendClass *class) +{ + GObjectClass *object_class; + EShellBackendClass *shell_backend_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ETaskShellBackendPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->get_property = task_shell_backend_get_property; + object_class->dispose = task_shell_backend_dispose; + object_class->constructed = task_shell_backend_constructed; + + shell_backend_class = E_SHELL_BACKEND_CLASS (class); + shell_backend_class->shell_view_type = E_TYPE_TASK_SHELL_VIEW; + shell_backend_class->name = "tasks"; + shell_backend_class->aliases = ""; + shell_backend_class->schemes = "task"; + shell_backend_class->sort_order = 600; + shell_backend_class->start = NULL; + shell_backend_class->is_busy = NULL; + shell_backend_class->shutdown = NULL; + shell_backend_class->migrate = e_task_shell_backend_migrate; + + g_object_class_install_property ( + object_class, + PROP_SOURCE_LIST, + g_param_spec_object ( + "source-list", + _("Source List"), + _("The registry of task lists"), + E_TYPE_SOURCE_LIST, + G_PARAM_READABLE)); +} + +static void +task_shell_backend_init (ETaskShellBackend *task_shell_backend) +{ + task_shell_backend->priv = + E_TASK_SHELL_BACKEND_GET_PRIVATE (task_shell_backend); +} + +GType +e_task_shell_backend_get_type (void) +{ + return task_shell_backend_type; +} + +void +e_task_shell_backend_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (ETaskShellBackendClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) task_shell_backend_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ETaskShellBackend), + 0, /* n_preallocs */ + (GInstanceInitFunc) task_shell_backend_init, + NULL /* value_table */ + }; + + task_shell_backend_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_BACKEND, + "ETaskShellBackend", &type_info, 0); +} + +ESourceList * +e_task_shell_backend_get_source_list (ETaskShellBackend *task_shell_backend) +{ + g_return_val_if_fail ( + E_IS_TASK_SHELL_BACKEND (task_shell_backend), NULL); + + return task_shell_backend->priv->source_list; +} diff --git a/modules/calendar/e-task-shell-backend.h b/modules/calendar/e-task-shell-backend.h new file mode 100644 index 0000000000..63b157ad85 --- /dev/null +++ b/modules/calendar/e-task-shell-backend.h @@ -0,0 +1,70 @@ +/* + * e-task-shell-backend.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_TASK_SHELL_BACKEND_H +#define E_TASK_SHELL_BACKEND_H + +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_TASK_SHELL_BACKEND \ + (e_task_shell_backend_get_type ()) +#define E_TASK_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_TASK_SHELL_BACKEND, ETaskShellBackend)) +#define E_TASK_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_TASK_SHELL_BACKEND, ETaskShellBackendClass)) +#define E_IS_TASK_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_TASK_SHELL_BACKEND)) +#define E_IS_TASK_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_TASK_SHELL_BACKEND)) +#define E_TASK_SHELL_BACKEND_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_TASK_SHELL_BACKEND, ETaskShellBackendClass)) + +G_BEGIN_DECLS + +typedef struct _ETaskShellBackend ETaskShellBackend; +typedef struct _ETaskShellBackendClass ETaskShellBackendClass; +typedef struct _ETaskShellBackendPrivate ETaskShellBackendPrivate; + +struct _ETaskShellBackend { + EShellBackend parent; + ETaskShellBackendPrivate *priv; +}; + +struct _ETaskShellBackendClass { + EShellBackendClass parent_class; +}; + +GType e_task_shell_backend_get_type (void); +void e_task_shell_backend_register_type + (GTypeModule *type_module); +ESourceList * e_task_shell_backend_get_source_list + (ETaskShellBackend *task_shell_backend); + +G_END_DECLS + +#endif /* E_TASK_SHELL_BACKEND_H */ diff --git a/modules/calendar/e-task-shell-content.c b/modules/calendar/e-task-shell-content.c new file mode 100644 index 0000000000..0177c6c3c3 --- /dev/null +++ b/modules/calendar/e-task-shell-content.c @@ -0,0 +1,700 @@ +/* + * e-task-shell-content.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-task-shell-content.h" + +#include + +#include "e-util/gconf-bridge.h" + +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/comp-util.h" +#include "calendar/gui/e-cal-model-tasks.h" +#include "calendar/gui/e-calendar-table.h" +#include "calendar/gui/e-calendar-table-config.h" + +#include "widgets/menus/gal-view-etable.h" + +#define E_TASK_SHELL_CONTENT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_TASK_SHELL_CONTENT, ETaskShellContentPrivate)) + +#define E_CALENDAR_TABLE_DEFAULT_STATE \ + "" \ + "" \ + " " \ + " " \ + " " \ + " " \ + " " \ + "" + +struct _ETaskShellContentPrivate { + GtkWidget *paned; + GtkWidget *task_table; + GtkWidget *task_preview; + + ECalModel *task_model; + ECalendarTableConfig *table_config; + GalViewInstance *view_instance; + + gchar *current_uid; +}; + +enum { + PROP_0, + PROP_MODEL, + PROP_PREVIEW_VISIBLE +}; + +enum { + TARGET_VCALENDAR +}; + +static GtkTargetEntry drag_types[] = { + { (gchar *) "text/calendar", 0, TARGET_VCALENDAR }, + { (gchar *) "text/x-calendar", 0, TARGET_VCALENDAR } +}; + +static gpointer parent_class; +static GType task_shell_content_type; + +static void +task_shell_content_display_view_cb (ETaskShellContent *task_shell_content, + GalView *gal_view) +{ + ECalendarTable *task_table; + ETable *table; + + if (!GAL_IS_VIEW_ETABLE (gal_view)) + return; + + task_table = e_task_shell_content_get_task_table (task_shell_content); + table = e_calendar_table_get_table (task_table); + + gal_view_etable_attach_table (GAL_VIEW_ETABLE (gal_view), table); +} + +static void +task_shell_content_table_foreach_cb (gint model_row, + gpointer user_data) +{ + ECalModelComponent *comp_data; + icalcomponent *clone; + icalcomponent *vcal; + gchar *string; + + struct { + ECalModel *model; + GSList *list; + } *foreach_data = user_data; + + comp_data = e_cal_model_get_component_at ( + foreach_data->model, model_row); + + vcal = e_cal_util_new_top_level (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_util_add_timezones_from_component (vcal, comp_data->icalcomp); + icalcomponent_add_component (vcal, clone); + + /* String is owned by libical; do not free. */ + string = icalcomponent_as_ical_string (vcal); + if (string != NULL) { + ESource *source; + const gchar *source_uid; + + source = e_cal_get_source (comp_data->client); + source_uid = e_source_peek_uid (source); + + foreach_data->list = g_slist_prepend ( + foreach_data->list, + g_strdup_printf ("%s\n%s", source_uid, string)); + } + + icalcomponent_free (vcal); +} + +static void +task_shell_content_table_drag_data_get_cb (ETaskShellContent *task_shell_content, + gint row, + gint col, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time) +{ + ECalendarTable *task_table; + ETable *table; + + struct { + ECalModel *model; + GSList *list; + } foreach_data; + + if (info != TARGET_VCALENDAR) + return; + + task_table = e_task_shell_content_get_task_table (task_shell_content); + table = e_calendar_table_get_table (task_table); + + foreach_data.model = e_calendar_table_get_model (task_table); + foreach_data.list = NULL; + + e_table_selected_row_foreach ( + table, task_shell_content_table_foreach_cb, + &foreach_data); + + if (foreach_data.list != NULL) { + cal_comp_selection_set_string_list ( + selection_data, foreach_data.list); + g_slist_foreach (foreach_data.list, (GFunc) g_free, NULL); + g_slist_free (foreach_data.list); + } +} + +static void +task_shell_content_table_drag_data_delete_cb (ETaskShellContent *task_shell_content, + gint row, + gint col, + GdkDragContext *context) +{ + /* Moved components are deleted from source immediately when moved, + * because some of them can be part of destination source, and we + * don't want to delete not-moved tasks. There is no such information + * which event has been moved and which not, so skip this method. */ +} + +static void +task_shell_content_cursor_change_cb (ETaskShellContent *task_shell_content, + gint row, + ETable *table) +{ + ECalComponentPreview *task_preview; + ECalendarTable *task_table; + ECalModel *task_model; + ECalModelComponent *comp_data; + ECalComponent *comp; + const gchar *uid; + + task_model = e_task_shell_content_get_task_model (task_shell_content); + task_table = e_task_shell_content_get_task_table (task_shell_content); + task_preview = e_task_shell_content_get_task_preview (task_shell_content); + + if (e_table_selected_count (table) != 1) { + e_cal_component_preview_clear (task_preview); + return; + } + + row = e_table_get_cursor_row (table); + comp_data = e_cal_model_get_component_at (task_model, row); + + comp = e_cal_component_new (); + e_cal_component_set_icalcomponent ( + comp, icalcomponent_new_clone (comp_data->icalcomp)); + e_cal_component_preview_display ( + task_preview, comp_data->client, comp); + + e_cal_component_get_uid (comp, &uid); + g_free (task_shell_content->priv->current_uid); + task_shell_content->priv->current_uid = g_strdup (uid); + + g_object_unref (comp); +} + +static void +task_shell_content_selection_change_cb (ETaskShellContent *task_shell_content, + ETable *table) +{ + ECalComponentPreview *task_preview; + + task_preview = e_task_shell_content_get_task_preview (task_shell_content); + + if (e_table_selected_count (table) != 1) + e_cal_component_preview_clear (task_preview); +} + +static void +task_shell_content_model_row_changed_cb (ETaskShellContent *task_shell_content, + gint row, + ETableModel *model) +{ + ECalModelComponent *comp_data; + ECalendarTable *task_table; + ETable *table; + const gchar *current_uid; + const gchar *uid; + + current_uid = task_shell_content->priv->current_uid; + if (current_uid == NULL) + return; + + comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row); + if (comp_data == NULL) + return; + + uid = icalcomponent_get_uid (comp_data->icalcomp); + if (g_strcmp0 (uid, current_uid) != 0) + return; + + task_table = e_task_shell_content_get_task_table (task_shell_content); + table = e_calendar_table_get_table (task_table); + + task_shell_content_cursor_change_cb (task_shell_content, 0, table); +} + +static void +task_shell_content_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_PREVIEW_VISIBLE: + e_task_shell_content_set_preview_visible ( + E_TASK_SHELL_CONTENT (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +task_shell_content_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_MODEL: + g_value_set_object ( + value, e_task_shell_content_get_task_model ( + E_TASK_SHELL_CONTENT (object))); + return; + + case PROP_PREVIEW_VISIBLE: + g_value_set_boolean ( + value, e_task_shell_content_get_preview_visible ( + E_TASK_SHELL_CONTENT (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +task_shell_content_dispose (GObject *object) +{ + ETaskShellContentPrivate *priv; + + priv = E_TASK_SHELL_CONTENT_GET_PRIVATE (object); + + if (priv->paned != NULL) { + g_object_unref (priv->paned); + priv->paned = NULL; + } + + if (priv->task_table != NULL) { + g_object_unref (priv->task_table); + priv->task_table = NULL; + } + + if (priv->task_preview != NULL) { + g_object_unref (priv->task_preview); + priv->task_preview = NULL; + } + + if (priv->task_model != NULL) { + g_object_unref (priv->task_model); + priv->task_model = NULL; + } + + if (priv->table_config != NULL) { + g_object_unref (priv->table_config); + priv->table_config = NULL; + } + + if (priv->view_instance != NULL) { + g_object_unref (priv->view_instance); + priv->view_instance = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +task_shell_content_finalize (GObject *object) +{ + ETaskShellContentPrivate *priv; + + priv = E_TASK_SHELL_CONTENT_GET_PRIVATE (object); + + g_free (priv->current_uid); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +task_shell_content_constructed (GObject *object) +{ + ETaskShellContentPrivate *priv; + EShellContent *shell_content; + EShellView *shell_view; + GalViewInstance *view_instance; + ETable *table; + GConfBridge *bridge; + GtkWidget *container; + GtkWidget *widget; + const gchar *key; + + priv = E_TASK_SHELL_CONTENT_GET_PRIVATE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_content = E_SHELL_CONTENT (object); + shell_view = e_shell_content_get_shell_view (shell_content); + + /* Build content widgets. */ + + container = GTK_WIDGET (object); + + widget = gtk_vpaned_new (); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->paned = g_object_ref (widget); + gtk_widget_show (widget); + + container = widget; + + widget = e_calendar_table_new (shell_view, priv->task_model); + gtk_paned_add1 (GTK_PANED (container), widget); + priv->task_table = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_paned_add2 (GTK_PANED (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = e_cal_component_preview_new (); + e_cal_component_preview_set_default_timezone ( + E_CAL_COMPONENT_PREVIEW (widget), + calendar_config_get_icaltimezone ()); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->task_preview = g_object_ref (widget); + gtk_widget_show (widget); + + /* Configure the task table. */ + + widget = E_CALENDAR_TABLE (priv->task_table)->etable; + table = e_table_scrolled_get_table (E_TABLE_SCROLLED (widget)); + + priv->table_config = e_calendar_table_config_new ( + E_CALENDAR_TABLE (priv->task_table)); + + e_table_set_state (table, E_CALENDAR_TABLE_DEFAULT_STATE); + + e_table_drag_source_set ( + table, GDK_BUTTON1_MASK, + drag_types, G_N_ELEMENTS (drag_types), + GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_ASK); + + g_signal_connect_swapped ( + table, "table-drag-data-get", + G_CALLBACK (task_shell_content_table_drag_data_get_cb), + object); + + g_signal_connect_swapped ( + table, "table-drag-data-delete", + G_CALLBACK (task_shell_content_table_drag_data_delete_cb), + object); + + g_signal_connect_swapped ( + table, "cursor-change", + G_CALLBACK (task_shell_content_cursor_change_cb), + object); + + g_signal_connect_swapped ( + table, "selection-change", + G_CALLBACK (task_shell_content_selection_change_cb), + object); + + g_signal_connect_swapped ( + priv->task_model, "model-row-changed", + G_CALLBACK (task_shell_content_model_row_changed_cb), + object); + + /* Load the view instance. */ + + view_instance = e_shell_view_new_view_instance (shell_view, NULL); + g_signal_connect_swapped ( + view_instance, "display-view", + G_CALLBACK (task_shell_content_display_view_cb), + object); + gal_view_instance_load (view_instance); + priv->view_instance = view_instance; + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (priv->paned); + key = "/apps/evolution/calendar/display/task_vpane_position"; + gconf_bridge_bind_property_delayed (bridge, key, object, "position"); +} + +static guint32 +task_shell_content_check_state (EShellContent *shell_content) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ETable *table; + GSList *list, *iter; + gboolean assignable = TRUE; + gboolean editable = TRUE; + gboolean has_url = FALSE; + gint n_selected; + gint n_complete = 0; + gint n_incomplete = 0; + guint32 state = 0; + + task_shell_content = E_TASK_SHELL_CONTENT (shell_content); + task_table = e_task_shell_content_get_task_table (task_shell_content); + + table = e_calendar_table_get_table (task_table); + n_selected = e_table_selected_count (table); + + list = e_calendar_table_get_selected (task_table); + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + icalproperty *prop; + const gchar *cap; + gboolean read_only; + + e_cal_is_read_only (comp_data->client, &read_only, NULL); + editable &= !read_only; + + cap = CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT; + if (e_cal_get_static_capability (comp_data->client, cap)) + assignable = FALSE; + + cap = CAL_STATIC_CAPABILITY_NO_CONV_TO_ASSIGN_TASK; + if (e_cal_get_static_capability (comp_data->client, cap)) + assignable = FALSE; + + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_URL_PROPERTY); + has_url |= (prop != NULL); + + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_COMPLETED_PROPERTY); + if (prop != NULL) + n_complete++; + else + n_incomplete++; + } + g_slist_free (list); + + if (n_selected == 1) + state |= E_TASK_SHELL_CONTENT_SELECTION_SINGLE; + if (n_selected > 1) + state |= E_TASK_SHELL_CONTENT_SELECTION_MULTIPLE; + if (assignable) + state |= E_TASK_SHELL_CONTENT_SELECTION_CAN_ASSIGN; + if (editable) + state |= E_TASK_SHELL_CONTENT_SELECTION_CAN_EDIT; + if (n_complete > 0) + state |= E_TASK_SHELL_CONTENT_SELECTION_HAS_COMPLETE; + if (n_incomplete > 0) + state |= E_TASK_SHELL_CONTENT_SELECTION_HAS_INCOMPLETE; + if (has_url) + state |= E_TASK_SHELL_CONTENT_SELECTION_HAS_URL; + + return state; +} + +static void +task_shell_content_class_init (ETaskShellContentClass *class) +{ + GObjectClass *object_class; + EShellContentClass *shell_content_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ETaskShellContentPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = task_shell_content_set_property; + object_class->get_property = task_shell_content_get_property; + object_class->dispose = task_shell_content_dispose; + object_class->finalize = task_shell_content_finalize; + object_class->constructed = task_shell_content_constructed; + + shell_content_class = E_SHELL_CONTENT_CLASS (class); + shell_content_class->check_state = task_shell_content_check_state; + + g_object_class_install_property ( + object_class, + PROP_MODEL, + g_param_spec_object ( + "model", + _("Model"), + _("The task table model"), + E_TYPE_CAL_MODEL, + G_PARAM_READABLE)); + + g_object_class_install_property ( + object_class, + PROP_PREVIEW_VISIBLE, + g_param_spec_boolean ( + "preview-visible", + _("Preview is Visible"), + _("Whether the preview pane is visible"), + TRUE, + G_PARAM_READWRITE)); +} + +static void +task_shell_content_init (ETaskShellContent *task_shell_content) +{ + task_shell_content->priv = + E_TASK_SHELL_CONTENT_GET_PRIVATE (task_shell_content); + + task_shell_content->priv->task_model = e_cal_model_tasks_new (); + + /* Postpone widget construction until we have a shell view. */ +} + +GType +e_task_shell_content_get_type (void) +{ + return task_shell_content_type; +} + +void +e_task_shell_content_register_type (GTypeModule *type_module) +{ + static const GTypeInfo type_info = { + sizeof (ETaskShellContentClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) task_shell_content_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ETaskShellContent), + 0, /* n_preallocs */ + (GInstanceInitFunc) task_shell_content_init, + NULL /* value_table */ + }; + + task_shell_content_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_CONTENT, + "ETaskShellContent", &type_info, 0); +} + +GtkWidget * +e_task_shell_content_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_TASK_SHELL_CONTENT, + "shell-view", shell_view, NULL); +} + +ECalModel * +e_task_shell_content_get_task_model (ETaskShellContent *task_shell_content) +{ + g_return_val_if_fail ( + E_IS_TASK_SHELL_CONTENT (task_shell_content), NULL); + + return task_shell_content->priv->task_model; +} + +ECalComponentPreview * +e_task_shell_content_get_task_preview (ETaskShellContent *task_shell_content) +{ + g_return_val_if_fail ( + E_IS_TASK_SHELL_CONTENT (task_shell_content), NULL); + + return E_CAL_COMPONENT_PREVIEW ( + task_shell_content->priv->task_preview); +} + +ECalendarTable * +e_task_shell_content_get_task_table (ETaskShellContent *task_shell_content) +{ + g_return_val_if_fail ( + E_IS_TASK_SHELL_CONTENT (task_shell_content), NULL); + + return E_CALENDAR_TABLE (task_shell_content->priv->task_table); +} + +GalViewInstance * +e_task_shell_content_get_view_instance (ETaskShellContent *task_shell_content) +{ + g_return_val_if_fail ( + E_IS_TASK_SHELL_CONTENT (task_shell_content), NULL); + + return task_shell_content->priv->view_instance; +} + +gboolean +e_task_shell_content_get_preview_visible (ETaskShellContent *task_shell_content) +{ + GtkPaned *paned; + GtkWidget *child; + + g_return_val_if_fail ( + E_IS_TASK_SHELL_CONTENT (task_shell_content), FALSE); + + paned = GTK_PANED (task_shell_content->priv->paned); + child = gtk_paned_get_child2 (paned); + + return GTK_WIDGET_VISIBLE (child); +} + +void +e_task_shell_content_set_preview_visible (ETaskShellContent *task_shell_content, + gboolean preview_visible) +{ + GtkPaned *paned; + GtkWidget *child; + + g_return_if_fail (E_IS_TASK_SHELL_CONTENT (task_shell_content)); + + paned = GTK_PANED (task_shell_content->priv->paned); + child = gtk_paned_get_child2 (paned); + + if (preview_visible) + gtk_widget_show (child); + else + gtk_widget_hide (child); + + g_object_notify (G_OBJECT (task_shell_content), "preview-visible"); +} diff --git a/modules/calendar/e-task-shell-content.h b/modules/calendar/e-task-shell-content.h new file mode 100644 index 0000000000..7e0b2128a7 --- /dev/null +++ b/modules/calendar/e-task-shell-content.h @@ -0,0 +1,100 @@ +/* + * e-task-shell-content.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_TASK_SHELL_CONTENT_H +#define E_TASK_SHELL_CONTENT_H + +#include +#include + +#include +#include +#include + +#include + +/* Standard GObject macros */ +#define E_TYPE_TASK_SHELL_CONTENT \ + (e_task_shell_content_get_type ()) +#define E_TASK_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_TASK_SHELL_CONTENT, ETaskShellContent)) +#define E_TASK_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_TASK_SHELL_CONTENT, ETaskShellContentClass)) +#define E_IS_TASK_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_TASK_SHELL_CONTENT)) +#define E_IS_TASK_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_TASK_SHELL_CONTENT)) +#define E_TASK_SHELL_CONTENT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_TASK_SHELL_CONTENT, ETaskShellContentClass)) + +G_BEGIN_DECLS + +typedef struct _ETaskShellContent ETaskShellContent; +typedef struct _ETaskShellContentClass ETaskShellContentClass; +typedef struct _ETaskShellContentPrivate ETaskShellContentPrivate; + +enum { + E_TASK_SHELL_CONTENT_SELECTION_SINGLE = 1 << 0, + E_TASK_SHELL_CONTENT_SELECTION_MULTIPLE = 1 << 1, + E_TASK_SHELL_CONTENT_SELECTION_CAN_ASSIGN = 1 << 2, + E_TASK_SHELL_CONTENT_SELECTION_CAN_EDIT = 1 << 3, + E_TASK_SHELL_CONTENT_SELECTION_HAS_COMPLETE = 1 << 4, + E_TASK_SHELL_CONTENT_SELECTION_HAS_INCOMPLETE = 1 << 5, + E_TASK_SHELL_CONTENT_SELECTION_HAS_URL = 1 << 6 +}; + +struct _ETaskShellContent { + EShellContent parent; + ETaskShellContentPrivate *priv; +}; + +struct _ETaskShellContentClass { + EShellContentClass parent_class; +}; + +GType e_task_shell_content_get_type (void); +void e_task_shell_content_register_type + (GTypeModule *type_module); +GtkWidget * e_task_shell_content_new(EShellView *shell_view); +ECalModel * e_task_shell_content_get_task_model + (ETaskShellContent *task_shell_content); +ECalComponentPreview * + e_task_shell_content_get_task_preview + (ETaskShellContent *task_shell_content); +ECalendarTable *e_task_shell_content_get_task_table + (ETaskShellContent *task_shell_content); +GalViewInstance * + e_task_shell_content_get_view_instance + (ETaskShellContent *task_shell_content); +gboolean e_task_shell_content_get_preview_visible + (ETaskShellContent *task_shell_content); +void e_task_shell_content_set_preview_visible + (ETaskShellContent *task_shell_content, + gboolean preview_visible); + +G_END_DECLS + +#endif /* E_TASK_SHELL_CONTENT_H */ diff --git a/modules/calendar/e-task-shell-migrate.c b/modules/calendar/e-task-shell-migrate.c new file mode 100644 index 0000000000..ced54bafdf --- /dev/null +++ b/modules/calendar/e-task-shell-migrate.c @@ -0,0 +1,664 @@ +/* + * e-task-shell-backend-migrate.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-task-shell-migrate.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "e-util/e-bconf-map.h" +#include "e-util/e-folder-map.h" +#include "e-util/e-util-private.h" +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/calendar-config-keys.h" + +#define WEBCAL_BASE_URI "webcal://" +#define PERSONAL_RELATIVE_URI "system" + +static e_gconf_map_t calendar_tasks_map[] = { + /* /Calendar/Tasks */ + { "HideCompletedTasks", "calendar/tasks/hide_completed", E_GCONF_MAP_BOOL }, + { "HideCompletedTasksUnits", "calendar/tasks/hide_completed_units", E_GCONF_MAP_STRING }, + { "HideCompletedTasksValue", "calendar/tasks/hide_completed_value", E_GCONF_MAP_INT }, + { NULL }, +}; + +static e_gconf_map_t calendar_tasks_colours_map[] = { + /* /Calendar/Tasks/Colors */ + { "TasksDueToday", "calendar/tasks/colors/due_today", E_GCONF_MAP_STRING }, + { "TasksOverDue", "calendar/tasks/colors/overdue", E_GCONF_MAP_STRING }, + { "TasksDueToday", "calendar/tasks/colors/due_today", E_GCONF_MAP_STRING }, + { NULL }, +}; + +static e_gconf_map_list_t task_remap_list[] = { + + { "/Calendar/Tasks", calendar_tasks_map }, + { "/Calendar/Tasks/Colors", calendar_tasks_colours_map }, + + { NULL }, +}; + +static GtkWidget *window; +static GtkLabel *label; +static GtkProgressBar *progress; + +#ifndef G_OS_WIN32 + +/* No previous versions have been available on Win32, so don't + * bother with upgrade support from 1.x on Win32. + */ + +static void +setup_progress_dialog (void) +{ + GtkWidget *vbox, *hbox, *w; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title ((GtkWindow *) window, _("Migrating...")); + gtk_window_set_modal ((GtkWindow *) window, TRUE); + gtk_container_set_border_width ((GtkContainer *) window, 6); + + vbox = gtk_vbox_new (FALSE, 6); + gtk_widget_show (vbox); + gtk_container_add ((GtkContainer *) window, vbox); + + w = gtk_label_new (_("The location and hierarchy of the Evolution task " + "folders has changed since Evolution 1.x.\n\nPlease be " + "patient while Evolution migrates your folders...")); + + gtk_label_set_line_wrap ((GtkLabel *) w, TRUE); + gtk_widget_show (w); + gtk_box_pack_start_defaults ((GtkBox *) vbox, w); + + hbox = gtk_hbox_new (FALSE, 6); + gtk_widget_show (hbox); + gtk_box_pack_start_defaults ((GtkBox *) vbox, hbox); + + label = (GtkLabel *) gtk_label_new (""); + gtk_widget_show ((GtkWidget *) label); + gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) label); + + progress = (GtkProgressBar *) gtk_progress_bar_new (); + gtk_widget_show ((GtkWidget *) progress); + gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) progress); + + gtk_widget_show (window); +} + +static void +dialog_close (void) +{ + gtk_widget_destroy ((GtkWidget *) window); +} + +static void +dialog_set_folder_name (const gchar *folder_name) +{ + gchar *text; + + text = g_strdup_printf (_("Migrating '%s':"), folder_name); + gtk_label_set_text (label, text); + g_free (text); + + gtk_progress_bar_set_fraction (progress, 0.0); + + while (gtk_events_pending ()) + gtk_main_iteration (); +} + +static void +dialog_set_progress (double percent) +{ + gchar text[5]; + + snprintf (text, sizeof (text), "%d%%", (gint) (percent * 100.0f)); + + gtk_progress_bar_set_fraction (progress, percent); + gtk_progress_bar_set_text (progress, text); + + while (gtk_events_pending ()) + gtk_main_iteration (); +} + +static gboolean +check_for_conflict (ESourceGroup *group, gchar *name) +{ + GSList *sources; + GSList *s; + + sources = e_source_group_peek_sources (group); + + for (s = sources; s; s = s->next) { + ESource *source = E_SOURCE (s->data); + + if (!strcmp (e_source_peek_name (source), name)) + return TRUE; + } + + return FALSE; +} + +static gchar * +get_source_name (ESourceGroup *group, const gchar *path) +{ + gchar **p = g_strsplit (path, "/", 0); + gint i, j, starting_index; + gint num_elements; + gboolean conflict; + GString *s = g_string_new (NULL); + + for (i = 0; p[i]; i ++); + + num_elements = i; + i--; + + /* p[i] is now the last path element */ + + /* check if it conflicts */ + starting_index = i; + do { + for (j = starting_index; j < num_elements; j += 2) { + if (j != starting_index) + g_string_append_c (s, '_'); + g_string_append (s, p[j]); + } + + conflict = check_for_conflict (group, s->str); + + + /* if there was a conflict back up 2 levels (skipping the /subfolder/ element) */ + if (conflict) + starting_index -= 2; + + /* we always break out if we can't go any further, + regardless of whether or not we conflict. */ + if (starting_index < 0) + break; + + } while (conflict); + g_strfreev (p); + + return g_string_free (s, FALSE); +} + +static gboolean +migrate_ical (ECal *old_ecal, ECal *new_ecal) +{ + GList *l, *objects; + gint num_added = 0; + gint num_objects; + gboolean retval = TRUE; + + /* both ecals are loaded, start the actual migration */ + if (!e_cal_get_object_list (old_ecal, "#t", &objects, NULL)) + return FALSE; + + num_objects = g_list_length (objects); + for (l = objects; l; l = l->next) { + icalcomponent *ical_comp = l->data; + GError *error = NULL; + + if (!e_cal_create_object (new_ecal, ical_comp, NULL, &error)) { + g_warning ("Migration of object failed: %s", error->message); + retval = FALSE; + } + + g_clear_error (&error); + + num_added ++; + dialog_set_progress ((double)num_added / num_objects); + } + + g_list_foreach (objects, (GFunc) icalcomponent_free, NULL); + g_list_free (objects); + + return retval; +} + +static gboolean +migrate_ical_folder_to_source (gchar *old_path, ESource *new_source, ECalSourceType type) +{ + ECal *old_ecal = NULL, *new_ecal = NULL; + ESource *old_source; + ESourceGroup *group; + gchar *old_uri = g_strdup_printf ("file://%s", old_path); + GError *error = NULL; + gboolean retval = FALSE; + + group = e_source_group_new ("", old_uri); + old_source = e_source_new ("", ""); + e_source_group_add_source (group, old_source, -1); + + dialog_set_folder_name (e_source_peek_name (new_source)); + + if (!(old_ecal = e_cal_new (old_source, type))) { + g_warning ("could not find a backend for '%s'", e_source_get_uri (old_source)); + goto finish; + } + if (!e_cal_open (old_ecal, FALSE, &error)) { + g_warning ("failed to load source ecal for migration: '%s' (%s)", error->message, + e_source_get_uri (old_source)); + goto finish; + } + + if (!(new_ecal = e_cal_new (new_source, type))) { + g_warning ("could not find a backend for '%s'", e_source_get_uri (new_source)); + goto finish; + } + if (!e_cal_open (new_ecal, FALSE, &error)) { + g_warning ("failed to load destination ecal for migration: '%s' (%s)", error->message, + e_source_get_uri (new_source)); + goto finish; + } + + retval = migrate_ical (old_ecal, new_ecal); + +finish: + g_clear_error (&error); + if (old_ecal) + g_object_unref (old_ecal); + g_object_unref (group); + if (new_ecal) + g_object_unref (new_ecal); + g_free (old_uri); + + return retval; +} + +static gboolean +migrate_ical_folder (gchar *old_path, ESourceGroup *dest_group, gchar *source_name, ECalSourceType type) +{ + ESource *new_source; + gboolean retval; + + new_source = e_source_new (source_name, source_name); + e_source_set_relative_uri (new_source, e_source_peek_uid (new_source)); + e_source_group_add_source (dest_group, new_source, -1); + + retval = migrate_ical_folder_to_source (old_path, new_source, type); + + g_object_unref (new_source); + + return retval; +} + +#endif /* !G_OS_WIN32 */ + +#ifndef G_OS_WIN32 + +static void +migrate_pilot_db_key (const gchar *key, gpointer user_data) +{ + EXmlHash *xmlhash = user_data; + + e_xmlhash_add (xmlhash, key, ""); +} + +static void +migrate_pilot_data (const gchar *component, const gchar *conduit, const gchar *old_path, const gchar *new_path) +{ + gchar *changelog, *map; + const gchar *dent; + const gchar *ext; + gchar *filename; + GDir *dir; + + if (!(dir = g_dir_open (old_path, 0, NULL))) + return; + + map = g_alloca (12 + strlen (conduit)); + sprintf (map, "pilot-map-%s-", conduit); + + changelog = g_alloca (24 + strlen (conduit)); + sprintf (changelog, "pilot-sync-evolution-%s-", conduit); + + while ((dent = g_dir_read_name (dir))) { + if (!strncmp (dent, map, strlen (map)) && + ((ext = strrchr (dent, '.')) && !strcmp (ext, ".xml"))) { + /* pilot map file - src and dest file formats are identical */ + guchar inbuf[4096]; + gsize nread, nwritten; + gint fd0, fd1; + gssize n; + + filename = g_build_filename (old_path, dent, NULL); + if ((fd0 = g_open (filename, O_RDONLY|O_BINARY, 0)) == -1) { + g_free (filename); + continue; + } + + g_free (filename); + filename = g_build_filename (new_path, dent, NULL); + if ((fd1 = g_open (filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666)) == -1) { + g_free (filename); + close (fd0); + continue; + } + + do { + do { + n = read (fd0, inbuf, sizeof (inbuf)); + } while (n == -1 && errno == EINTR); + + if (n < 1) + break; + + nread = n; + nwritten = 0; + do { + do { + n = write (fd1, inbuf + nwritten, nread - nwritten); + } while (n == -1 && errno == EINTR); + + if (n > 0) + nwritten += n; + } while (nwritten < nread && n != -1); + + if (n == -1) + break; + } while (1); + + if (n != -1) + n = fsync (fd1); + + if (n == -1) { + g_warning ("Failed to migrate %s: %s", dent, strerror (errno)); + g_unlink (filename); + } + + close (fd0); + close (fd1); + g_free (filename); + } else if (!strncmp (dent, changelog, strlen (changelog)) && + ((ext = strrchr (dent, '.')) && !strcmp (ext, ".db"))) { + /* src and dest formats differ, src format is db3 while dest format is xml */ + EXmlHash *xmlhash; + EDbHash *dbhash; + struct stat st; + + filename = g_build_filename (old_path, dent, NULL); + if (g_stat (filename, &st) == -1) { + g_free (filename); + continue; + } + + dbhash = e_dbhash_new (filename); + g_free (filename); + + filename = g_strdup_printf ("%s/%s.ics-%s", new_path, component, dent); + if (g_stat (filename, &st) != -1) + g_unlink (filename); + xmlhash = e_xmlhash_new (filename); + g_free (filename); + + e_dbhash_foreach_key (dbhash, migrate_pilot_db_key, xmlhash); + + e_dbhash_destroy (dbhash); + + e_xmlhash_write (xmlhash); + e_xmlhash_destroy (xmlhash); + } + } + + g_dir_close (dir); +} + +#endif + +static void +create_task_sources (EShellBackend *shell_backend, + ESourceList *source_list, + ESourceGroup **on_this_computer, + ESourceGroup **on_the_web, + ESource **personal_source) +{ + GSList *groups; + ESourceGroup *group; + gchar *base_uri, *base_uri_proto; + const gchar *base_dir; + + *on_this_computer = NULL; + *on_the_web = NULL; + *personal_source = NULL; + + base_dir = e_shell_backend_get_config_dir (shell_backend); + base_uri = g_build_filename (base_dir, "local", NULL); + + base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL); + + groups = e_source_list_peek_groups (source_list); + if (groups) { + /* groups are already there, we need to search for things... */ + GSList *g; + + for (g = groups; g; g = g->next) { + + group = E_SOURCE_GROUP (g->data); + + if (!*on_this_computer && !strcmp (base_uri_proto, e_source_group_peek_base_uri (group))) + *on_this_computer = g_object_ref (group); + else if (!*on_the_web && !strcmp (WEBCAL_BASE_URI, e_source_group_peek_base_uri (group))) + *on_the_web = g_object_ref (group); + } + } + + if (*on_this_computer) { + /* make sure "Personal" shows up as a source under + this group */ + GSList *sources = e_source_group_peek_sources (*on_this_computer); + GSList *s; + for (s = sources; s; s = s->next) { + ESource *source = E_SOURCE (s->data); + const gchar *relative_uri; + + relative_uri = e_source_peek_relative_uri (source); + if (relative_uri == NULL) + continue; + if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) { + *personal_source = g_object_ref (source); + break; + } + } + } else { + /* create the local source group */ + group = e_source_group_new (_("On This Computer"), base_uri_proto); + e_source_list_add_group (source_list, group, -1); + + *on_this_computer = group; + } + + if (!*personal_source) { + /* Create the default Person task list */ + ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); + e_source_group_add_source (*on_this_computer, source, -1); + + if (!calendar_config_get_primary_tasks () && !calendar_config_get_tasks_selected ()) { + GSList selected; + + calendar_config_set_primary_tasks (e_source_peek_uid (source)); + + selected.data = (gpointer)e_source_peek_uid (source); + selected.next = NULL; + calendar_config_set_tasks_selected (&selected); + } + + e_source_set_color_spec (source, "#BECEDD"); + *personal_source = source; + } + + if (!*on_the_web) { + /* Create the Webcal source group */ + group = e_source_group_new (_("On The Web"), WEBCAL_BASE_URI); + e_source_list_add_group (source_list, group, -1); + + *on_the_web = group; + } + + g_free (base_uri_proto); + g_free (base_uri); +} + +gboolean +e_task_shell_backend_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint micro, + GError **error) +{ + ESourceGroup *on_this_computer = NULL; + ESourceGroup *on_the_web = NULL; + ESource *personal_source = NULL; + ESourceList *source_list; + gboolean retval = FALSE; + + source_list = g_object_get_data ( + G_OBJECT (source_list), "source-list"); + + /* we call this unconditionally now - create_groups either + creates the groups/sources or it finds the necessary + groups/sources. */ + create_task_sources ( + shell_backend, source_list, &on_this_computer, + &on_the_web, &personal_source); + +#ifndef G_OS_WIN32 + if (major == 1) { + xmlDocPtr config_doc = NULL; + gchar *conf_file; + + conf_file = g_build_filename (g_get_home_dir (), "evolution", "config.xmldb", NULL); + if (g_file_test (conf_file, G_FILE_TEST_IS_REGULAR)) + config_doc = e_xml_parse_file (conf_file); + g_free (conf_file); + + if (config_doc && minor <= 2) { + GConfClient *gconf; + gint res = 0; + + /* move bonobo config to gconf */ + gconf = gconf_client_get_default (); + + res = e_bconf_import (gconf, config_doc, task_remap_list); + + g_object_unref (gconf); + + xmlFreeDoc(config_doc); + + if (res != 0) { + g_set_error(error, 0, 0, _("Unable to migrate old settings from evolution/config.xmldb")); + goto fail; + } + } + + if (minor <= 4) { + GSList *migration_dirs, *l; + gchar *path, *local_task_folder; + + setup_progress_dialog (); + + path = g_build_filename (g_get_home_dir (), "evolution", "local", NULL); + migration_dirs = e_folder_map_local_folders (path, "tasks"); + local_task_folder = g_build_filename (path, "Tasks", NULL); + g_free (path); + + if (personal_source) + migrate_ical_folder_to_source (local_task_folder, personal_source, E_CAL_SOURCE_TYPE_TODO); + + for (l = migration_dirs; l; l = l->next) { + gchar *source_name; + + if (personal_source && !strcmp ((gchar *)l->data, local_task_folder)) + continue; + + source_name = get_source_name (on_this_computer, (gchar *)l->data); + + if (!migrate_ical_folder (l->data, on_this_computer, source_name, E_CAL_SOURCE_TYPE_TODO)) { + /* FIXME: domain/code */ + g_set_error(error, 0, 0, _("Unable to migrate tasks `%s'"), source_name); + g_free(source_name); + goto fail; + } + + g_free (source_name); + } + + g_free (local_task_folder); + + dialog_close (); + } + + if (minor < 5 || (minor == 5 && micro <= 10)) { + gchar *old_path, *new_path; + + old_path = g_build_filename (g_get_home_dir (), "evolution", "local", "Tasks", NULL); + new_path = g_build_filename (e_shell_backend_get_config_dir (shell_backend), + "local", "system", NULL); + migrate_pilot_data ("tasks", "todo", old_path, new_path); + g_free (new_path); + g_free (old_path); + } + + /* we only need to do this next step if people ran + older versions of 1.5. We need to clear out the + absolute URI's that were assigned to ESources + during one phase of development, as they take + precedent over relative uris (but aren't updated + when editing an ESource). */ + if (minor == 5 && micro <= 11) { + GSList *g; + for (g = e_source_list_peek_groups (source_list); g; g = g->next) { + ESourceGroup *group = g->data; + GSList *s; + + for (s = e_source_group_peek_sources (group); s; s = s->next) { + ESource *source = s->data; + e_source_set_absolute_uri (source, NULL); + } + } + } + } +#endif /* !G_OS_WIN32 */ + e_source_list_sync (source_list, NULL); + retval = TRUE; +fail: + if (on_this_computer) + g_object_unref (on_this_computer); + if (on_the_web) + g_object_unref (on_the_web); + if (personal_source) + g_object_unref (personal_source); + + return retval; +} diff --git a/modules/calendar/e-task-shell-migrate.h b/modules/calendar/e-task-shell-migrate.h new file mode 100644 index 0000000000..4cb91c9f4a --- /dev/null +++ b/modules/calendar/e-task-shell-migrate.h @@ -0,0 +1,38 @@ +/* + * e-task-shell-backend-migrate.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_TASK_SHELL_BACKEND_MIGRATE_H +#define E_TASK_SHELL_BACKEND_MIGRATE_H + +#include +#include + +G_BEGIN_DECLS + +gboolean e_task_shell_backend_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint micro, + GError **error); + +G_END_DECLS + +#endif /* E_TASK_SHELL_BACKEND_MIGRATE_H */ diff --git a/modules/calendar/e-task-shell-sidebar.c b/modules/calendar/e-task-shell-sidebar.c new file mode 100644 index 0000000000..827a0a037e --- /dev/null +++ b/modules/calendar/e-task-shell-sidebar.c @@ -0,0 +1,696 @@ +/* + * e-task-shell-sidebar.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-task-shell-sidebar.h" + +#include +#include +#include + +#include "e-util/e-error.h" +#include "e-util/e-util.h" +#include "calendar/common/authentication.h" +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/e-task-list-selector.h" +#include "calendar/gui/misc.h" + +#include "e-task-shell-backend.h" +#include "e-task-shell-view.h" + +#define E_TASK_SHELL_SIDEBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_TASK_SHELL_SIDEBAR, ETaskShellSidebarPrivate)) + +struct _ETaskShellSidebarPrivate { + GtkWidget *selector; + + /* UID -> Client */ + GHashTable *client_table; +}; + +enum { + PROP_0, + PROP_SELECTOR +}; + +enum { + CLIENT_ADDED, + CLIENT_REMOVED, + STATUS_MESSAGE, + LAST_SIGNAL +}; + +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; +static GType task_shell_sidebar_type; + +static void +task_shell_sidebar_emit_client_added (ETaskShellSidebar *task_shell_sidebar, + ECal *client) +{ + guint signal_id = signals[CLIENT_ADDED]; + + g_signal_emit (task_shell_sidebar, signal_id, 0, client); +} + +static void +task_shell_sidebar_emit_client_removed (ETaskShellSidebar *task_shell_sidebar, + ECal *client) +{ + guint signal_id = signals[CLIENT_REMOVED]; + + g_signal_emit (task_shell_sidebar, signal_id, 0, client); +} + +static void +task_shell_sidebar_emit_status_message (ETaskShellSidebar *task_shell_sidebar, + const gchar *status_message) +{ + guint signal_id = signals[STATUS_MESSAGE]; + + g_signal_emit (task_shell_sidebar, signal_id, 0, status_message, -1.0); +} + +static void +task_shell_sidebar_backend_died_cb (ETaskShellSidebar *task_shell_sidebar, + ECal *client) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + GHashTable *client_table; + ESource *source; + const gchar *uid; + + client_table = task_shell_sidebar->priv->client_table; + + shell_sidebar = E_SHELL_SIDEBAR (task_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + source = e_cal_get_source (client); + uid = e_source_peek_uid (source); + + g_object_ref (source); + + g_hash_table_remove (client_table, uid); + task_shell_sidebar_emit_status_message (task_shell_sidebar, NULL); + + e_error_run ( + GTK_WINDOW (shell_window), + "calendar:tasks-crashed", NULL); + + g_object_unref (source); +} + +static void +task_shell_sidebar_backend_error_cb (ETaskShellSidebar *task_shell_sidebar, + const gchar *message, + ECal *client) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + GtkWidget *dialog; + const gchar *uri; + gchar *uri_no_passwd; + + shell_sidebar = E_SHELL_SIDEBAR (task_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + uri = e_cal_get_uri (client); + uri_no_passwd = get_uri_without_password (uri); + + dialog = gtk_message_dialog_new ( + GTK_WINDOW (shell_window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, + _("Error on %s\n%s"), + uri_no_passwd, message); + + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + + g_free (uri_no_passwd); +} + +static void +task_shell_sidebar_client_opened_cb (ETaskShellSidebar *task_shell_sidebar, + ECalendarStatus status, + ECal *client) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + ESource *source; + + source = e_cal_get_source (client); + + shell_sidebar = E_SHELL_SIDEBAR (task_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + if (status == E_CALENDAR_STATUS_AUTHENTICATION_FAILED || + status == E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED) + auth_cal_forget_password (client); + + switch (status) { + case E_CALENDAR_STATUS_OK: + g_signal_handlers_disconnect_matched ( + client, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, + task_shell_sidebar_client_opened_cb, NULL); + + task_shell_sidebar_emit_status_message ( + task_shell_sidebar, _("Loading tasks")); + task_shell_sidebar_emit_client_added ( + task_shell_sidebar, client); + task_shell_sidebar_emit_status_message ( + task_shell_sidebar, NULL); + break; + + case E_CALENDAR_STATUS_AUTHENTICATION_FAILED: + e_cal_open_async (client, FALSE); + break; + + case E_CALENDAR_STATUS_BUSY: + break; + + case E_CALENDAR_STATUS_REPOSITORY_OFFLINE: + e_error_run ( + GTK_WINDOW (shell_window), + "calendar:prompt-no-contents-offline-tasks", + NULL); + break; + + default: + task_shell_sidebar_emit_client_removed ( + task_shell_sidebar, client); + break; + } +} + +static void +task_shell_sidebar_row_changed_cb (ETaskShellSidebar *task_shell_sidebar, + GtkTreePath *tree_path, + GtkTreeIter *tree_iter, + GtkTreeModel *tree_model) +{ + ESourceSelector *selector; + ESource *source; + + /* XXX ESourceSelector's underlying tree store has only one + * column: ESource objects. While we're not supposed to + * know this, listening for "row-changed" signals from + * the model is easier to deal with than the selector's + * "selection-changed" signal, which doesn't tell you + * _which_ row changed. */ + + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + gtk_tree_model_get (tree_model, tree_iter, 0, &source, -1); + + /* XXX This signal gets emitted a lot while the model is being + * rebuilt, during which time we won't get a valid ESource. + * ESourceSelector should probably block this signal while + * rebuilding the model, but we'll be forgiving and not + * emit a warning. */ + if (!E_IS_SOURCE (source)) + return; + + if (e_source_selector_source_is_selected (selector, source)) + e_task_shell_sidebar_add_source (task_shell_sidebar, source); + else + e_task_shell_sidebar_remove_source (task_shell_sidebar, source); +} + +static void +task_shell_sidebar_selection_changed_cb (ETaskShellSidebar *task_shell_sidebar, + ESourceSelector *selector) +{ + GSList *list, *iter; + + /* This signal is emitted less frequently than "row-changed", + * especially when the model is being rebuilt. So we'll take + * it easy on poor GConf. */ + + list = e_source_selector_get_selection (selector); + + for (iter = list; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + + iter->data = (gpointer) e_source_peek_uid (source); + g_object_unref (source); + } + + calendar_config_set_tasks_selected (list); + + g_slist_free (list); +} + +static void +task_shell_sidebar_primary_selection_changed_cb (ETaskShellSidebar *task_shell_sidebar, + ESourceSelector *selector) +{ + ESource *source; + const gchar *uid; + + /* XXX ESourceSelector needs a "primary-selection-uid" property + * so we can just bind the property with GConfBridge. */ + + source = e_source_selector_peek_primary_selection (selector); + if (source == NULL) + return; + + uid = e_source_peek_uid (source); + calendar_config_set_primary_tasks (uid); +} + +static void +task_shell_sidebar_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SELECTOR: + g_value_set_object ( + value, e_task_shell_sidebar_get_selector ( + E_TASK_SHELL_SIDEBAR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +task_shell_sidebar_dispose (GObject *object) +{ + ETaskShellSidebarPrivate *priv; + + priv = E_TASK_SHELL_SIDEBAR_GET_PRIVATE (object); + + if (priv->selector != NULL) { + g_object_unref (priv->selector); + priv->selector = NULL; + } + + g_hash_table_remove_all (priv->client_table); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +task_shell_sidebar_finalize (GObject *object) +{ + ETaskShellSidebarPrivate *priv; + + priv = E_TASK_SHELL_SIDEBAR_GET_PRIVATE (object); + + g_hash_table_destroy (priv->client_table); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +task_shell_sidebar_constructed (GObject *object) +{ + ETaskShellSidebarPrivate *priv; + EShellView *shell_view; + EShellBackend *shell_backend; + EShellSidebar *shell_sidebar; + ESourceSelector *selector; + ESourceList *source_list; + ESource *source; + GtkContainer *container; + GtkTreeModel *model; + GtkWidget *widget; + AtkObject *a11y; + GSList *list, *iter; + gchar *uid; + + priv = E_TASK_SHELL_SIDEBAR_GET_PRIVATE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_sidebar = E_SHELL_SIDEBAR (object); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + source_list = e_task_shell_backend_get_source_list ( + E_TASK_SHELL_BACKEND (shell_backend)); + + container = GTK_CONTAINER (shell_sidebar); + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_container_add (container, widget); + gtk_widget_show (widget); + + container = GTK_CONTAINER (widget); + + widget = e_task_list_selector_new (source_list); + e_source_selector_set_select_new (E_SOURCE_SELECTOR (widget), TRUE); + gtk_container_add (container, widget); + a11y = gtk_widget_get_accessible (widget); + atk_object_set_name (a11y, _("Task List Selector")); + priv->selector = g_object_ref (widget); + gtk_widget_show (widget); + + /* Restore the selector state from the last session. */ + + selector = E_SOURCE_SELECTOR (priv->selector); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); + + g_signal_connect_swapped ( + model, "row-changed", + G_CALLBACK (task_shell_sidebar_row_changed_cb), + object); + + source = NULL; + uid = calendar_config_get_primary_tasks (); + if (uid != NULL) + source = e_source_list_peek_source_by_uid (source_list, uid); + if (source == NULL) + source = e_source_list_peek_source_any (source_list); + if (source != NULL) + e_source_selector_set_primary_selection (selector, source); + g_free (uid); + + list = calendar_config_get_tasks_selected (); + for (iter = list; iter != NULL; iter = iter->next) { + uid = iter->data; + source = e_source_list_peek_source_by_uid (source_list, uid); + g_free (uid); + + if (source == NULL) + continue; + + e_source_selector_select_source (selector, source); + } + g_slist_free (list); + + /* Listen for subsequent changes to the selector. */ + + g_signal_connect_swapped ( + widget, "selection-changed", + G_CALLBACK (task_shell_sidebar_selection_changed_cb), + object); + + g_signal_connect_swapped ( + widget, "primary-selection-changed", + G_CALLBACK (task_shell_sidebar_primary_selection_changed_cb), + object); +} + +static guint32 +task_shell_sidebar_check_state (EShellSidebar *shell_sidebar) +{ + ETaskShellSidebar *task_shell_sidebar; + ESourceSelector *selector; + ESource *source; + gboolean is_system = FALSE; + guint32 state = 0; + + task_shell_sidebar = E_TASK_SHELL_SIDEBAR (shell_sidebar); + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + + if (source != NULL) { + const gchar *uri; + + uri = e_source_peek_relative_uri (source); + is_system = (uri == NULL || strcmp (uri, "system") == 0); + } + + if (source != NULL) + state |= E_TASK_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE; + if (is_system) + state |= E_TASK_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM; + + return state; +} + +static void +task_shell_sidebar_client_removed (ETaskShellSidebar *task_shell_sidebar, + ECal *client) +{ + ESourceSelector *selector; + GHashTable *client_table; + ESource *source; + const gchar *uid; + + client_table = task_shell_sidebar->priv->client_table; + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + + g_signal_handlers_disconnect_matched ( + client, G_SIGNAL_MATCH_DATA, 0, 0, + NULL, NULL, task_shell_sidebar); + + source = e_cal_get_source (client); + e_source_selector_unselect_source (selector, source); + + uid = e_source_peek_uid (source); + g_hash_table_remove (client_table, uid); + + task_shell_sidebar_emit_status_message (task_shell_sidebar, NULL); +} + +static void +task_shell_sidebar_class_init (ETaskShellSidebarClass *class) +{ + GObjectClass *object_class; + EShellSidebarClass *shell_sidebar_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ETaskShellSidebarPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->get_property = task_shell_sidebar_get_property; + object_class->dispose = task_shell_sidebar_dispose; + object_class->finalize = task_shell_sidebar_finalize; + object_class->constructed = task_shell_sidebar_constructed; + + shell_sidebar_class = E_SHELL_SIDEBAR_CLASS (class); + shell_sidebar_class->check_state = task_shell_sidebar_check_state; + + class->client_removed = task_shell_sidebar_client_removed; + + g_object_class_install_property ( + object_class, + PROP_SELECTOR, + g_param_spec_object ( + "selector", + _("Source Selector Widget"), + _("This widget displays groups of task lists"), + E_TYPE_SOURCE_SELECTOR, + G_PARAM_READABLE)); + + signals[CLIENT_ADDED] = g_signal_new ( + "client-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ETaskShellSidebarClass, client_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CAL); + + signals[CLIENT_REMOVED] = g_signal_new ( + "client-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ETaskShellSidebarClass, client_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CAL); + + signals[STATUS_MESSAGE] = g_signal_new ( + "status-message", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (ETaskShellSidebarClass, status_message), + NULL, NULL, + e_marshal_VOID__STRING_DOUBLE, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_DOUBLE); +} + +static void +task_shell_sidebar_init (ETaskShellSidebar *task_shell_sidebar) +{ + GHashTable *client_table; + + client_table = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_object_unref); + + task_shell_sidebar->priv = + E_TASK_SHELL_SIDEBAR_GET_PRIVATE (task_shell_sidebar); + + task_shell_sidebar->priv->client_table = client_table; + + /* Postpone widget construction until we have a shell view. */ +} + +GType +e_task_shell_sidebar_get_type (void) +{ + return task_shell_sidebar_type; +} + +void +e_task_shell_sidebar_register_type (GTypeModule *type_module) +{ + static const GTypeInfo type_info = { + sizeof (ETaskShellSidebarClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) task_shell_sidebar_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ETaskShellSidebar), + 0, /* n_preallocs */ + (GInstanceInitFunc) task_shell_sidebar_init, + NULL /* value_table */ + }; + + task_shell_sidebar_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_SIDEBAR, + "ETaskShellSidebar", &type_info, 0); +} + +GtkWidget * +e_task_shell_sidebar_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_TASK_SHELL_SIDEBAR, + "shell-view", shell_view, NULL); +} + +GList * +e_task_shell_sidebar_get_clients (ETaskShellSidebar *task_shell_sidebar) +{ + GHashTable *client_table; + + g_return_val_if_fail ( + E_IS_TASK_SHELL_SIDEBAR (task_shell_sidebar), NULL); + + client_table = task_shell_sidebar->priv->client_table; + + return g_hash_table_get_values (client_table); +} + +ESourceSelector * +e_task_shell_sidebar_get_selector (ETaskShellSidebar *task_shell_sidebar) +{ + g_return_val_if_fail ( + E_IS_TASK_SHELL_SIDEBAR (task_shell_sidebar), NULL); + + return E_SOURCE_SELECTOR (task_shell_sidebar->priv->selector); +} + +void +e_task_shell_sidebar_add_source (ETaskShellSidebar *task_shell_sidebar, + ESource *source) +{ + ESourceSelector *selector; + GHashTable *client_table; + ECal *client; + const gchar *uid; + const gchar *uri; + gchar *message; + + g_return_if_fail (E_IS_TASK_SHELL_SIDEBAR (task_shell_sidebar)); + g_return_if_fail (E_IS_SOURCE (source)); + + client_table = task_shell_sidebar->priv->client_table; + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + + uid = e_source_peek_uid (source); + client = g_hash_table_lookup (client_table, uid); + + if (client != NULL) + return; + + client = auth_new_cal_from_source (source, E_CAL_SOURCE_TYPE_TODO); + g_return_if_fail (client != NULL); + + g_signal_connect_swapped ( + client, "backend-died", + G_CALLBACK (task_shell_sidebar_backend_died_cb), + task_shell_sidebar); + + g_signal_connect_swapped ( + client, "backend-error", + G_CALLBACK (task_shell_sidebar_backend_error_cb), + task_shell_sidebar); + + g_hash_table_insert (client_table, g_strdup (uid), client); + e_source_selector_select_source (selector, source); + + uri = e_cal_get_uri (client); + message = g_strdup_printf (_("Opening tasks at %s"), uri); + task_shell_sidebar_emit_status_message (task_shell_sidebar, message); + g_free (message); + + g_signal_connect_swapped ( + client, "cal-opened", + G_CALLBACK (task_shell_sidebar_client_opened_cb), + task_shell_sidebar); + + e_cal_open_async (client, FALSE); +} + +void +e_task_shell_sidebar_remove_source (ETaskShellSidebar *task_shell_sidebar, + ESource *source) +{ + ESourceSelector *selector; + GHashTable *client_table; + ECal *client; + const gchar *uid; + + g_return_if_fail (E_IS_TASK_SHELL_SIDEBAR (task_shell_sidebar)); + g_return_if_fail (E_IS_SOURCE (source)); + + client_table = task_shell_sidebar->priv->client_table; + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + + uid = e_source_peek_uid (source); + client = g_hash_table_lookup (client_table, uid); + + if (client == NULL) + return; + + task_shell_sidebar_emit_client_removed (task_shell_sidebar, client); +} diff --git a/modules/calendar/e-task-shell-sidebar.h b/modules/calendar/e-task-shell-sidebar.h new file mode 100644 index 0000000000..5d4c74fe11 --- /dev/null +++ b/modules/calendar/e-task-shell-sidebar.h @@ -0,0 +1,97 @@ +/* + * e-task-shell-sidebar.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_TASK_SHELL_SIDEBAR_H +#define E_TASK_SHELL_SIDEBAR_H + +#include +#include + +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_TASK_SHELL_SIDEBAR \ + (e_task_shell_sidebar_get_type ()) +#define E_TASK_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_TASK_SHELL_SIDEBAR, ETaskShellSidebar)) +#define E_TASK_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_TASK_SHELL_SIDEBAR, ETaskShellSidebarClass)) +#define E_IS_TASK_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_TASK_SHELL_SIDEBAR)) +#define E_IS_TASK_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_TASK_SHELL_SIDEBAR)) +#define E_TASK_SHELL_SIDEBAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_TASK_SHELL_SIDEBAR, ETaskShellSidebarClass)) + +G_BEGIN_DECLS + +typedef struct _ETaskShellSidebar ETaskShellSidebar; +typedef struct _ETaskShellSidebarClass ETaskShellSidebarClass; +typedef struct _ETaskShellSidebarPrivate ETaskShellSidebarPrivate; + +enum { + E_TASK_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE = 1 << 0, + E_TASK_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM = 1 << 1 +}; + +struct _ETaskShellSidebar { + EShellSidebar parent; + ETaskShellSidebarPrivate *priv; +}; + +struct _ETaskShellSidebarClass { + EShellSidebarClass parent_class; + + /* Signals */ + void (*client_added) (ETaskShellSidebar *task_shell_sidebar, + ECal *client); + void (*client_removed) (ETaskShellSidebar *task_shell_sidebar, + ECal *client); + void (*status_message) (ETaskShellSidebar *task_shell_sidebar, + const gchar *status_message, + gdouble percent); +}; + +GType e_task_shell_sidebar_get_type (void); +void e_task_shell_sidebar_register_type + (GTypeModule *type_module); +GtkWidget * e_task_shell_sidebar_new(EShellView *shell_view); +GList * e_task_shell_sidebar_get_clients + (ETaskShellSidebar *task_shell_sidebar); +ESourceSelector * + e_task_shell_sidebar_get_selector + (ETaskShellSidebar *task_shell_sidebar); +void e_task_shell_sidebar_add_source + (ETaskShellSidebar *task_shell_sidebar, + ESource *source); +void e_task_shell_sidebar_remove_source + (ETaskShellSidebar *task_shell_sidebar, + ESource *source); + +G_END_DECLS + +#endif /* E_TASK_SHELL_SIDEBAR_H */ diff --git a/modules/calendar/e-task-shell-view-actions.c b/modules/calendar/e-task-shell-view-actions.c new file mode 100644 index 0000000000..4deed9fdf0 --- /dev/null +++ b/modules/calendar/e-task-shell-view-actions.c @@ -0,0 +1,1154 @@ +/* + * e-task-shell-view-actions.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-task-shell-view-private.h" + +static void +action_gal_save_custom_view_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + EShellView *shell_view; + GalViewInstance *view_instance; + + /* All shell views respond to the activation of this action, + * which is defined by EShellWindow. But only the currently + * active shell view proceeds with saving the custom view. */ + shell_view = E_SHELL_VIEW (task_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + task_shell_content = task_shell_view->priv->task_shell_content; + view_instance = e_task_shell_content_get_view_instance (task_shell_content); + gal_view_instance_save_as (view_instance); +} + +static void +action_search_execute_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + EShellView *shell_view; + + /* All shell views respond to the activation of this action, + * which is defined by EShellWindow. But only the currently + * active shell view proceeds with executing the search. */ + shell_view = E_SHELL_VIEW (task_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + e_task_shell_view_execute_search (task_shell_view); +} + +static void +action_search_filter_cb (GtkRadioAction *action, + GtkRadioAction *current, + ETaskShellView *task_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + gtk_action_activate (ACTION (SEARCH_EXECUTE)); +} + +static void +action_task_assign_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + GSList *list; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only open the first selected task. */ + e_task_shell_view_open_task (task_shell_view, comp_data); + + /* FIXME Need to actually assign the task. */ +} + +static void +action_task_clipboard_copy_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + e_calendar_table_copy_clipboard (task_table); +} + +static void +action_task_clipboard_cut_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + e_calendar_table_cut_clipboard (task_table); +} + +static void +action_task_clipboard_paste_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + e_calendar_table_paste_clipboard (task_table); +} + +static void +action_task_delete_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalComponentPreview *task_preview; + ECalendarTable *task_table; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + task_preview = e_task_shell_content_get_task_preview (task_shell_content); + + e_task_shell_view_set_status_message ( + task_shell_view, _("Deleting selected tasks..."), -1.0); + e_calendar_table_delete_selected (task_table); + e_task_shell_view_set_status_message (task_shell_view, NULL, -1.0); + + e_cal_component_preview_clear (task_preview); +} + +static void +action_task_forward_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + ECalComponent *comp; + icalcomponent *clone; + GSList *list; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only forward the first selected task. */ + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_component_set_icalcomponent (comp, clone); + itip_send_comp ( + E_CAL_COMPONENT_METHOD_PUBLISH, comp, + comp_data->client, NULL, NULL, NULL, TRUE); + g_object_unref (comp); +} + +static void +action_task_list_copy_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellSidebar *task_shell_sidebar; + EShellWindow *shell_window; + EShellView *shell_view; + ESourceSelector *selector; + ESource *source; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (E_IS_SOURCE (source)); + + copy_source_dialog ( + GTK_WINDOW (shell_window), + source, E_CAL_SOURCE_TYPE_TODO); +} + +static void +action_task_list_delete_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellBackend *task_shell_backend; + ETaskShellContent *task_shell_content; + ETaskShellSidebar *task_shell_sidebar; + EShellWindow *shell_window; + EShellView *shell_view; + ECalendarTable *task_table; + ECal *client; + ECalModel *model; + ESourceSelector *selector; + ESourceGroup *source_group; + ESourceList *source_list; + ESource *source; + gint response; + gchar *uri; + GError *error = NULL; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + task_shell_backend = task_shell_view->priv->task_shell_backend; + source_list = e_task_shell_backend_get_source_list (task_shell_backend); + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + model = e_calendar_table_get_model (task_table); + + task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (E_IS_SOURCE (source)); + + /* Ask for confirmation. */ + response = e_error_run ( + GTK_WINDOW (shell_window), + "calendar:prompt-delete-task-list", + e_source_peek_name (source)); + if (response != GTK_RESPONSE_YES) + return; + + uri = e_source_get_uri (source); + client = e_cal_model_get_client_for_uri (model, uri); + if (client == NULL) + client = e_cal_new_from_uri (uri, E_CAL_SOURCE_TYPE_JOURNAL); + g_free (uri); + + g_return_if_fail (client != NULL); + + if (!e_cal_remove (client, &error)) { + g_warning ("%s", error->message); + g_error_free (error); + return; + } + + if (e_source_selector_source_is_selected (selector, source)) { + e_task_shell_sidebar_remove_source ( + task_shell_sidebar, source); + e_source_selector_unselect_source (selector, source); + } + + source_group = e_source_peek_group (source); + e_source_group_remove_source (source_group, source); + + if (!e_source_list_sync (source_list, &error)) { + g_warning ("%s", error->message); + g_error_free (error); + } +} + +static void +action_task_list_new_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + calendar_setup_new_task_list (GTK_WINDOW (shell_window)); +} + +static void +action_task_list_print_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ETable *table; + GtkPrintOperationAction print_action; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + table = e_calendar_table_get_table (task_table); + + print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; + print_table (table, _("Print Tasks"), _("Tasks"), print_action); +} + +static void +action_task_list_print_preview_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ETable *table; + GtkPrintOperationAction print_action; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + table = e_calendar_table_get_table (task_table); + + print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW; + print_table (table, _("Print Tasks"), _("Tasks"), print_action); +} + +static void +action_task_list_properties_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellSidebar *task_shell_sidebar; + EShellView *shell_view; + EShellWindow *shell_window; + ESource *source; + ESourceSelector *selector; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (E_IS_SOURCE (source)); + + calendar_setup_edit_task_list (GTK_WINDOW (shell_window), source); +} + +static void +action_task_list_rename_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellSidebar *task_shell_sidebar; + ESourceSelector *selector; + + task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + + e_source_selector_edit_primary_selection (selector); +} + +static void +action_task_list_select_one_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellSidebar *task_shell_sidebar; + ESourceSelector *selector; + ESource *primary; + GSList *list, *iter; + + /* XXX ESourceSelector should provide a function for this. */ + + task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + primary = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (primary != NULL); + + list = e_source_selector_get_selection (selector); + for (iter = list; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + + if (source == primary) + continue; + + e_source_selector_unselect_source (selector, source); + } + e_source_selector_free_selection (list); + + e_source_selector_select_source (selector, primary); +} + +static void +action_task_mark_complete_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModel *model; + GSList *list, *iter; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + list = e_calendar_table_get_selected (task_table); + model = e_calendar_table_get_model (task_table); + + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + e_cal_model_tasks_mark_comp_complete ( + E_CAL_MODEL_TASKS (model), comp_data); + } + + g_slist_free (list); +} + +static void +action_task_mark_incomplete_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModel *model; + GSList *list, *iter; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + list = e_calendar_table_get_selected (task_table); + model = e_calendar_table_get_model (task_table); + + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + e_cal_model_tasks_mark_comp_incomplete ( + E_CAL_MODEL_TASKS (model), comp_data); + } + + g_slist_free (list); +} + +static void +action_task_new_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + ECal *client; + ECalComponent *comp; + CompEditor *editor; + GSList *list; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + client = comp_data->client; + editor = task_editor_new (client, shell, COMP_EDITOR_NEW_ITEM); + comp = cal_comp_task_new_with_defaults (client); + comp_editor_edit_comp (editor, comp); + + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (comp); + g_object_unref (client); +} + +static void +action_task_open_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + GSList *list; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only open the first selected task. */ + e_task_shell_view_open_task (task_shell_view, comp_data); +} + +static void +action_task_open_url_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + icalproperty *prop; + const gchar *uri; + GSList *list; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + + /* XXX We only open the URI of the first selected task. */ + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_URL_PROPERTY); + g_return_if_fail (prop == NULL); + + uri = icalproperty_get_url (prop); + e_show_uri (GTK_WINDOW (shell_window), uri); +} + +static void +action_task_preview_cb (GtkToggleAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + gboolean visible; + + task_shell_content = task_shell_view->priv->task_shell_content; + visible = gtk_toggle_action_get_active (action); + e_task_shell_content_set_preview_visible (task_shell_content, visible); +} + +static void +action_task_print_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + ECalComponent *comp; + icalcomponent *clone; + GtkPrintOperationAction print_action; + GSList *list; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only print the first selected task. */ + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; + e_cal_component_set_icalcomponent (comp, clone); + print_comp (comp, comp_data->client, print_action); + g_object_unref (comp); +} + +static void +action_task_purge_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkWidget *dialog; + GtkWidget *widget; + gboolean active; + gint response; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + if (!calendar_config_get_confirm_purge ()) + goto purge; + + /* XXX This needs reworked. The dialog looks like ass. */ + + dialog = gtk_message_dialog_new ( + GTK_WINDOW (shell_window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_YES_NO, + "%s", _("This operation will permanently erase all tasks " + "marked as completed. If you continue, you will not be able " + "to recover these tasks.\n\nReally erase these tasks?")); + + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_NO); + + widget = gtk_check_button_new_with_label (_("Do not ask me again")); + gtk_box_pack_start ( + GTK_BOX (GTK_DIALOG (dialog)->vbox), widget, TRUE, TRUE, 6); + gtk_widget_show (widget); + + response = gtk_dialog_run (GTK_DIALOG (dialog)); + active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)); + gtk_widget_destroy (dialog); + + if (response != GTK_RESPONSE_YES) + return; + + if (active) + calendar_config_set_confirm_purge (FALSE); + +purge: + + /* FIXME */ + ; +} + +static void +action_task_save_as_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + GSList *list; + gchar *filename; + gchar *string; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + filename = e_file_dialog_save (_("Save as..."), NULL); + if (filename == NULL) + return; + + string = e_cal_get_component_as_string ( + comp_data->client, comp_data->icalcomp); + if (string == NULL) { + g_warning ("Could not convert task to a string"); + return; + } + + e_write_file_uri (filename, string); + + g_free (filename); + g_free (string); +} + +static void +action_task_search_cb (GtkRadioAction *action, + GtkRadioAction *current, + ETaskShellView *task_shell_view) +{ + EShellView *shell_view; + EShellContent *shell_content; + const gchar *search_hint; + + /* XXX Figure out a way to handle this in EShellContent + * instead of every shell view having to handle it. + * The problem is EShellContent does not know what + * the search option actions are for this view. It + * would have to dig up the popup menu and retrieve + * the action for each menu item. Seems messy. */ + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + + search_hint = gtk_action_get_label (GTK_ACTION (current)); + e_shell_content_set_search_hint (shell_content, search_hint); +} + +static GtkActionEntry task_entries[] = { + + { "task-assign", + NULL, + N_("_Assign Task"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_task_assign_cb) }, + + { "task-clipboard-copy", + GTK_STOCK_COPY, + NULL, + NULL, + N_("Copy selected tasks"), + G_CALLBACK (action_task_clipboard_copy_cb) }, + + { "task-clipboard-cut", + GTK_STOCK_CUT, + NULL, + NULL, + N_("Cut selected tasks"), + G_CALLBACK (action_task_clipboard_cut_cb) }, + + { "task-clipboard-paste", + GTK_STOCK_PASTE, + NULL, + NULL, + N_("Paste tasks from the clipboard"), + G_CALLBACK (action_task_clipboard_paste_cb) }, + + { "task-delete", + GTK_STOCK_DELETE, + N_("_Delete Task"), + NULL, + N_("Delete selected tasks"), + G_CALLBACK (action_task_delete_cb) }, + + { "task-forward", + "mail-forward", + N_("_Forward as iCalendar..."), + "f", + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_task_forward_cb) }, + + { "task-list-copy", + GTK_STOCK_COPY, + N_("Copy..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_task_list_copy_cb) }, + + { "task-list-delete", + GTK_STOCK_DELETE, + N_("_Delete"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_task_list_delete_cb) }, + + { "task-list-new", + "stock_todo", + N_("_New Task List"), + NULL, + N_("Create a new task list"), + G_CALLBACK (action_task_list_new_cb) }, + + { "task-list-properties", + GTK_STOCK_PROPERTIES, + NULL, + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_task_list_properties_cb) }, + + { "task-list-rename", + NULL, + N_("_Rename..."), + "F2", + N_("Rename the selected task list"), + G_CALLBACK (action_task_list_rename_cb) }, + + { "task-list-select-one", + "stock_check-filled", + N_("Show _Only This Task List"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_task_list_select_one_cb) }, + + { "task-mark-complete", + NULL, + N_("_Mark as Complete"), + "k", + N_("Mark selected tasks as complete"), + G_CALLBACK (action_task_mark_complete_cb) }, + + { "task-mark-incomplete", + NULL, + N_("Mar_k as Incomplete"), + NULL, + N_("Mark selected tasks as incomplete"), + G_CALLBACK (action_task_mark_incomplete_cb) }, + + { "task-new", + "stock_task", + N_("New _Task"), + NULL, + N_("Create a new task"), + G_CALLBACK (action_task_new_cb) }, + + { "task-open", + GTK_STOCK_OPEN, + N_("_Open Task"), + "o", + N_("View the selected task"), + G_CALLBACK (action_task_open_cb) }, + + { "task-open-url", + "applications-internet", + N_("Open _Web Page"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_task_open_url_cb) }, + + { "task-purge", + NULL, + N_("Purg_e"), + "e", + N_("Delete completed tasks"), + G_CALLBACK (action_task_purge_cb) }, + + { "task-save-as", + GTK_STOCK_SAVE_AS, + N_("_Save as iCalendar..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_task_save_as_cb) }, + + /*** Menus ***/ + + { "task-actions-menu", + NULL, + N_("_Actions"), + NULL, + NULL, + NULL } +}; + +static EPopupActionEntry task_popup_entries[] = { + + { "task-list-popup-copy", + NULL, + "task-list-copy" }, + + { "task-list-popup-delete", + NULL, + "task-list-delete" }, + + { "task-list-popup-properties", + NULL, + "task-list-properties" }, + + { "task-list-popup-rename", + NULL, + "task-list-rename" }, + + { "task-list-popup-select-one", + NULL, + "task-list-select-one" }, + + { "task-popup-assign", + NULL, + "task-assign" }, + + { "task-popup-clipboard-copy", + NULL, + "task-clipboard-copy" }, + + { "task-popup-clipboard-cut", + NULL, + "task-clipboard-cut" }, + + { "task-popup-clipboard-paste", + NULL, + "task-clipboard-paste" }, + + { "task-popup-delete", + NULL, + "task-delete" }, + + { "task-popup-forward", + NULL, + "task-forward" }, + + { "task-popup-mark-complete", + NULL, + "task-mark-complete" }, + + { "task-popup-mark-incomplete", + NULL, + "task-mark-incomplete" }, + + { "task-popup-open", + NULL, + "task-open" }, + + { "task-popup-open-url", + NULL, + "task-open-url" }, + + { "task-popup-save-as", + NULL, + "task-save-as" }, +}; + +static GtkToggleActionEntry task_toggle_entries[] = { + + { "task-preview", + NULL, + N_("Task _Preview"), + "m", + N_("Show task preview pane"), + G_CALLBACK (action_task_preview_cb), + TRUE } +}; + +static GtkRadioActionEntry task_filter_entries[] = { + + { "task-filter-active-tasks", + NULL, + N_("Active Tasks"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_FILTER_ACTIVE_TASKS }, + + { "task-filter-any-category", + NULL, + N_("Any Category"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_FILTER_ANY_CATEGORY }, + + { "task-filter-completed-tasks", + NULL, + N_("Completed Tasks"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_FILTER_COMPLETED_TASKS }, + + { "task-filter-next-7-days-tasks", + NULL, + N_("Next 7 Days' Tasks"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_FILTER_NEXT_7_DAYS_TASKS }, + + { "task-filter-overdue-tasks", + NULL, + N_("Overdue Tasks"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_FILTER_OVERDUE_TASKS }, + + { "task-filter-tasks-with-attachments", + NULL, + N_("Tasks with Attachments"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_FILTER_TASKS_WITH_ATTACHMENTS }, + + { "task-filter-unmatched", + NULL, + N_("Unmatched"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_FILTER_UNMATCHED } +}; + +static GtkRadioActionEntry task_search_entries[] = { + + { "task-search-any-field-contains", + NULL, + N_("Any field contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_SEARCH_ANY_FIELD_CONTAINS }, + + { "task-search-description-contains", + NULL, + N_("Description contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_SEARCH_DESCRIPTION_CONTAINS }, + + { "task-search-summary-contains", + NULL, + N_("Summary contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_SEARCH_SUMMARY_CONTAINS } +}; + +static GtkActionEntry lockdown_printing_entries[] = { + + { "task-list-print", + GTK_STOCK_PRINT, + NULL, + "p", + N_("Print the list of tasks"), + G_CALLBACK (action_task_list_print_cb) }, + + { "task-list-print-preview", + GTK_STOCK_PRINT_PREVIEW, + NULL, + NULL, + N_("Preview the list of tasks to be printed"), + G_CALLBACK (action_task_list_print_preview_cb) }, + + { "task-print", + GTK_STOCK_PRINT, + NULL, + NULL, + N_("Print the selected task"), + G_CALLBACK (action_task_print_cb) } +}; + +static EPopupActionEntry lockdown_printing_popup_entries[] = { + + { "task-popup-print", + NULL, + "task-print" } +}; + +void +e_task_shell_view_actions_init (ETaskShellView *task_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkActionGroup *action_group; + GConfBridge *bridge; + GtkAction *action; + GObject *object; + const gchar *key; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + /* Task Actions */ + action_group = ACTION_GROUP (TASKS); + gtk_action_group_add_actions ( + action_group, task_entries, + G_N_ELEMENTS (task_entries), task_shell_view); + e_action_group_add_popup_actions ( + action_group, task_popup_entries, + G_N_ELEMENTS (task_popup_entries)); + gtk_action_group_add_toggle_actions ( + action_group, task_toggle_entries, + G_N_ELEMENTS (task_toggle_entries), task_shell_view); + gtk_action_group_add_radio_actions ( + action_group, task_search_entries, + G_N_ELEMENTS (task_search_entries), + TASK_SEARCH_SUMMARY_CONTAINS, + G_CALLBACK (action_task_search_cb), task_shell_view); + + /* Lockdown Printing Actions */ + action_group = ACTION_GROUP (LOCKDOWN_PRINTING); + gtk_action_group_add_actions ( + action_group, lockdown_printing_entries, + G_N_ELEMENTS (lockdown_printing_entries), task_shell_view); + e_action_group_add_popup_actions ( + action_group, lockdown_printing_popup_entries, + G_N_ELEMENTS (lockdown_printing_popup_entries)); + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (ACTION (TASK_PREVIEW)); + key = "/apps/evolution/calendar/display/show_task_preview"; + gconf_bridge_bind_property (bridge, key, object, "active"); + + /* Fine tuning. */ + + action = ACTION (TASK_DELETE); + g_object_set (action, "short-label", _("Delete"), NULL); + + g_signal_connect ( + ACTION (GAL_SAVE_CUSTOM_VIEW), "activate", + G_CALLBACK (action_gal_save_custom_view_cb), task_shell_view); + + g_signal_connect ( + ACTION (SEARCH_EXECUTE), "activate", + G_CALLBACK (action_search_execute_cb), task_shell_view); +} + +void +e_task_shell_view_update_search_filter (ETaskShellView *task_shell_view) +{ + EShellContent *shell_content; + EShellWindow *shell_window; + EShellView *shell_view; + GtkActionGroup *action_group; + GtkRadioAction *radio_action; + GList *list, *iter; + GSList *group; + gint ii; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + action_group = ACTION_GROUP (TASKS_FILTER); + e_action_group_remove_all_actions (action_group); + + /* Add the standard filter actions. */ + gtk_action_group_add_radio_actions ( + action_group, task_filter_entries, + G_N_ELEMENTS (task_filter_entries), + TASK_FILTER_ANY_CATEGORY, + G_CALLBACK (action_search_filter_cb), + task_shell_view); + + /* Retrieve the radio group from an action we just added. */ + list = gtk_action_group_list_actions (action_group); + radio_action = GTK_RADIO_ACTION (list->data); + group = gtk_radio_action_get_group (radio_action); + g_list_free (list); + + /* Build the category actions. */ + + list = e_categories_get_list (); + for (iter = list, ii = 0; iter != NULL; iter = iter->next, ii++) { + const gchar *category_name = iter->data; + const gchar *filename; + GtkAction *action; + gchar *action_name; + + action_name = g_strdup_printf ( + "task-filter-category-%d", ii); + radio_action = gtk_radio_action_new ( + action_name, category_name, NULL, NULL, ii); + g_free (action_name); + + /* Convert the category icon file to a themed icon name. */ + filename = e_categories_get_icon_file_for (category_name); + if (filename != NULL && *filename != '\0') { + gchar *basename; + gchar *cp; + + basename = g_path_get_basename (filename); + + /* Lose the file extension. */ + if ((cp = strrchr (basename, '.')) != NULL) + *cp = '\0'; + + g_object_set ( + radio_action, "icon-name", basename, NULL); + + g_free (basename); + } + + gtk_radio_action_set_group (radio_action, group); + group = gtk_radio_action_get_group (radio_action); + + /* The action group takes ownership of the action. */ + action = GTK_ACTION (radio_action); + gtk_action_group_add_action (action_group, action); + g_object_unref (radio_action); + } + g_list_free (list); + + /* Use any action in the group; doesn't matter which. */ + e_shell_content_set_filter_action (shell_content, radio_action); + + ii = TASK_FILTER_UNMATCHED; + e_shell_content_add_filter_separator_after (shell_content, ii); + + ii = TASK_FILTER_TASKS_WITH_ATTACHMENTS; + e_shell_content_add_filter_separator_after (shell_content, ii); +} diff --git a/modules/calendar/e-task-shell-view-actions.h b/modules/calendar/e-task-shell-view-actions.h new file mode 100644 index 0000000000..d7db39bcc9 --- /dev/null +++ b/modules/calendar/e-task-shell-view-actions.h @@ -0,0 +1,105 @@ +/* + * e-task-shell-view-actions.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_TASK_SHELL_VIEW_ACTIONS_H +#define E_TASK_SHELL_VIEW_ACTIONS_H + +#include + +/* Task Actions */ +#define E_SHELL_WINDOW_ACTION_TASK_ASSIGN(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-assign") +#define E_SHELL_WINDOW_ACTION_TASK_CLIPBOARD_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-clipboard-copy") +#define E_SHELL_WINDOW_ACTION_TASK_CLIPBOARD_CUT(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-clipboard-cut") +#define E_SHELL_WINDOW_ACTION_TASK_CLIPBOARD_PASTE(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-clipboard-paste") +#define E_SHELL_WINDOW_ACTION_TASK_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-delete") +#define E_SHELL_WINDOW_ACTION_TASK_FORWARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-forward") +#define E_SHELL_WINDOW_ACTION_TASK_MARK_COMPLETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-mark-complete") +#define E_SHELL_WINDOW_ACTION_TASK_MARK_INCOMPLETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-mark-incomplete") +#define E_SHELL_WINDOW_ACTION_TASK_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-new") +#define E_SHELL_WINDOW_ACTION_TASK_OPEN(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-open") +#define E_SHELL_WINDOW_ACTION_TASK_OPEN_URL(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-open-url") +#define E_SHELL_WINDOW_ACTION_TASK_PREVIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-preview") +#define E_SHELL_WINDOW_ACTION_TASK_PRINT(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-print") +#define E_SHELL_WINDOW_ACTION_TASK_PURGE(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-purge") +#define E_SHELL_WINDOW_ACTION_TASK_SAVE_AS(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-save-as") + +/* Task List Actions */ +#define E_SHELL_WINDOW_ACTION_TASK_LIST_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-list-copy") +#define E_SHELL_WINDOW_ACTION_TASK_LIST_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-list-delete") +#define E_SHELL_WINDOW_ACTION_TASK_LIST_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-list-new") +#define E_SHELL_WINDOW_ACTION_TASK_LIST_PRINT(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-list-print") +#define E_SHELL_WINDOW_ACTION_TASK_LIST_PRINT_PREVIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-list-print-preview") +#define E_SHELL_WINDOW_ACTION_TASK_LIST_PROPERTIES(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-list-properties") +#define E_SHELL_WINDOW_ACTION_TASK_LIST_RENAME(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-list-rename") +#define E_SHELL_WINDOW_ACTION_TASK_LIST_SELECT_ONE(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-list-select-one") + +/* Task Query Actions */ +#define E_SHELL_WINDOW_ACTION_TASK_FILTER_ACTIVE_TASKS(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-filter-active-tasks") +#define E_SHELL_WINDOW_ACTION_TASK_FILTER_ANY_CATEGORY(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-filter-any-category") +#define E_SHELL_WINDOW_ACTION_TASK_FILTER_COMPLETED_TASKS(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-filter-completed-tasks") +#define E_SHELL_WINDOW_ACTION_TASK_FILTER_NEXT_7_DAYS_TASKS(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-filter-next-7-days-tasks") +#define E_SHELL_WINDOW_ACTION_TASK_FILTER_OVERDUE_TASKS(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-filter-overdue-tasks") +#define E_SHELL_WINDOW_ACTION_TASK_FILTER_TASKS_WITH_ATTACHMENTS(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-filter-tasks-with-attachments") +#define E_SHELL_WINDOW_ACTION_TASK_FILTER_UNMATCHED(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-filter-unmatched") +#define E_SHELL_WINDOW_ACTION_TASK_SEARCH_ANY_FIELD_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-search-any-field-contains") +#define E_SHELL_WINDOW_ACTION_TASK_SEARCH_DESCRIPTION_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-search-description-contains") +#define E_SHELL_WINDOW_ACTION_TASK_SEARCH_SUMMARY_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-search-summary-contains") + +/* Action Groups */ +#define E_SHELL_WINDOW_ACTION_GROUP_TASKS(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "tasks") +#define E_SHELL_WINDOW_ACTION_GROUP_TASKS_FILTER(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "tasks-filter") + +#endif /* E_TASK_SHELL_VIEW_ACTIONS_H */ diff --git a/modules/calendar/e-task-shell-view-private.c b/modules/calendar/e-task-shell-view-private.c new file mode 100644 index 0000000000..d6fd8e35aa --- /dev/null +++ b/modules/calendar/e-task-shell-view-private.c @@ -0,0 +1,744 @@ +/* + * e-task-shell-view-private.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-task-shell-view-private.h" + +#include "widgets/menus/gal-view-factory-etable.h" + +static void +task_shell_view_config_hide_completed_tasks_changed_cb (GConfClient *client, + guint id, + GConfEntry *entry, + gpointer user_data) +{ + ETaskShellView *task_shell_view = user_data; + ETaskShellContent *task_shell_content; + ETaskShellSidebar *task_shell_sidebar; + ECalendarTable *task_table; + GList *clients; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; + clients = e_task_shell_sidebar_get_clients (task_shell_sidebar); + + e_calendar_table_process_completed_tasks (task_table, clients, TRUE); + + /* Search query takes whether to show completed tasks into account, + * so if the preference has changed we need to update the query. */ + e_task_shell_view_execute_search (task_shell_view); + + g_list_free (clients); +} + +static void +task_shell_view_config_timezone_changed_cb (GConfClient *client, + guint id, + GConfEntry *entry, + gpointer user_data) +{ + ETaskShellView *task_shell_view = user_data; + + e_task_shell_view_update_timezone (task_shell_view); +} + +static void +task_shell_view_table_popup_event_cb (EShellView *shell_view, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/task-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); +} + +static void +task_shell_view_table_user_created_cb (ETaskShellView *task_shell_view, + ECalendarTable *task_table) +{ + ETaskShellSidebar *task_shell_sidebar; + ECalModel *model; + ECal *client; + ESource *source; + + /* This is the "Click to Add" handler. */ + + model = e_calendar_table_get_model (task_table); + client = e_cal_model_get_default_client (model); + source = e_cal_get_source (client); + + task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; + e_task_shell_sidebar_add_source (task_shell_sidebar, source); + + e_cal_model_add_client (model, client); +} + +static void +task_shell_view_selector_client_added_cb (ETaskShellView *task_shell_view, + ECal *client) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModel *model; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + model = e_calendar_table_get_model (task_table); + + e_cal_model_add_client (model, client); + e_task_shell_view_update_timezone (task_shell_view); +} + +static void +task_shell_view_selector_client_removed_cb (ETaskShellView *task_shell_view, + ECal *client) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModel *model; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + model = e_calendar_table_get_model (task_table); + + e_cal_model_remove_client (model, client); +} + +static gboolean +task_shell_view_selector_popup_event_cb (EShellView *shell_view, + ESource *primary_source, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/task-list-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); + + return TRUE; +} + +static gboolean +task_shell_view_update_timeout_cb (ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ETaskShellSidebar *task_shell_sidebar; + ECalendarTable *task_table; + ECalModel *model; + GList *clients; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + model = e_calendar_table_get_model (task_table); + + task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; + clients = e_task_shell_sidebar_get_clients (task_shell_sidebar); + + e_calendar_table_process_completed_tasks (task_table, clients, FALSE); + e_cal_model_tasks_update_due_tasks (E_CAL_MODEL_TASKS (model)); + + g_list_free (clients); + + return TRUE; +} + +static void +task_shell_view_load_view_collection (EShellViewClass *shell_view_class) +{ + GalViewCollection *collection; + GalViewFactory *factory; + ETableSpecification *spec; + const gchar *base_dir; + gchar *filename; + + collection = shell_view_class->view_collection; + + base_dir = EVOLUTION_ETSPECDIR; + spec = e_table_specification_new (); + filename = g_build_filename (base_dir, ETSPEC_FILENAME, NULL); + if (!e_table_specification_load_from_file (spec, filename)) + g_critical ("Unable to load ETable specification file " + "for tasks"); + g_free (filename); + + factory = gal_view_factory_etable_new (spec); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + g_object_unref (spec); + + gal_view_collection_load (collection); +} + +static void +task_shell_view_notify_view_id_cb (ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + GalViewInstance *view_instance; + const gchar *view_id; + + task_shell_content = task_shell_view->priv->task_shell_content; + view_instance = + e_task_shell_content_get_view_instance (task_shell_content); + view_id = e_shell_view_get_view_id (E_SHELL_VIEW (task_shell_view)); + + /* A NULL view ID implies we're in a custom view. But you can + * only get to a custom view via the "Define Views" dialog, which + * would have already modified the view instance appropriately. + * Furthermore, there's no way to refer to a custom view by ID + * anyway, since custom views have no IDs. */ + if (view_id == NULL) + return; + + gal_view_instance_set_current_view_id (view_instance, view_id); +} + +void +e_task_shell_view_private_init (ETaskShellView *task_shell_view, + EShellViewClass *shell_view_class) +{ + if (!gal_view_collection_loaded (shell_view_class->view_collection)) + task_shell_view_load_view_collection (shell_view_class); + + g_signal_connect ( + task_shell_view, "notify::view-id", + G_CALLBACK (task_shell_view_notify_view_id_cb), NULL); +} + +void +e_task_shell_view_private_constructed (ETaskShellView *task_shell_view) +{ + ETaskShellViewPrivate *priv = task_shell_view->priv; + ETaskShellContent *task_shell_content; + ETaskShellSidebar *task_shell_sidebar; + EShellView *shell_view; + EShellBackend *shell_backend; + EShellContent *shell_content; + EShellSidebar *shell_sidebar; + EShellWindow *shell_window; + ECalendarTable *task_table; + ECalModel *model; + ETable *table; + ESourceSelector *selector; + guint id; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + e_shell_window_add_action_group (shell_window, "tasks"); + e_shell_window_add_action_group (shell_window, "tasks-filter"); + + /* Cache these to avoid lots of awkward casting. */ + priv->task_shell_backend = g_object_ref (shell_backend); + priv->task_shell_content = g_object_ref (shell_content); + priv->task_shell_sidebar = g_object_ref (shell_sidebar); + + task_shell_content = E_TASK_SHELL_CONTENT (shell_content); + task_table = e_task_shell_content_get_task_table (task_shell_content); + model = e_calendar_table_get_model (task_table); + table = e_calendar_table_get_table (task_table); + + task_shell_sidebar = E_TASK_SHELL_SIDEBAR (shell_sidebar); + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + + g_signal_connect_swapped ( + task_table, "open-component", + G_CALLBACK (e_task_shell_view_open_task), + task_shell_view); + + g_signal_connect_swapped ( + task_table, "popup-event", + G_CALLBACK (task_shell_view_table_popup_event_cb), + task_shell_view); + + g_signal_connect_swapped ( + task_table, "status-message", + G_CALLBACK (e_task_shell_view_set_status_message), + task_shell_view); + + g_signal_connect_swapped ( + task_table, "user-created", + G_CALLBACK (task_shell_view_table_user_created_cb), + task_shell_view); + + g_signal_connect_swapped ( + model, "model-changed", + G_CALLBACK (e_task_shell_view_update_sidebar), + task_shell_view); + + g_signal_connect_swapped ( + model, "model-rows-deleted", + G_CALLBACK (e_task_shell_view_update_sidebar), + task_shell_view); + + g_signal_connect_swapped ( + model, "model-rows-inserted", + G_CALLBACK (e_task_shell_view_update_sidebar), + task_shell_view); + + g_signal_connect_swapped ( + table, "selection-change", + G_CALLBACK (e_task_shell_view_update_sidebar), + task_shell_view); + + g_signal_connect_swapped ( + task_shell_sidebar, "client-added", + G_CALLBACK (task_shell_view_selector_client_added_cb), + task_shell_view); + + g_signal_connect_swapped ( + task_shell_sidebar, "client-removed", + G_CALLBACK (task_shell_view_selector_client_removed_cb), + task_shell_view); + + g_signal_connect_swapped ( + task_shell_sidebar, "status-message", + G_CALLBACK (e_task_shell_view_set_status_message), + task_shell_view); + + g_signal_connect_swapped ( + selector, "popup-event", + G_CALLBACK (task_shell_view_selector_popup_event_cb), + task_shell_view); + + g_signal_connect_swapped ( + selector, "primary-selection-changed", + G_CALLBACK (e_shell_view_update_actions), + task_shell_view); + + e_categories_register_change_listener ( + G_CALLBACK (e_task_shell_view_update_search_filter), + task_shell_view); + + task_shell_view_update_timeout_cb (task_shell_view); + priv->update_timeout = g_timeout_add_full ( + G_PRIORITY_LOW, 60000, (GSourceFunc) + task_shell_view_update_timeout_cb, + task_shell_view, NULL); + + /* Listen for configuration changes. */ + + /* Timezone */ + id = calendar_config_add_notification_timezone ( + task_shell_view_config_timezone_changed_cb, task_shell_view); + priv->notifications = g_list_prepend ( + priv->notifications, GUINT_TO_POINTER (id)); + + /* Hide Completed Tasks (enable/units/value) */ + id = calendar_config_add_notification_hide_completed_tasks ( + task_shell_view_config_hide_completed_tasks_changed_cb, + task_shell_view); + priv->notifications = g_list_prepend ( + priv->notifications, GUINT_TO_POINTER (id)); + id = calendar_config_add_notification_hide_completed_tasks_units ( + task_shell_view_config_hide_completed_tasks_changed_cb, + task_shell_view); + priv->notifications = g_list_prepend ( + priv->notifications, GUINT_TO_POINTER (id)); + id = calendar_config_add_notification_hide_completed_tasks_value ( + task_shell_view_config_hide_completed_tasks_changed_cb, + task_shell_view); + priv->notifications = g_list_prepend ( + priv->notifications, GUINT_TO_POINTER (id)); + + e_task_shell_view_actions_init (task_shell_view); + e_task_shell_view_update_sidebar (task_shell_view); + e_task_shell_view_update_search_filter (task_shell_view); + e_task_shell_view_update_timezone (task_shell_view); + + e_task_shell_view_execute_search (task_shell_view); +} + +void +e_task_shell_view_private_dispose (ETaskShellView *task_shell_view) +{ + ETaskShellViewPrivate *priv = task_shell_view->priv; + GList *iter; + + DISPOSE (priv->task_shell_backend); + DISPOSE (priv->task_shell_content); + DISPOSE (priv->task_shell_sidebar); + + if (task_shell_view->priv->activity != NULL) { + /* XXX Activity is no cancellable. */ + e_activity_complete (task_shell_view->priv->activity); + g_object_unref (task_shell_view->priv->activity); + task_shell_view->priv->activity = NULL; + } + + if (priv->update_timeout > 0) { + g_source_remove (priv->update_timeout); + priv->update_timeout = 0; + } + + for (iter = priv->notifications; iter != NULL; iter = iter->next) { + guint notification_id = GPOINTER_TO_UINT (iter->data); + calendar_config_remove_notification (notification_id); + } + g_list_free (priv->notifications); + priv->notifications = NULL; +} + +void +e_task_shell_view_private_finalize (ETaskShellView *task_shell_view) +{ + /* XXX Nothing to do? */ +} + +void +e_task_shell_view_execute_search (ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + EShellView *shell_view; + EShellWindow *shell_window; + EShellContent *shell_content; + GtkAction *action; + GString *string; + ECalComponentPreview *task_preview; + ECalendarTable *task_table; + ECalModel *model; + FilterRule *rule; + const gchar *format; + const gchar *text; + time_t start_range; + time_t end_range; + gchar *start, *end; + gchar *query; + gchar *temp; + gint value; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + text = e_shell_content_get_search_text (shell_content); + + shell_window = e_shell_view_get_shell_window (shell_view); + action = ACTION (TASK_SEARCH_ANY_FIELD_CONTAINS); + value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + + if (text == NULL || *text == '\0') { + text = ""; + value = TASK_SEARCH_SUMMARY_CONTAINS; + } + + switch (value) { + default: + text = ""; + /* fall through */ + + case TASK_SEARCH_SUMMARY_CONTAINS: + format = "(contains? \"summary\" %s)"; + break; + + case TASK_SEARCH_DESCRIPTION_CONTAINS: + format = "(contains? \"description\" %s)"; + break; + + case TASK_SEARCH_ANY_FIELD_CONTAINS: + format = "(contains? \"any\" %s)"; + break; + } + + /* Build the query. */ + string = g_string_new (""); + e_sexp_encode_string (string, text); + query = g_strdup_printf (format, string->str); + g_string_free (string, TRUE); + + /* Apply selected filter. */ + value = e_shell_content_get_filter_value (shell_content); + switch (value) { + case TASK_FILTER_ANY_CATEGORY: + break; + + case TASK_FILTER_UNMATCHED: + temp = g_strdup_printf ( + "(and (has-categories? #f) %s)", query); + g_free (query); + query = temp; + break; + + case TASK_FILTER_NEXT_7_DAYS_TASKS: + start_range = time (NULL); + end_range = time_add_day (start_range, 7); + start = isodate_from_time_t (start_range); + end = isodate_from_time_t (end_range); + + temp = g_strdup_printf ( + "(and %s (due-in-time-range? " + "(make-time \"%s\") (make-time \"%s\")))", + query, start, end); + g_free (query); + query = temp; + break; + + case TASK_FILTER_ACTIVE_TASKS: + start_range = time (NULL); + end_range = time_add_day (start_range, 365); + start = isodate_from_time_t (start_range); + end = isodate_from_time_t (end_range); + + temp = g_strdup_printf ( + "(and %s (due-in-time-range? " + "(make-time \"%s\") (make-time \"%s\")) " + "(not (is-completed?)))", + query, start, end); + g_free (query); + query = temp; + break; + + case TASK_FILTER_OVERDUE_TASKS: + start_range = 0; + end_range = time (NULL); + start = isodate_from_time_t (start_range); + end = isodate_from_time_t (end_range); + + temp = g_strdup_printf ( + "(and %s (due-in-time-range? " + "(make-time \"%s\") (make-time \"%s\")) " + "(not (is-completed?)))", + query, start, end); + g_free (query); + query = temp; + break; + + case TASK_FILTER_COMPLETED_TASKS: + temp = g_strdup_printf ( + "(and (is-completed?) %s)", query); + g_free (query); + query = temp; + break; + + case TASK_FILTER_TASKS_WITH_ATTACHMENTS: + temp = g_strdup_printf ( + "(and (has-attachments?) %s)", query); + g_free (query); + query = temp; + break; + + default: + { + GList *categories; + const gchar *category_name; + + categories = e_categories_get_list (); + category_name = g_list_nth_data (categories, value); + g_list_free (categories); + + temp = g_strdup_printf ( + "(and (has-categories? \"%s\") %s)", + category_name, query); + g_free (query); + query = temp; + break; + } + } + + /* Honor the user's preference to hide completed tasks. */ + temp = calendar_config_get_hide_completed_tasks_sexp (FALSE); + if (temp != NULL) { + gchar *temp2; + + temp2 = g_strdup_printf ("(and %s %s)", temp, query); + g_free (query); + g_free (temp); + query = temp2; + } + + /* XXX This is wrong. We need to programmatically construct a + * FilterRule, tell it to build code, and pass the resulting + * expression string to ECalModel. */ + rule = filter_rule_new (); + e_shell_content_set_search_rule (shell_content, rule); + g_object_unref (rule); + + /* Submit the query. */ + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + model = e_calendar_table_get_model (task_table); + e_cal_model_set_search_query (model, query); + g_free (query); + + task_preview = + e_task_shell_content_get_task_preview (task_shell_content); + e_cal_component_preview_clear (task_preview); +} + +void +e_task_shell_view_open_task (ETaskShellView *task_shell_view, + ECalModelComponent *comp_data) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + CompEditor *editor; + CompEditorFlags flags = 0; + ECalComponent *comp; + icalcomponent *clone; + icalproperty *prop; + const gchar *uid; + + g_return_if_fail (E_IS_TASK_SHELL_VIEW (task_shell_view)); + g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data)); + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + + uid = icalcomponent_get_uid (comp_data->icalcomp); + editor = comp_editor_find_instance (uid); + + if (editor != NULL) + goto exit; + + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_component_set_icalcomponent (comp, clone); + + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_ATTENDEE_PROPERTY); + if (prop != NULL) + flags |= COMP_EDITOR_IS_ASSIGNED; + + if (itip_organizer_is_user (comp, comp_data->client)) + flags |= COMP_EDITOR_USER_ORG; + + if (!e_cal_component_has_attendees (comp)) + flags |= COMP_EDITOR_USER_ORG; + + editor = task_editor_new (comp_data->client, shell, flags); + comp_editor_edit_comp (editor, comp); + + g_object_ref (comp); + + if (flags & COMP_EDITOR_IS_ASSIGNED) + task_editor_show_assignment (TASK_EDITOR (editor)); + +exit: + gtk_window_present (GTK_WINDOW (editor)); +} + +void +e_task_shell_view_set_status_message (ETaskShellView *task_shell_view, + const gchar *status_message, + gdouble percent) +{ + EActivity *activity; + EShellView *shell_view; + EShellBackend *shell_backend; + + g_return_if_fail (E_IS_TASK_SHELL_VIEW (task_shell_view)); + + activity = task_shell_view->priv->activity; + shell_view = E_SHELL_VIEW (task_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + if (status_message == NULL || *status_message == '\0') { + if (activity != NULL) { + e_activity_complete (activity); + g_object_unref (activity); + activity = NULL; + } + + } else if (activity == NULL) { + activity = e_activity_new (status_message); + e_activity_set_percent (activity, percent); + e_shell_backend_add_activity (shell_backend, activity); + + } else { + e_activity_set_percent (activity, percent); + e_activity_set_primary_text (activity, status_message); + } + + task_shell_view->priv->activity = activity; +} + +void +e_task_shell_view_update_sidebar (ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + EShellView *shell_view; + EShellSidebar *shell_sidebar; + ECalendarTable *task_table; + ECalModel *model; + ETable *table; + GString *string; + const gchar *format; + gint n_rows; + gint n_selected; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + model = e_calendar_table_get_model (task_table); + table = e_calendar_table_get_table (task_table); + + n_rows = e_table_model_row_count (E_TABLE_MODEL (model)); + n_selected = e_table_selected_count (table); + + string = g_string_sized_new (64); + + format = ngettext ("%d task", "%d tasks", n_rows); + g_string_append_printf (string, format, n_rows); + + if (n_selected > 0) { + format = _("%d selected"); + g_string_append_len (string, ", ", 2); + g_string_append_printf (string, format, n_selected); + } + + e_shell_sidebar_set_secondary_text (shell_sidebar, string->str); + + g_string_free (string, TRUE); +} + +void +e_task_shell_view_update_timezone (ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ETaskShellSidebar *task_shell_sidebar; + ECalComponentPreview *task_preview; + icaltimezone *timezone; + GList *clients, *iter; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_preview = e_task_shell_content_get_task_preview (task_shell_content); + + task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; + clients = e_task_shell_sidebar_get_clients (task_shell_sidebar); + + timezone = calendar_config_get_icaltimezone (); + + for (iter = clients; iter != NULL; iter = iter->next) { + ECal *client = iter->data; + + if (e_cal_get_load_state (client) == E_CAL_LOAD_LOADED) + e_cal_set_default_timezone (client, timezone, NULL); + } + + e_cal_component_preview_set_default_timezone (task_preview, timezone); + + g_list_free (clients); +} diff --git a/modules/calendar/e-task-shell-view-private.h b/modules/calendar/e-task-shell-view-private.h new file mode 100644 index 0000000000..d3bb3cf086 --- /dev/null +++ b/modules/calendar/e-task-shell-view-private.h @@ -0,0 +1,141 @@ +/* + * e-task-shell-view-private.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_TASK_SHELL_VIEW_PRIVATE_H +#define E_TASK_SHELL_VIEW_PRIVATE_H + +#include "e-task-shell-view.h" + +#include +#include +#include +#include +#include + +#include "e-util/e-dialog-utils.h" +#include "e-util/e-error.h" +#include "e-util/e-util.h" +#include "e-util/gconf-bridge.h" +#include "widgets/misc/e-popup-action.h" + +#include "calendar/common/authentication.h" +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/comp-util.h" +#include "calendar/gui/e-cal-component-preview.h" +#include "calendar/gui/e-cal-model-tasks.h" +#include "calendar/gui/e-calendar-selector.h" +#include "calendar/gui/print.h" +#include "calendar/gui/dialogs/calendar-setup.h" +#include "calendar/gui/dialogs/copy-source-dialog.h" +#include "calendar/gui/dialogs/task-editor.h" + +#include "e-task-shell-backend.h" +#include "e-task-shell-content.h" +#include "e-task-shell-sidebar.h" +#include "e-task-shell-view-actions.h" + +#define E_TASK_SHELL_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_TASK_SHELL_VIEW, ETaskShellViewPrivate)) + +/* Shorthand, requires a variable named "shell_window". */ +#define ACTION(name) \ + (E_SHELL_WINDOW_ACTION_##name (shell_window)) +#define ACTION_GROUP(name) \ + (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) + +/* For use in dispose() methods. */ +#define DISPOSE(obj) \ + G_STMT_START { \ + if ((obj) != NULL) { g_object_unref (obj); (obj) = NULL; } \ + } G_STMT_END + +/* ETable Specifications */ +#define ETSPEC_FILENAME "e-calendar-table.etspec" + +G_BEGIN_DECLS + +/* Filter items are displayed in ascending order. + * Non-negative values are reserved for categories. */ +enum { + TASK_FILTER_ANY_CATEGORY = -7, + TASK_FILTER_UNMATCHED = -6, + TASK_FILTER_NEXT_7_DAYS_TASKS = -5, + TASK_FILTER_ACTIVE_TASKS = -4, + TASK_FILTER_OVERDUE_TASKS = -3, + TASK_FILTER_COMPLETED_TASKS = -2, + TASK_FILTER_TASKS_WITH_ATTACHMENTS = -1 +}; + +/* Search items are displayed in ascending order. */ +enum { + TASK_SEARCH_SUMMARY_CONTAINS, + TASK_SEARCH_DESCRIPTION_CONTAINS, + TASK_SEARCH_ANY_FIELD_CONTAINS +}; + +struct _ETaskShellViewPrivate { + + /* These are just for convenience. */ + ETaskShellBackend *task_shell_backend; + ETaskShellContent *task_shell_content; + ETaskShellSidebar *task_shell_sidebar; + + EActivity *activity; + guint update_timeout; + + /* GConf notification IDs */ + GList *notifications; +}; + +void e_task_shell_view_private_init + (ETaskShellView *task_shell_view, + EShellViewClass *shell_view_class); +void e_task_shell_view_private_constructed + (ETaskShellView *task_shell_view); +void e_task_shell_view_private_dispose + (ETaskShellView *task_shell_view); +void e_task_shell_view_private_finalize + (ETaskShellView *task_shell_view); + +/* Private Utilities */ + +void e_task_shell_view_actions_init + (ETaskShellView *task_shell_view); +void e_task_shell_view_execute_search + (ETaskShellView *task_shell_view); +void e_task_shell_view_open_task + (ETaskShellView *task_shell_view, + ECalModelComponent *comp_data); +void e_task_shell_view_set_status_message + (ETaskShellView *task_shell_view, + const gchar *status_message, + gdouble percent); +void e_task_shell_view_update_sidebar + (ETaskShellView *task_shell_view); +void e_task_shell_view_update_search_filter + (ETaskShellView *task_shell_view); +void e_task_shell_view_update_timezone + (ETaskShellView *task_shell_view); + +G_END_DECLS + +#endif /* E_TASK_SHELL_VIEW_PRIVATE_H */ diff --git a/modules/calendar/e-task-shell-view.c b/modules/calendar/e-task-shell-view.c new file mode 100644 index 0000000000..ce1b53a43c --- /dev/null +++ b/modules/calendar/e-task-shell-view.c @@ -0,0 +1,255 @@ +/* + * e-task-shell-view.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-task-shell-view-private.h" + +static gpointer parent_class; +static GType task_shell_view_type; + +static void +task_shell_view_dispose (GObject *object) +{ + e_task_shell_view_private_dispose (E_TASK_SHELL_VIEW (object)); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +task_shell_view_finalize (GObject *object) +{ + e_task_shell_view_private_finalize (E_TASK_SHELL_VIEW (object)); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +task_shell_view_constructed (GObject *object) +{ + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + e_task_shell_view_private_constructed (E_TASK_SHELL_VIEW (object)); +} + +static void +task_shell_view_update_actions (EShellView *shell_view) +{ + ETaskShellViewPrivate *priv; + EShellContent *shell_content; + EShellSidebar *shell_sidebar; + EShellWindow *shell_window; + GtkAction *action; + const gchar *label; + gboolean sensitive; + guint32 state; + + /* Be descriptive. */ + gboolean any_tasks_selected; + gboolean has_primary_source; + gboolean multiple_tasks_selected; + gboolean primary_source_is_system; + gboolean selection_has_url; + gboolean selection_is_assignable; + gboolean single_task_selected; + gboolean some_tasks_complete; + gboolean some_tasks_incomplete; + gboolean sources_are_editable; + + priv = E_TASK_SHELL_VIEW_GET_PRIVATE (shell_view); + + shell_window = e_shell_view_get_shell_window (shell_view); + + shell_content = e_shell_view_get_shell_content (shell_view); + state = e_shell_content_check_state (shell_content); + + single_task_selected = + (state & E_TASK_SHELL_CONTENT_SELECTION_SINGLE); + multiple_tasks_selected = + (state & E_TASK_SHELL_CONTENT_SELECTION_MULTIPLE); + selection_is_assignable = + (state & E_TASK_SHELL_CONTENT_SELECTION_CAN_ASSIGN); + sources_are_editable = + (state & E_TASK_SHELL_CONTENT_SELECTION_CAN_EDIT); + some_tasks_complete = + (state & E_TASK_SHELL_CONTENT_SELECTION_HAS_COMPLETE); + some_tasks_incomplete = + (state & E_TASK_SHELL_CONTENT_SELECTION_HAS_INCOMPLETE); + selection_has_url = + (state & E_TASK_SHELL_CONTENT_SELECTION_HAS_URL); + + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + state = e_shell_sidebar_check_state (shell_sidebar); + + has_primary_source = + (state & E_TASK_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE); + primary_source_is_system = + (state & E_TASK_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM); + + any_tasks_selected = + (single_task_selected || multiple_tasks_selected); + + action = ACTION (TASK_ASSIGN); + sensitive = + single_task_selected && sources_are_editable && + selection_is_assignable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_CLIPBOARD_COPY); + sensitive = any_tasks_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_CLIPBOARD_CUT); + sensitive = any_tasks_selected && sources_are_editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_CLIPBOARD_PASTE); + sensitive = sources_are_editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_DELETE); + sensitive = any_tasks_selected && sources_are_editable; + gtk_action_set_sensitive (action, sensitive); + if (multiple_tasks_selected) + label = _("Delete Tasks"); + else + label = _("Delete Task"); + g_object_set (action, "label", label, NULL); + + action = ACTION (TASK_FORWARD); + sensitive = single_task_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_LIST_COPY); + sensitive = has_primary_source; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_LIST_DELETE); + sensitive = has_primary_source && !primary_source_is_system; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_LIST_PROPERTIES); + sensitive = has_primary_source; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_LIST_RENAME); + sensitive = has_primary_source; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_MARK_COMPLETE); + sensitive = + any_tasks_selected && + sources_are_editable && + some_tasks_incomplete; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_MARK_INCOMPLETE); + sensitive = + any_tasks_selected && + sources_are_editable && + some_tasks_complete; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_OPEN); + sensitive = single_task_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_OPEN_URL); + sensitive = single_task_selected && selection_has_url; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_PRINT); + sensitive = single_task_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_PURGE); + sensitive = sources_are_editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_SAVE_AS); + sensitive = single_task_selected; + gtk_action_set_sensitive (action, sensitive); +} + +static void +task_shell_view_class_init (ETaskShellViewClass *class, + GTypeModule *type_module) +{ + GObjectClass *object_class; + EShellViewClass *shell_view_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ETaskShellViewPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->dispose = task_shell_view_dispose; + object_class->finalize = task_shell_view_finalize; + object_class->constructed = task_shell_view_constructed; + + shell_view_class = E_SHELL_VIEW_CLASS (class); + shell_view_class->label = _("Tasks"); + shell_view_class->icon_name = "evolution-tasks"; + shell_view_class->ui_definition = "evolution-tasks.ui"; + shell_view_class->ui_manager_id = "org.gnome.evolution.tasks"; + shell_view_class->search_options = "/task-search-options"; + shell_view_class->search_rules = "tasktypes.xml"; + shell_view_class->new_shell_content = e_task_shell_content_new; + shell_view_class->new_shell_sidebar = e_task_shell_sidebar_new; + shell_view_class->update_actions = task_shell_view_update_actions; +} + +static void +task_shell_view_init (ETaskShellView *task_shell_view, + EShellViewClass *shell_view_class) +{ + task_shell_view->priv = + E_TASK_SHELL_VIEW_GET_PRIVATE (task_shell_view); + + e_task_shell_view_private_init (task_shell_view, shell_view_class); +} + +GType +e_task_shell_view_get_type (void) +{ + return task_shell_view_type; +} + +void +e_task_shell_view_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (ETaskShellViewClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) task_shell_view_class_init, + (GClassFinalizeFunc) NULL, + type_module, + sizeof (ETaskShellView), + 0, /* n_preallocs */ + (GInstanceInitFunc) task_shell_view_init, + NULL /* value_table */ + }; + + task_shell_view_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_VIEW, + "ETaskShellView", &type_info, 0); +} diff --git a/modules/calendar/e-task-shell-view.h b/modules/calendar/e-task-shell-view.h new file mode 100644 index 0000000000..8478e53cc2 --- /dev/null +++ b/modules/calendar/e-task-shell-view.h @@ -0,0 +1,67 @@ +/* + * e-task-shell-view.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_TASK_SHELL_VIEW_H +#define E_TASK_SHELL_VIEW_H + +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_TASK_SHELL_VIEW \ + (e_task_shell_view_get_type ()) +#define E_TASK_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_TASK_SHELL_VIEW, ETaskShellView)) +#define E_TASK_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_TASK_SHELL_VIEW, ETaskShellViewClass)) +#define E_IS_TASK_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_TASK_SHELL_VIEW)) +#define E_IS_TASK_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_TASK_SHELL_VIEW)) +#define E_TASK_SHELL_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_TASK_SHELL_VIEW, ETaskShellViewClass)) + +G_BEGIN_DECLS + +typedef struct _ETaskShellView ETaskShellView; +typedef struct _ETaskShellViewClass ETaskShellViewClass; +typedef struct _ETaskShellViewPrivate ETaskShellViewPrivate; + +struct _ETaskShellView { + EShellView parent; + ETaskShellViewPrivate *priv; +}; + +struct _ETaskShellViewClass { + EShellViewClass parent_class; +}; + +GType e_task_shell_view_get_type (void); +void e_task_shell_view_register_type (GTypeModule *type_module); + +G_END_DECLS + +#endif /* E_TASK_SHELL_VIEW_H */ diff --git a/modules/calendar/evolution-module-calendar.c b/modules/calendar/evolution-module-calendar.c new file mode 100644 index 0000000000..63bf98ead9 --- /dev/null +++ b/modules/calendar/evolution-module-calendar.c @@ -0,0 +1,65 @@ +/* + * evolution-module-calendar.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-backend.h" +#include "e-cal-shell-content.h" +#include "e-cal-shell-sidebar.h" +#include "e-cal-shell-view.h" + +#include "e-memo-shell-backend.h" +#include "e-memo-shell-content.h" +#include "e-memo-shell-sidebar.h" +#include "e-memo-shell-view.h" + +#include "e-task-shell-backend.h" +#include "e-task-shell-content.h" +#include "e-task-shell-sidebar.h" +#include "e-task-shell-view.h" + +/* Module Entry Points */ +void e_module_load (GTypeModule *type_module); +void e_module_unload (GTypeModule *type_module); + +G_MODULE_EXPORT void +e_module_load (GTypeModule *type_module) +{ + /* Register dynamically loaded types. */ + + e_cal_shell_backend_register_type (type_module); + e_cal_shell_content_register_type (type_module); + e_cal_shell_sidebar_register_type (type_module); + e_cal_shell_view_register_type (type_module); + + e_memo_shell_backend_register_type (type_module); + e_memo_shell_content_register_type (type_module); + e_memo_shell_sidebar_register_type (type_module); + e_memo_shell_view_register_type (type_module); + + e_task_shell_backend_register_type (type_module); + e_task_shell_content_register_type (type_module); + e_task_shell_sidebar_register_type (type_module); + e_task_shell_view_register_type (type_module); +} + +G_MODULE_EXPORT void +e_module_unload (GTypeModule *type_module) +{ +} diff --git a/modules/mail/Makefile.am b/modules/mail/Makefile.am new file mode 100644 index 0000000000..ab73a5d542 --- /dev/null +++ b/modules/mail/Makefile.am @@ -0,0 +1,56 @@ +INCLUDES = \ + -I$(top_srcdir) \ + -I$(top_srcdir)/mail \ + -I$(top_srcdir)/widgets \ + $(EVOLUTION_MAIL_CFLAGS) \ + -DEVOLUTION_ETSPECDIR=\""$(etspecdir)"\" \ + -DEVOLUTION_GLADEDIR=\""$(gladedir)"\" \ + -DEVOLUTION_PRIVDATADIR=\""$(privdatadir)"\" \ + -DG_LOG_DOMAIN=\"evolution-module-mail\" + +module_LTLIBRARIES = libevolution-module-mail.la + +libevolution_module_mail_la_SOURCES = \ + evolution-module-mail.c \ + e-attachment-handler-mail.c \ + e-attachment-handler-mail.h \ + e-mail-shell-backend.c \ + e-mail-shell-backend.h \ + e-mail-shell-content.c \ + e-mail-shell-content.h \ + e-mail-shell-migrate.c \ + e-mail-shell-migrate.h \ + e-mail-shell-settings.c \ + e-mail-shell-settings.h \ + e-mail-shell-sidebar.c \ + e-mail-shell-sidebar.h \ + e-mail-shell-view.c \ + e-mail-shell-view.h \ + e-mail-shell-view-actions.c \ + e-mail-shell-view-actions.h \ + e-mail-shell-view-private.c \ + e-mail-shell-view-private.h \ + em-account-editor.c \ + em-account-editor.h \ + em-account-prefs.c \ + em-account-prefs.h \ + em-composer-prefs.c \ + em-composer-prefs.h \ + em-mailer-prefs.c \ + em-mailer-prefs.h \ + em-network-prefs.c \ + em-network-prefs.h + +libevolution_module_mail_la_LIBADD = \ + $(top_builddir)/e-util/libeutil.la \ + $(top_builddir)/shell/libeshell.la \ + $(top_builddir)/composer/libcomposer.la \ + $(top_builddir)/widgets/table/libetable.la \ + $(top_builddir)/widgets/text/libetext.la \ + $(top_builddir)/widgets/misc/libemiscwidgets.la \ + $(top_builddir)/mail/importers/libevolution-mail-importers.la + +libevolution_module_mail_la_LDFLAGS = \ + -avoid-version -module $(NO_UNDEFINED) + +-include $(top_srcdir)/git.mk diff --git a/modules/mail/e-attachment-handler-mail.c b/modules/mail/e-attachment-handler-mail.c new file mode 100644 index 0000000000..c17c97d8ca --- /dev/null +++ b/modules/mail/e-attachment-handler-mail.c @@ -0,0 +1,524 @@ +/* + * e-attachment-handler-mail.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-attachment-handler-mail.h" + +#include +#include +#include + +#include "e-util/e-error.h" +#include "mail/em-composer-utils.h" +#include "mail/mail-tools.h" + +#define E_ATTACHMENT_HANDLER_MAIL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ATTACHMENT_HANDLER_MAIL, EAttachmentHandlerMailPrivate)) + +struct _EAttachmentHandlerMailPrivate { + gint placeholder; +}; + +static gpointer parent_class; + +static const gchar *ui = +"" +" " +" " +" " +" " +" " +" " +" " +""; + +/* Note: Do not use the info field. */ +static GtkTargetEntry target_table[] = { + { (gchar *) "message/rfc822", 0, 0 }, + { (gchar *) "x-uid-list", 0, 0 } +}; + +static void +attachment_handler_mail_forward (GtkAction *action, + EAttachmentView *view) +{ + EAttachment *attachment; + CamelMimePart *mime_part; + CamelDataWrapper *wrapper; + GList *selected; + + selected = e_attachment_view_get_selected_attachments (view); + g_return_if_fail (g_list_length (selected) == 1); + + attachment = E_ATTACHMENT (selected->data); + mime_part = e_attachment_get_mime_part (attachment); + wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); + + em_utils_forward_message (CAMEL_MIME_MESSAGE (wrapper), NULL); + + g_list_foreach (selected, (GFunc) g_object_unref, NULL); + g_list_free (selected); +} + +static void +attachment_handler_mail_reply_all (GtkAction *action, + EAttachmentView *view) +{ + EAttachment *attachment; + CamelMimePart *mime_part; + CamelDataWrapper *wrapper; + GList *selected; + + selected = e_attachment_view_get_selected_attachments (view); + g_return_if_fail (g_list_length (selected) == 1); + + attachment = E_ATTACHMENT (selected->data); + mime_part = e_attachment_get_mime_part (attachment); + wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); + + em_utils_reply_to_message ( + NULL, NULL, CAMEL_MIME_MESSAGE (wrapper), + REPLY_MODE_ALL, NULL); + + g_list_foreach (selected, (GFunc) g_object_unref, NULL); + g_list_free (selected); +} + +static void +attachment_handler_mail_reply_sender (GtkAction *action, + EAttachmentView *view) +{ + EAttachment *attachment; + CamelMimePart *mime_part; + CamelDataWrapper *wrapper; + GList *selected; + + selected = e_attachment_view_get_selected_attachments (view); + g_return_if_fail (g_list_length (selected) == 1); + + attachment = E_ATTACHMENT (selected->data); + mime_part = e_attachment_get_mime_part (attachment); + wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); + + em_utils_reply_to_message ( + NULL, NULL, CAMEL_MIME_MESSAGE (wrapper), + REPLY_MODE_SENDER, NULL); + + g_list_foreach (selected, (GFunc) g_object_unref, NULL); + g_list_free (selected); +} + +static GtkActionEntry standard_entries[] = { + + { "mail-forward", + "mail-forward", + N_("_Forward"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (attachment_handler_mail_forward) }, + + { "mail-reply-all", + "mail-reply-all", + N_("Reply to _All"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (attachment_handler_mail_reply_all) }, + + { "mail-reply-sender", + "mail-reply-sender", + N_("_Reply to Sender"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (attachment_handler_mail_reply_sender) } +}; + +static void +attachment_handler_mail_message_rfc822 (EAttachmentView *view, + GdkDragContext *drag_context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time) +{ + static GdkAtom atom = GDK_NONE; + EAttachmentStore *store; + EAttachment *attachment; + CamelMimeMessage *message; + CamelDataWrapper *wrapper; + CamelStream *stream; + const gchar *data; + gboolean success = FALSE; + gpointer parent; + gint length; + + if (G_UNLIKELY (atom == GDK_NONE)) + atom = gdk_atom_intern_static_string ("message/rfc822"); + + if (gtk_selection_data_get_target (selection_data) != atom) + return; + + g_signal_stop_emission_by_name (view, "drag-data-received"); + + data = (const gchar *) gtk_selection_data_get_data (selection_data); + length = gtk_selection_data_get_length (selection_data); + + stream = camel_stream_mem_new (); + camel_stream_write (stream, data, length); + camel_stream_reset (stream); + + message = camel_mime_message_new (); + wrapper = CAMEL_DATA_WRAPPER (message); + + if (camel_data_wrapper_construct_from_stream (wrapper, stream) == -1) + goto exit; + + store = e_attachment_view_get_store (view); + + parent = gtk_widget_get_toplevel (GTK_WIDGET (view)); + parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; + + attachment = e_attachment_new_for_message (message); + e_attachment_store_add_attachment (store, attachment); + e_attachment_load_async ( + attachment, (GAsyncReadyCallback) + e_attachment_load_handle_error, parent); + g_object_unref (attachment); + + success = TRUE; + +exit: + camel_object_unref (message); + camel_object_unref (stream); + + gtk_drag_finish (drag_context, success, FALSE, time); +} + +static void +attachment_handler_mail_x_uid_list (EAttachmentView *view, + GdkDragContext *drag_context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time) +{ + static GdkAtom atom = GDK_NONE; + CamelException ex = CAMEL_EXCEPTION_INITIALISER; + CamelDataWrapper *wrapper; + CamelMimeMessage *message; + CamelMultipart *multipart; + CamelMimePart *mime_part; + CamelFolder *folder = NULL; + EAttachment *attachment; + EAttachmentStore *store; + GPtrArray *uids; + const gchar *data; + const gchar *cp, *end; + gchar *description; + gpointer parent; + gint length; + guint ii; + + if (G_UNLIKELY (atom == GDK_NONE)) + atom = gdk_atom_intern_static_string ("x-uid-list"); + + if (gtk_selection_data_get_target (selection_data) != atom) + return; + + store = e_attachment_view_get_store (view); + + parent = gtk_widget_get_toplevel (GTK_WIDGET (view)); + parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; + + uids = g_ptr_array_new (); + + data = (const gchar *) gtk_selection_data_get_data (selection_data); + length = gtk_selection_data_get_length (selection_data); + + /* The UID list is delimited by NUL characters. + * Brilliant. So we can't use g_strsplit(). */ + + cp = data; + end = data + length; + + while (cp < end) { + const gchar *start = cp; + + while (cp < end && *cp != '\0') + cp++; + + /* Skip the first string. */ + if (start > data) + g_ptr_array_add (uids, g_strndup (start, cp - start)); + + cp++; + } + + if (uids->len == 0) + goto exit; + + /* The first string is the folder URI. */ + folder = mail_tool_uri_to_folder (data, 0, &ex); + if (folder == NULL) + goto exit; + + /* Handle one message. */ + if (uids->len == 1) { + message = camel_folder_get_message ( + folder, uids->pdata[0], &ex); + if (message == NULL) + goto exit; + + attachment = e_attachment_new_for_message (message); + e_attachment_store_add_attachment (store, attachment); + e_attachment_load_async ( + attachment, (GAsyncReadyCallback) + e_attachment_load_handle_error, parent); + g_object_unref (attachment); + + camel_object_unref (message); + goto exit; + } + + /* Build a multipart/digest message out of the UIDs. */ + + multipart = camel_multipart_new (); + wrapper = CAMEL_DATA_WRAPPER (multipart); + camel_data_wrapper_set_mime_type (wrapper, "multipart/digest"); + camel_multipart_set_boundary (multipart, NULL); + + for (ii = 0; ii < uids->len; ii++) { + message = camel_folder_get_message ( + folder, uids->pdata[ii], &ex); + if (message == NULL) { + camel_object_unref (multipart); + goto exit; + } + + mime_part = camel_mime_part_new (); + wrapper = CAMEL_DATA_WRAPPER (message); + camel_mime_part_set_disposition (mime_part, "inline"); + camel_medium_set_content_object ( + CAMEL_MEDIUM (mime_part), wrapper); + camel_mime_part_set_content_type (mime_part, "message/rfc822"); + camel_multipart_add_part (multipart, mime_part); + camel_object_unref (mime_part); + + camel_object_unref (message); + } + + mime_part = camel_mime_part_new (); + wrapper = CAMEL_DATA_WRAPPER (multipart); + camel_medium_set_content_object (CAMEL_MEDIUM (mime_part), wrapper); + + /* Translators: This is only for multiple messages. */ + description = g_strdup_printf (_("%d attached messages"), uids->len); + camel_mime_part_set_description (mime_part, description); + g_free (description); + + attachment = e_attachment_new (); + e_attachment_set_mime_part (attachment, mime_part); + e_attachment_store_add_attachment (store, attachment); + e_attachment_load_async ( + attachment, (GAsyncReadyCallback) + e_attachment_load_handle_error, parent); + g_object_unref (attachment); + + camel_object_unref (mime_part); + camel_object_unref (multipart); + +exit: + if (camel_exception_is_set (&ex)) { + gchar *folder_name; + + if (folder != NULL) + camel_object_get ( + folder, NULL, CAMEL_FOLDER_NAME, + &folder_name, NULL); + else + folder_name = g_strdup (data); + + e_error_run ( + parent, "mail-composer:attach-nomessages", + folder_name, camel_exception_get_description (&ex), + NULL); + + if (folder != NULL) + camel_object_free ( + folder, CAMEL_FOLDER_NAME, folder_name); + else + g_free (folder_name); + + camel_exception_clear (&ex); + } + + if (folder != NULL) + camel_object_unref (folder); + + g_ptr_array_free (uids, TRUE); + + g_signal_stop_emission_by_name (view, "drag-data-received"); +} + +static void +attachment_handler_mail_update_actions (EAttachmentView *view) +{ + EAttachment *attachment; + CamelMimePart *mime_part; + CamelDataWrapper *wrapper; + GtkActionGroup *action_group; + GList *selected; + gboolean visible = FALSE; + + selected = e_attachment_view_get_selected_attachments (view); + + if (g_list_length (selected) != 1) + goto exit; + + attachment = E_ATTACHMENT (selected->data); + mime_part = e_attachment_get_mime_part (attachment); + + if (!CAMEL_IS_MIME_PART (mime_part)) + goto exit; + + wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); + + visible = CAMEL_IS_MIME_MESSAGE (wrapper); + +exit: + action_group = e_attachment_view_get_action_group (view, "mail"); + gtk_action_group_set_visible (action_group, visible); + + g_list_foreach (selected, (GFunc) g_object_unref, NULL); + g_list_free (selected); +} + +static void +attachment_handler_mail_constructed (GObject *object) +{ + EAttachmentHandler *handler; + EAttachmentView *view; + GtkActionGroup *action_group; + GtkUIManager *ui_manager; + GError *error = NULL; + + handler = E_ATTACHMENT_HANDLER (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + view = e_attachment_handler_get_view (handler); + + action_group = e_attachment_view_add_action_group (view, "mail"); + gtk_action_group_add_actions ( + action_group, standard_entries, + G_N_ELEMENTS (standard_entries), view); + + ui_manager = e_attachment_view_get_ui_manager (view); + gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); + + if (error != NULL) { + g_warning ("%s", error->message); + g_error_free (error); + } + + g_signal_connect ( + view, "update-actions", + G_CALLBACK (attachment_handler_mail_update_actions), + NULL); + + g_signal_connect ( + view, "drag-data-received", + G_CALLBACK (attachment_handler_mail_message_rfc822), + NULL); + + g_signal_connect ( + view, "drag-data-received", + G_CALLBACK (attachment_handler_mail_x_uid_list), + NULL); +} + +static GdkDragAction +attachment_handler_mail_get_drag_actions (EAttachmentHandler *handler) +{ + return GDK_ACTION_COPY; +} + +static const GtkTargetEntry * +attachment_handler_mail_get_target_table (EAttachmentHandler *handler, + guint *n_targets) +{ + if (n_targets != NULL) + *n_targets = G_N_ELEMENTS (target_table); + + return target_table; +} + +static void +attachment_handler_mail_class_init (EAttachmentHandlerMailClass *class) +{ + GObjectClass *object_class; + EAttachmentHandlerClass *handler_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EAttachmentHandlerMailPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->constructed = attachment_handler_mail_constructed; + + handler_class = E_ATTACHMENT_HANDLER_CLASS (class); + handler_class->get_drag_actions = attachment_handler_mail_get_drag_actions; + handler_class->get_target_table = attachment_handler_mail_get_target_table; +} + +static void +attachment_handler_mail_init (EAttachmentHandlerMail *handler) +{ + handler->priv = E_ATTACHMENT_HANDLER_MAIL_GET_PRIVATE (handler); +} + +GType +e_attachment_handler_mail_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EAttachmentHandlerMailClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) attachment_handler_mail_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EAttachmentHandlerMail), + 0, /* n_preallocs */ + (GInstanceInitFunc) attachment_handler_mail_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + E_TYPE_ATTACHMENT_HANDLER, + "EAttachmentHandlerMail", &type_info, 0); + } + + return type; +} diff --git a/modules/mail/e-attachment-handler-mail.h b/modules/mail/e-attachment-handler-mail.h new file mode 100644 index 0000000000..c62ea99cab --- /dev/null +++ b/modules/mail/e-attachment-handler-mail.h @@ -0,0 +1,65 @@ +/* + * e-attachment-handler-mail.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_ATTACHMENT_HANDLER_MAIL_H +#define E_ATTACHMENT_HANDLER_MAIL_H + +#include + +/* Standard GObject macros */ +#define E_TYPE_ATTACHMENT_HANDLER_MAIL \ + (e_attachment_handler_mail_get_type ()) +#define E_ATTACHMENT_HANDLER_MAIL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_ATTACHMENT_HANDLER_MAIL, EAttachmentHandlerMail)) +#define E_ATTACHMENT_HANDLER_MAIL_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_ATTACHMENT_HANDLER_MAIL, EAttachmentHandlerMailClass)) +#define E_IS_ATTACHMENT_HANDLER_MAIL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_ATTACHMENT_HANDLER_MAIL)) +#define E_IS_ATTACHMENT_HANDLER_MAIL_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_ATTACHMENT_HANDLER_MAIL)) +#define E_ATTACHMENT_HANDLER_MAIL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_ATTACHMENT_HANDLER_MAIL, EAttachmentHandlerMailClass)) + +G_BEGIN_DECLS + +typedef struct _EAttachmentHandlerMail EAttachmentHandlerMail; +typedef struct _EAttachmentHandlerMailClass EAttachmentHandlerMailClass; +typedef struct _EAttachmentHandlerMailPrivate EAttachmentHandlerMailPrivate; + +struct _EAttachmentHandlerMail { + EAttachmentHandler parent; + EAttachmentHandlerMailPrivate *priv; +}; + +struct _EAttachmentHandlerMailClass { + EAttachmentHandlerClass parent_class; +}; + +GType e_attachment_handler_mail_get_type (void); + +G_END_DECLS + +#endif /* E_ATTACHMENT_HANDLER_MAIL_H */ diff --git a/modules/mail/e-mail-shell-backend.c b/modules/mail/e-mail-shell-backend.c new file mode 100644 index 0000000000..3dcb7b1391 --- /dev/null +++ b/modules/mail/e-mail-shell-backend.c @@ -0,0 +1,787 @@ +/* + * e-mail-shell-backend.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-shell-backend.h" + +#include +#include +#include +#include +#include + +#include "e-util/e-account-utils.h" +#include "e-util/e-binding.h" +#include "e-util/e-import.h" +#include "e-util/e-util.h" +#include "shell/e-shell.h" +#include "shell/e-shell-window.h" +#include "composer/e-msg-composer.h" +#include "widgets/misc/e-preferences-window.h" + +#include "e-mail-shell-migrate.h" +#include "e-mail-shell-settings.h" +#include "e-mail-shell-sidebar.h" +#include "e-mail-shell-view.h" + +#include "e-attachment-handler-mail.h" +#include "e-mail-browser.h" +#include "e-mail-reader.h" +#include "e-mail-store.h" +#include "em-account-editor.h" +#include "em-account-prefs.h" +#include "em-composer-prefs.h" +#include "em-composer-utils.h" +#include "em-config.h" +#include "em-event.h" +#include "em-folder-utils.h" +#include "em-format-hook.h" +#include "em-format-html-display.h" +#include "em-junk-hook.h" +#include "em-mailer-prefs.h" +#include "em-network-prefs.h" +#include "em-utils.h" +#include "mail-config.h" +#include "mail-ops.h" +#include "mail-send-recv.h" +#include "mail-session.h" +#include "mail-vfolder.h" +#include "importers/mail-importer.h" + +#define E_MAIL_SHELL_BACKEND_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_SHELL_BACKEND, EMailShellBackendPrivate)) + +#define BACKEND_NAME "mail" + +struct _EMailShellBackendPrivate { + gint mail_sync_in_progress; + guint mail_sync_timeout_source_id; +}; + +static gpointer parent_class; +static GType mail_shell_backend_type; + +/* XXX So many things need the shell backend that it's + * just easier for now to make it globally available. + * We should fix this, though. */ +EMailShellBackend *global_mail_shell_backend = NULL; + +extern gint camel_application_is_exiting; + +static gboolean +mail_shell_backend_run_account_druid (GtkWindow *parent) +{ + EAccountList *account_list; + EMAccountEditor *account_editor; + + account_editor = em_account_editor_new ( + NULL, EMAE_DRUID, + "org.gnome.evolution.mail.config.accountDruid"); + if (GTK_IS_WINDOW (parent)) + gtk_window_set_transient_for ( + GTK_WINDOW (account_editor->editor), parent); + g_object_weak_ref ( + G_OBJECT (account_editor->editor), + (GWeakNotify) gtk_main_quit, NULL); + gtk_widget_show (account_editor->editor); + gtk_grab_add (account_editor->editor); + gtk_main (); + + account_list = e_get_account_list (); + + return (e_list_length ((EList *) account_list) > 0); +} + +static void +mail_shell_backend_init_hooks (void) +{ + e_plugin_hook_register_type (em_config_hook_get_type ()); + e_plugin_hook_register_type (em_event_hook_get_type ()); + e_plugin_hook_register_type (em_junk_hook_get_type ()); + + /* EMFormat classes must be registered before EMFormatHook. */ + em_format_hook_register_type (em_format_get_type ()); + em_format_hook_register_type (em_format_html_get_type ()); + em_format_hook_register_type (em_format_html_display_get_type ()); + e_plugin_hook_register_type (em_format_hook_get_type ()); + + em_junk_hook_register_type (emj_get_type ()); +} + +static void +mail_shell_backend_init_importers (void) +{ + EImportClass *import_class; + EImportImporter *importer; + + import_class = g_type_class_ref (e_import_get_type ()); + + importer = mbox_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); + + importer = elm_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); + + importer = pine_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); +} + +static void +mail_shell_backend_mail_icon_cb (EShellWindow *shell_window, + const gchar *icon_name) +{ + GtkAction *action; + + action = e_shell_window_get_shell_view_action ( + shell_window, BACKEND_NAME); + g_object_set (action, "icon-name", icon_name, NULL); +} + +static void +action_mail_folder_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + EMFolderTree *folder_tree = NULL; + EMailShellSidebar *mail_shell_sidebar; + EShellSidebar *shell_sidebar; + EShellView *shell_view; + const gchar *view_name; + + /* Take care not to unnecessarily load the mail shell view. */ + view_name = e_shell_window_get_active_view (shell_window); + if (g_strcmp0 (view_name, BACKEND_NAME) != 0) + goto exit; + + shell_view = e_shell_window_get_shell_view (shell_window, view_name); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + + mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar); + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + +exit: + em_folder_utils_create_folder ( + NULL, folder_tree, GTK_WINDOW (shell_window)); +} + +static void +action_mail_message_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + EMailShellSidebar *mail_shell_sidebar; + EShellSidebar *shell_sidebar; + EShellView *shell_view; + EMFolderTree *folder_tree; + const gchar *view_name; + gchar *uri = NULL; + + if (!em_utils_check_user_can_send_mail ()) + return; + + /* Take care not to unnecessarily load the mail shell view. */ + view_name = e_shell_window_get_active_view (shell_window); + if (g_strcmp0 (view_name, BACKEND_NAME) != 0) + goto exit; + + shell_view = e_shell_window_get_shell_view (shell_window, view_name); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + + mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar); + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + uri = em_folder_tree_get_selected_uri (folder_tree); + +exit: + em_utils_compose_new_message (uri); + + g_free (uri); +} + +static GtkActionEntry item_entries[] = { + + { "mail-message-new", + "mail-message-new", + NC_("New", "_Mail Message"), + "m", + N_("Compose a new mail message"), + G_CALLBACK (action_mail_message_new_cb) } +}; + +static GtkActionEntry source_entries[] = { + + { "mail-folder-new", + "folder-new", + NC_("New", "Mail _Folder"), + NULL, + N_("Create a new mail folder"), + G_CALLBACK (action_mail_folder_new_cb) } +}; + +static void +mail_shell_backend_init_preferences (EShell *shell) +{ + EAccountList *account_list; + GtkWidget *preferences_window; + + account_list = e_get_account_list (); + preferences_window = e_shell_get_preferences_window (shell); + + e_preferences_window_add_page ( + E_PREFERENCES_WINDOW (preferences_window), + "mail-accounts", + "preferences-mail-accounts", + _("Mail Accounts"), + em_account_prefs_new (account_list), + 100); + + e_preferences_window_add_page ( + E_PREFERENCES_WINDOW (preferences_window), + "mail", + "preferences-mail", + _("Mail Preferences"), + em_mailer_prefs_new (shell), + 300); + + e_preferences_window_add_page ( + E_PREFERENCES_WINDOW (preferences_window), + "composer", + "preferences-composer", + _("Composer Preferences"), + em_composer_prefs_new (shell), + 400); + + e_preferences_window_add_page ( + E_PREFERENCES_WINDOW (preferences_window), + "system-network-proxy", + "preferences-system-network-proxy", + _("Network Preferences"), + em_network_prefs_new (), + 500); +} + +static void +mail_shell_backend_sync_store_done_cb (CamelStore *store, + gpointer user_data) +{ + EMailShellBackend *mail_shell_backend = user_data; + + mail_shell_backend->priv->mail_sync_in_progress--; +} + +static void +mail_shell_backend_sync_store_cb (CamelStore *store, + EMailShellBackend *mail_shell_backend) +{ + if (!camel_application_is_exiting) { + mail_shell_backend->priv->mail_sync_in_progress++; + mail_sync_store ( + store, FALSE, + mail_shell_backend_sync_store_done_cb, + mail_shell_backend); + } +} + +static gboolean +mail_shell_backend_mail_sync (EMailShellBackend *mail_shell_backend) +{ + if (camel_application_is_exiting) + return FALSE; + + if (mail_shell_backend->priv->mail_sync_in_progress) + goto exit; + + if (session == NULL || !camel_session_is_online (session)) + goto exit; + + e_mail_store_foreach ( + (GHFunc) mail_shell_backend_sync_store_cb, + mail_shell_backend); + +exit: + return !camel_application_is_exiting; +} + +static void +mail_shell_backend_notify_online_cb (EShell *shell, + GParamSpec *pspec, + EShellBackend *shell_backend) +{ + gboolean online; + + online = e_shell_get_online (shell); + camel_session_set_online (session, online); +} + +static void +mail_shell_backend_handle_email_uri_cb (gchar *folder_uri, + CamelFolder *folder, + gpointer user_data) +{ + EShellBackend *shell_backend = user_data; + CamelURL *url = user_data; + const gchar *forward; + const gchar *reply; + const gchar *uid; + + if (folder == NULL) { + g_warning ("Could not open folder '%s'", folder_uri); + goto exit; + } + + forward = camel_url_get_param (url, "forward"); + reply = camel_url_get_param (url, "reply"); + uid = camel_url_get_param (url, "uid"); + + if (reply != NULL) { + gint mode; + + if (g_strcmp0 (reply, "all") == 0) + mode = REPLY_MODE_ALL; + else if (g_strcmp0 (reply, "list") == 0) + mode = REPLY_MODE_LIST; + else + mode = REPLY_MODE_SENDER; + + em_utils_reply_to_message (folder, uid, NULL, mode, NULL); + + } else if (forward != NULL) { + GPtrArray *uids; + + uids = g_ptr_array_new (); + g_ptr_array_add (uids, g_strdup (uid)); + + if (g_strcmp0 (forward, "attached") == 0) + em_utils_forward_attached (folder, uids, folder_uri); + else if (g_strcmp0 (forward, "inline") == 0) + em_utils_forward_inline (folder, uids, folder_uri); + else if (g_strcmp0 (forward, "quoted") == 0) + em_utils_forward_quoted (folder, uids, folder_uri); + else + em_utils_forward_messages (folder, uids, folder_uri); + + } else { + GtkWidget *browser; + + /* FIXME Should pass in the shell module. */ + browser = e_mail_browser_new (shell_backend); + e_mail_reader_set_folder ( + E_MAIL_READER (browser), folder, folder_uri); + e_mail_reader_set_message ( + E_MAIL_READER (browser), uid, FALSE); + gtk_widget_show (browser); + } + +exit: + camel_url_free (url); +} + +static gboolean +mail_shell_backend_handle_uri_cb (EShell *shell, + const gchar *uri, + EMailShellBackend *mail_shell_backend) +{ + gboolean handled = TRUE; + + if (g_str_has_prefix (uri, "mailto:")) { + if (em_utils_check_user_can_send_mail ()) + em_utils_compose_new_message_with_mailto (uri, NULL); + + } else if (g_str_has_prefix (uri, "email:")) { + CamelURL *url; + + url = camel_url_new (uri, NULL); + if (camel_url_get_param (url, "uid") != NULL) { + gchar *curi = em_uri_to_camel (uri); + + mail_get_folder ( + curi, 0, + mail_shell_backend_handle_email_uri_cb, + mail_shell_backend, mail_msg_unordered_push); + g_free (curi); + + } else { + g_warning ("Email URI's must include a uid parameter"); + camel_url_free (url); + } + } else + handled = FALSE; + + return TRUE; +} + +/* Helper for mail_shell_backend_prepare_for_[off|on]line_cb() */ +static void +mail_shell_store_line_transition_done_cb (CamelStore *store, + gpointer user_data) +{ + EActivity *activity = user_data; + + g_object_unref (activity); +} + +/* Helper for mail_shell_backend_prepare_for_offline_cb() */ +static void +mail_shell_store_prepare_for_offline_cb (CamelService *service, + gpointer unused, + EActivity *activity) +{ + if (CAMEL_IS_DISCO_STORE (service) || CAMEL_IS_OFFLINE_STORE (service)) + mail_store_set_offline ( + CAMEL_STORE (service), TRUE, + mail_shell_store_line_transition_done_cb, + g_object_ref (activity)); +} + +static void +mail_shell_backend_prepare_for_offline_cb (EShell *shell, + EActivity *activity, + EMailShellBackend *mail_shell_backend) +{ + GList *watched_windows; + GtkWidget *parent = NULL; + gboolean synchronize = FALSE; + + watched_windows = e_shell_get_watched_windows (shell); + if (watched_windows != NULL) + parent = GTK_WIDGET (watched_windows->data); + + if (e_shell_get_network_available (shell)) + synchronize = em_utils_prompt_user ( + GTK_WINDOW (parent), + "/apps/evolution/mail/prompts/quick_offline", + "mail:ask-quick-offline", NULL); + + if (!synchronize) { + mail_cancel_all (); + camel_session_set_network_state (session, FALSE); + } + + e_mail_store_foreach ( + (GHFunc) mail_shell_store_prepare_for_offline_cb, activity); +} + +/* Helper for mail_shell_backend_prepare_for_online_cb() */ +static void +mail_shell_store_prepare_for_online_cb (CamelService *service, + gpointer unused, + EActivity *activity) +{ + if (CAMEL_IS_DISCO_STORE (service) || CAMEL_IS_OFFLINE_STORE (service)) + mail_store_set_offline ( + CAMEL_STORE (service), FALSE, + mail_shell_store_line_transition_done_cb, + g_object_ref (activity)); +} + +static void +mail_shell_backend_prepare_for_online_cb (EShell *shell, + EActivity *activity, + EMailShellBackend *mail_shell_backend) +{ + camel_session_set_online (session, TRUE); + + e_mail_store_foreach ( + (GHFunc) mail_shell_store_prepare_for_online_cb, activity); +} + +static void +mail_shell_backend_send_receive_cb (EShell *shell, + GtkWindow *parent, + EShellBackend *shell_backend) +{ + em_utils_clear_get_password_canceled_accounts_flag (); + mail_send_receive (parent); +} + +static void +mail_shell_backend_window_weak_notify_cb (EShell *shell, + GObject *where_the_object_was) +{ + g_signal_handlers_disconnect_by_func ( + shell, mail_shell_backend_mail_icon_cb, + where_the_object_was); +} + +static void +mail_shell_backend_window_created_cb (EShell *shell, + GtkWindow *window, + EShellBackend *shell_backend) +{ + EShellSettings *shell_settings; + static gboolean first_time = TRUE; + const gchar *backend_name; + + shell_settings = e_shell_get_shell_settings (shell); + + /* This applies to both the composer and signature editor. */ + if (GTKHTML_IS_EDITOR (window)) { + GList *spell_languages; + + e_binding_new ( + G_OBJECT (shell_settings), "composer-inline-spelling", + G_OBJECT (window), "inline-spelling"); + + e_binding_new ( + G_OBJECT (shell_settings), "composer-magic-links", + G_OBJECT (window), "magic-links"); + + e_binding_new ( + G_OBJECT (shell_settings), "composer-magic-smileys", + G_OBJECT (window), "magic-smileys"); + + spell_languages = e_load_spell_languages (); + gtkhtml_editor_set_spell_languages ( + GTKHTML_EDITOR (window), spell_languages); + g_list_free (spell_languages); + } + + if (E_IS_MSG_COMPOSER (window)) { + /* Integrate the new composer into the mail module. */ + em_configure_new_composer (E_MSG_COMPOSER (window)); + return; + } + + if (!E_IS_SHELL_WINDOW (window)) + return; + + backend_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name; + + e_shell_window_register_new_item_actions ( + E_SHELL_WINDOW (window), backend_name, + item_entries, G_N_ELEMENTS (item_entries)); + + e_shell_window_register_new_source_actions ( + E_SHELL_WINDOW (window), backend_name, + source_entries, G_N_ELEMENTS (source_entries)); + + g_signal_connect_swapped ( + shell, "event::mail-icon", + G_CALLBACK (mail_shell_backend_mail_icon_cb), window); + + g_object_weak_ref ( + G_OBJECT (window), (GWeakNotify) + mail_shell_backend_window_weak_notify_cb, shell); + + if (first_time) { + g_signal_connect ( + window, "map-event", + G_CALLBACK (e_msg_composer_check_autosave), NULL); + first_time = FALSE; + } +} + +static void +mail_shell_backend_constructed (GObject *object) +{ + EMailShellBackendPrivate *priv; + EShell *shell; + EShellBackend *shell_backend; + const gchar *data_dir; + + priv = E_MAIL_SHELL_BACKEND_GET_PRIVATE (object); + + shell_backend = E_SHELL_BACKEND (object); + shell = e_shell_backend_get_shell (shell_backend); + + /* This also initializes Camel, so it needs to happen early. */ + mail_session_init (shell_backend); + + mail_shell_backend_init_hooks (); + mail_shell_backend_init_importers (); + + e_attachment_handler_mail_get_type (); + + /* XXX This never gets unreffed. */ + global_mail_shell_backend = g_object_ref (shell_backend); + + g_signal_connect ( + shell, "notify::online", + G_CALLBACK (mail_shell_backend_notify_online_cb), + shell_backend); + + g_signal_connect ( + shell, "handle-uri", + G_CALLBACK (mail_shell_backend_handle_uri_cb), + shell_backend); + + g_signal_connect ( + shell, "prepare-for-offline", + G_CALLBACK (mail_shell_backend_prepare_for_offline_cb), + shell_backend); + + g_signal_connect ( + shell, "prepare-for-online", + G_CALLBACK (mail_shell_backend_prepare_for_online_cb), + shell_backend); + + g_signal_connect ( + shell, "send-receive", + G_CALLBACK (mail_shell_backend_send_receive_cb), + shell_backend); + + g_signal_connect ( + shell, "window-created", + G_CALLBACK (mail_shell_backend_window_created_cb), + shell_backend); + + mail_config_init (); + mail_msg_init (); + + data_dir = e_shell_backend_get_data_dir (shell_backend); + e_mail_store_init (data_dir); + + /* Initialize settings before initializing preferences, + * since the preferences bind to the shell settings. */ + e_mail_shell_settings_init (shell); + mail_shell_backend_init_preferences (shell); +} + +static void +mail_shell_backend_start (EShellBackend *shell_backend) +{ + EMailShellBackendPrivate *priv; + EShell *shell; + EShellSettings *shell_settings; + gboolean enable_search_folders; + + priv = E_MAIL_SHELL_BACKEND_GET_PRIVATE (shell_backend); + + shell = e_shell_backend_get_shell (shell_backend); + shell_settings = e_shell_get_shell_settings (shell); + + /* XXX Do we really still need this flag? */ + mail_session_set_interactive (TRUE); + + enable_search_folders = e_shell_settings_get_boolean ( + shell_settings, "mail-enable-search-folders"); + if (enable_search_folders) + vfolder_load_storage (); + + mail_autoreceive_init (shell_backend, session); + + if (g_getenv ("CAMEL_FLUSH_CHANGES") != NULL) + priv->mail_sync_timeout_source_id = g_timeout_add_seconds ( + mail_config_get_sync_timeout (), + (GSourceFunc) mail_shell_backend_mail_sync, + shell_backend); +} + +static void +mail_shell_backend_class_init (EMailShellBackendClass *class) +{ + GObjectClass *object_class; + EShellBackendClass *shell_backend_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMailShellBackendPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->constructed = mail_shell_backend_constructed; + + shell_backend_class = E_SHELL_BACKEND_CLASS (class); + shell_backend_class->shell_view_type = E_TYPE_MAIL_SHELL_VIEW; + shell_backend_class->name = BACKEND_NAME; + shell_backend_class->aliases = ""; + shell_backend_class->schemes = "mailto:email"; + shell_backend_class->sort_order = 200; + shell_backend_class->start = mail_shell_backend_start; + shell_backend_class->is_busy = NULL; + shell_backend_class->shutdown = NULL; + shell_backend_class->migrate = e_mail_shell_migrate; +} + +static void +mail_shell_backend_init (EMailShellBackend *mail_shell_backend) +{ + mail_shell_backend->priv = + E_MAIL_SHELL_BACKEND_GET_PRIVATE (mail_shell_backend); +} + +GType +e_mail_shell_backend_get_type (void) +{ + return mail_shell_backend_type; +} + +void +e_mail_shell_backend_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (EMailShellBackendClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) mail_shell_backend_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMailShellBackend), + 0, /* n_preallocs */ + (GInstanceInitFunc) mail_shell_backend_init, + NULL /* value_table */ + }; + + mail_shell_backend_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_BACKEND, + "EMailShellBackend", &type_info, 0); +} + +/******************* Code below here belongs elsewhere. *******************/ + +#include "filter/filter-option.h" +#include "shell/e-shell-settings.h" +#include "mail/e-mail-label-list-store.h" + +GSList * +e_mail_labels_get_filter_options (void) +{ + EShell *shell; + EShellSettings *shell_settings; + EMailLabelListStore *list_store; + GtkTreeModel *model; + GtkTreeIter iter; + GSList *list = NULL; + gboolean valid; + + shell = e_shell_get_default (); + shell_settings = e_shell_get_shell_settings (shell); + list_store = e_shell_settings_get_object ( + shell_settings, "mail-label-list-store"); + + model = GTK_TREE_MODEL (list_store); + valid = gtk_tree_model_get_iter_first (model, &iter); + + while (valid) { + struct _filter_option *option; + gchar *name, *tag; + + name = e_mail_label_list_store_get_name (list_store, &iter); + tag = e_mail_label_list_store_get_tag (list_store, &iter); + + option = g_new0 (struct _filter_option, 1); + option->title = e_str_without_underscores (name); + option->value = tag; /* takes ownership */ + + g_free (name); + + valid = gtk_tree_model_iter_next (model, &iter); + } + + g_object_unref (list_store); + + return list; +} diff --git a/modules/mail/e-mail-shell-backend.h b/modules/mail/e-mail-shell-backend.h new file mode 100644 index 0000000000..4bc1a36706 --- /dev/null +++ b/modules/mail/e-mail-shell-backend.h @@ -0,0 +1,82 @@ +/* + * e-mail-shell-backend.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_SHELL_BACKEND_H +#define E_MAIL_SHELL_BACKEND_H + +#include + +#include +#include +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_MAIL_SHELL_BACKEND \ + (e_mail_shell_backend_get_type ()) +#define E_MAIL_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_SHELL_BACKEND, EMailShellBackend)) +#define E_MAIL_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_SHELL_BACKEND, EMailShellBackendClass)) +#define E_IS_MAIL_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_SHELL_BACKEND)) +#define E_IS_MAIL_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_SHELL_BACKEND)) +#define E_MAIL_SHELL_BACKEND_GET_CLASS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_SHELL_BACKEND, EMailShellBackendClass)) + +G_BEGIN_DECLS + +typedef struct _EMailShellBackend EMailShellBackend; +typedef struct _EMailShellBackendClass EMailShellBackendClass; +typedef struct _EMailShellBackendPrivate EMailShellBackendPrivate; + +struct _EMailShellBackend { + EShellBackend parent; + EMailShellBackendPrivate *priv; +}; + +struct _EMailShellBackendClass { + EShellBackendClass parent_class; +}; + +/* Globally available shell backend. + * + * XXX I don't like having this globally available but passing it around + * to all the various utilities that need to access the backend's data + * directory is too much of a pain for now. */ +extern EMailShellBackend *global_mail_shell_backend; + +GType e_mail_shell_backend_get_type (void); +void e_mail_shell_backend_register_type + (GTypeModule *type_module); + +/* XXX Find a better place for this function. */ +GSList * e_mail_labels_get_filter_options(void); + +G_END_DECLS + +#endif /* E_MAIL_SHELL_BACKEND_H */ diff --git a/modules/mail/e-mail-shell-content.c b/modules/mail/e-mail-shell-content.c new file mode 100644 index 0000000000..b801093116 --- /dev/null +++ b/modules/mail/e-mail-shell-content.c @@ -0,0 +1,1053 @@ +/* + * e-mail-shell-content.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-shell-content.h" + +#include +#include +#include + +#include "e-util/gconf-bridge.h" +#include "widgets/menus/gal-view-etable.h" +#include "widgets/menus/gal-view-instance.h" + +#include "em-search-context.h" +#include "em-utils.h" +#include "mail-config.h" +#include "mail-ops.h" + +#include "e-mail-reader.h" +#include "e-mail-search-bar.h" +#include "e-mail-shell-backend.h" +#include "e-mail-shell-view-actions.h" + +#define E_MAIL_SHELL_CONTENT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_SHELL_CONTENT, EMailShellContentPrivate)) + +#define STATE_KEY_SCROLLBAR_POSITION "ScrollbarPosition" +#define STATE_KEY_SELECTED_MESSAGE "SelectedMessage" + +struct _EMailShellContentPrivate { + GtkWidget *paned; + GtkWidget *message_list; + GtkWidget *search_bar; + + EMFormatHTMLDisplay *html_display; + GalViewInstance *view_instance; + + /* ETable scrolling hack */ + gdouble default_scrollbar_position; + + guint paned_binding_id; + guint scroll_timeout_id; + + /* Signal handler IDs */ + guint message_list_built_id; + guint message_list_scrolled_id; + + guint preview_visible : 1; + guint suppress_message_selection : 1; + guint vertical_view : 1; + guint show_deleted : 1; +}; + +enum { + PROP_0, + PROP_PREVIEW_VISIBLE, + PROP_SHOW_DELETED, + PROP_VERTICAL_VIEW +}; + +static gpointer parent_class; +static GType mail_shell_content_type; + +static void +mail_shell_content_etree_unfreeze (MessageList *message_list, + GdkEvent *event) +{ + ETableItem *item; + GObject *object; + + item = e_tree_get_item (message_list->tree); + object = G_OBJECT (((GnomeCanvasItem *) item)->canvas); + + g_object_set_data (object, "freeze-cursor", 0); +} + +static void +mail_shell_content_message_list_scrolled_cb (EMailShellContent *mail_shell_content, + MessageList *message_list) +{ + EShellContent *shell_content; + EShellView *shell_view; + GKeyFile *key_file; + const gchar *folder_uri; + const gchar *key; + gchar *group_name; + gdouble position; + + /* Save the scrollbar position for the current folder. */ + + folder_uri = message_list->folder_uri; + + if (folder_uri == NULL) + return; + + shell_content = E_SHELL_CONTENT (mail_shell_content); + shell_view = e_shell_content_get_shell_view (shell_content); + key_file = e_shell_view_get_state_key_file (shell_view); + + key = STATE_KEY_SCROLLBAR_POSITION; + group_name = g_strdup_printf ("Folder %s", folder_uri); + position = message_list_get_scrollbar_position (message_list); + + g_key_file_set_double (key_file, group_name, key, position); + e_shell_view_set_state_dirty (shell_view); + + g_free (group_name); +} + +static gboolean +mail_shell_content_scroll_timeout_cb (EMailShellContent *mail_shell_content) +{ + EMailShellContentPrivate *priv = mail_shell_content->priv; + EShellContent *shell_content; + EShellView *shell_view; + MessageList *message_list; + EMailReader *reader; + GKeyFile *key_file; + const gchar *folder_uri; + const gchar *key; + gchar *group_name; + + /* Initialize the scrollbar position for the current folder + * and setup a callback to handle scrollbar position changes. */ + + shell_content = E_SHELL_CONTENT (mail_shell_content); + shell_view = e_shell_content_get_shell_view (shell_content); + key_file = e_shell_view_get_state_key_file (shell_view); + + reader = E_MAIL_READER (mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + folder_uri = message_list->folder_uri; + + if (folder_uri == NULL) + goto skip; + + /* Restore the message list scrollbar position. */ + + key = STATE_KEY_SCROLLBAR_POSITION; + group_name = g_strdup_printf ("Folder %s", folder_uri); + + if (g_key_file_has_key (key_file, group_name, key, NULL)) { + gdouble position; + + position = g_key_file_get_double ( + key_file, group_name, key, NULL); + message_list_set_scrollbar_position (message_list, position); + } + + g_free (group_name); + +skip: + priv->message_list_scrolled_id = g_signal_connect_swapped ( + message_list, "message-list-scrolled", + G_CALLBACK (mail_shell_content_message_list_scrolled_cb), + mail_shell_content); + + priv->scroll_timeout_id = 0; + + return FALSE; +} + +static void +mail_shell_content_message_list_built_cb (EMailShellContent *mail_shell_content, + MessageList *message_list) +{ + EMailShellContentPrivate *priv = mail_shell_content->priv; + EShellContent *shell_content; + EShellView *shell_view; + GtkScrolledWindow *scrolled_window; + GtkWidget *vscrollbar; + GKeyFile *key_file; + gchar *uid; + + g_signal_handler_disconnect ( + message_list, priv->message_list_built_id); + priv->message_list_built_id = 0; + + shell_content = E_SHELL_CONTENT (mail_shell_content); + shell_view = e_shell_content_get_shell_view (shell_content); + key_file = e_shell_view_get_state_key_file (shell_view); + + if (message_list->cursor_uid != NULL) + uid = NULL; + + else if (message_list->folder_uri == NULL) + uid = NULL; + + else if (mail_shell_content->priv->suppress_message_selection) + uid = NULL; + + else { + const gchar *folder_uri; + const gchar *key; + gchar *group_name; + + key = STATE_KEY_SELECTED_MESSAGE; + folder_uri = message_list->folder_uri; + group_name = g_strdup_printf ("Folder %s", folder_uri); + uid = g_key_file_get_string (key_file, group_name, key, NULL); + g_free (group_name); + } + + if (uid != NULL) { + CamelFolder *folder; + CamelMessageInfo *info; + + folder = message_list->folder; + info = camel_folder_get_message_info (folder, uid); + if (info != NULL) { + EMailReader *reader; + + reader = E_MAIL_READER (mail_shell_content); + e_mail_reader_set_message (reader, uid, TRUE); + camel_folder_free_message_info (folder, info); + } + + g_free (uid); + } + + /* FIXME This is a gross workaround for an ETable bug that I can't + * fix (Ximian bug #55303). + * + * Since e_canvas_item_region_show_relay() uses a timeout, + * we have to use a timeout of the same interval but a lower + * priority. */ + priv->scroll_timeout_id = g_timeout_add_full ( + G_PRIORITY_LOW, 250, (GSourceFunc) + mail_shell_content_scroll_timeout_cb, + mail_shell_content, NULL); + + /* FIXME This is another ugly hack to hide a side-effect of the + * previous workaround. */ + scrolled_window = GTK_SCROLLED_WINDOW (message_list); + vscrollbar = gtk_scrolled_window_get_vscrollbar (scrolled_window); + g_signal_connect_swapped ( + vscrollbar, "button-press-event", + G_CALLBACK (mail_shell_content_etree_unfreeze), + message_list); +} + +static void +mail_shell_content_display_view_cb (EMailShellContent *mail_shell_content, + GalView *gal_view) +{ + EMailReader *reader; + MessageList *message_list; + + reader = E_MAIL_READER (mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + if (GAL_IS_VIEW_ETABLE (gal_view)) + gal_view_etable_attach_tree ( + GAL_VIEW_ETABLE (gal_view), message_list->tree); +} + +static void +mail_shell_content_message_selected_cb (EMailShellContent *mail_shell_content, + const gchar *message_uid, + MessageList *message_list) +{ + EShellContent *shell_content; + EShellView *shell_view; + GKeyFile *key_file; + const gchar *folder_uri; + const gchar *key; + gchar *group_name; + + folder_uri = message_list->folder_uri; + + /* This also gets triggered when selecting a store name on + * the sidebar such as "On This Computer", in which case + * 'folder_uri' will be NULL. */ + if (folder_uri == NULL) + return; + + shell_content = E_SHELL_CONTENT (mail_shell_content); + shell_view = e_shell_content_get_shell_view (shell_content); + key_file = e_shell_view_get_state_key_file (shell_view); + + key = STATE_KEY_SELECTED_MESSAGE; + group_name = g_strdup_printf ("Folder %s", folder_uri); + + if (message_uid != NULL) + g_key_file_set_string (key_file, group_name, key, message_uid); + else + g_key_file_remove_key (key_file, group_name, key, NULL); + e_shell_view_set_state_dirty (shell_view); + + g_free (group_name); +} + +static void +mail_shell_content_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_PREVIEW_VISIBLE: + e_mail_shell_content_set_preview_visible ( + E_MAIL_SHELL_CONTENT (object), + g_value_get_boolean (value)); + return; + + case PROP_SHOW_DELETED: + e_mail_shell_content_set_show_deleted ( + E_MAIL_SHELL_CONTENT (object), + g_value_get_boolean (value)); + return; + + case PROP_VERTICAL_VIEW: + e_mail_shell_content_set_vertical_view ( + E_MAIL_SHELL_CONTENT (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_shell_content_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_PREVIEW_VISIBLE: + g_value_set_boolean ( + value, + e_mail_shell_content_get_preview_visible ( + E_MAIL_SHELL_CONTENT (object))); + return; + + case PROP_SHOW_DELETED: + g_value_set_boolean ( + value, + e_mail_shell_content_get_show_deleted ( + E_MAIL_SHELL_CONTENT (object))); + return; + + case PROP_VERTICAL_VIEW: + g_value_set_boolean ( + value, + e_mail_shell_content_get_vertical_view ( + E_MAIL_SHELL_CONTENT (object))); + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_shell_content_dispose (GObject *object) +{ + EMailShellContentPrivate *priv; + + priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (object); + + if (priv->paned != NULL) { + g_object_unref (priv->paned); + priv->paned = NULL; + } + + if (priv->message_list != NULL) { + g_object_unref (priv->message_list); + priv->message_list = NULL; + } + + if (priv->search_bar != NULL) { + g_object_unref (priv->search_bar); + priv->search_bar = NULL; + } + + if (priv->html_display != NULL) { + g_object_unref (priv->html_display); + priv->html_display = NULL; + } + + if (priv->view_instance != NULL) { + g_object_unref (priv->view_instance); + priv->view_instance = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +mail_shell_content_constructed (GObject *object) +{ + EMailShellContentPrivate *priv; + EShellContent *shell_content; + EShellBackend *shell_backend; + EShellView *shell_view; + EShellViewClass *shell_view_class; + EMailReader *reader; + MessageList *message_list; + GConfBridge *bridge; + GtkWidget *container; + GtkWidget *widget; + GtkHTML *html; + GalViewCollection *view_collection; + const gchar *key; + + priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (object); + priv->html_display = em_format_html_display_new (); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_content = E_SHELL_CONTENT (object); + shell_view = e_shell_content_get_shell_view (shell_content); + shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + view_collection = shell_view_class->view_collection; + + html = EM_FORMAT_HTML (priv->html_display)->html; + + /* Build content widgets. */ + + container = GTK_WIDGET (object); + + widget = gtk_vpaned_new (); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->paned = g_object_ref (widget); + gtk_widget_show (widget); + + container = widget; + + widget = message_list_new (shell_backend); + gtk_paned_add1 (GTK_PANED (container), widget); + priv->message_list = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_vbox_new (FALSE, 1); + gtk_paned_add2 (GTK_PANED (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_container_add (GTK_CONTAINER (widget), GTK_WIDGET (html)); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + gtk_widget_show (GTK_WIDGET (html)); + gtk_widget_show (widget); + + widget = e_mail_search_bar_new (html); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + priv->search_bar = g_object_ref (widget); + gtk_widget_hide (widget); + + g_signal_connect_swapped ( + widget, "changed", + G_CALLBACK (em_format_redraw), priv->html_display); + + /* Load the view instance. */ + + e_mail_shell_content_update_view_instance ( + E_MAIL_SHELL_CONTENT (shell_content)); + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (priv->paned); + key = "/apps/evolution/mail/display/paned_size"; + gconf_bridge_bind_property_delayed (bridge, key, object, "position"); + + object = G_OBJECT (shell_content); + key = "/apps/evolution/mail/display/show_deleted"; + gconf_bridge_bind_property (bridge, key, object, "show-deleted"); + + /* Message list customizations. */ + + reader = E_MAIL_READER (shell_content); + message_list = e_mail_reader_get_message_list (reader); + + g_signal_connect_swapped ( + message_list, "message-selected", + G_CALLBACK (mail_shell_content_message_selected_cb), + shell_content); +} + +static guint32 +mail_shell_content_check_state (EShellContent *shell_content) +{ + return e_mail_reader_check_state (E_MAIL_READER (shell_content)); +} + +static GtkActionGroup * +mail_shell_content_get_action_group (EMailReader *reader) +{ + EShellContent *shell_content; + EShellWindow *shell_window; + EShellView *shell_view; + + shell_content = E_SHELL_CONTENT (reader); + shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + + return E_SHELL_WINDOW_ACTION_GROUP_MAIL (shell_window); +} + +static gboolean +mail_shell_content_get_hide_deleted (EMailReader *reader) +{ + EMailShellContent *mail_shell_content; + + mail_shell_content = E_MAIL_SHELL_CONTENT (reader); + + return !e_mail_shell_content_get_show_deleted (mail_shell_content); +} + +static EMFormatHTMLDisplay * +mail_shell_content_get_html_display (EMailReader *reader) +{ + EMailShellContentPrivate *priv; + + priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (reader); + + return priv->html_display; +} + +static MessageList * +mail_shell_content_get_message_list (EMailReader *reader) +{ + EMailShellContentPrivate *priv; + + priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (reader); + + return MESSAGE_LIST (priv->message_list); +} + +static EShellBackend * +mail_shell_content_get_shell_backend (EMailReader *reader) +{ + EShellContent *shell_content; + EShellView *shell_view; + + shell_content = E_SHELL_CONTENT (reader); + shell_view = e_shell_content_get_shell_view (shell_content); + + return e_shell_view_get_shell_backend (shell_view); +} + +static GtkWindow * +mail_shell_content_get_window (EMailReader *reader) +{ + EShellContent *shell_content; + EShellWindow *shell_window; + EShellView *shell_view; + + shell_content = E_SHELL_CONTENT (reader); + shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + + return GTK_WINDOW (shell_window); +} + +static void +mail_shell_content_set_folder (EMailReader *reader, + CamelFolder *folder, + const gchar *folder_uri) +{ + EMailShellContentPrivate *priv; + EMailReaderIface *default_iface; + MessageList *message_list; + gboolean different_folder; + + priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (reader); + + message_list = e_mail_reader_get_message_list (reader); + + message_list_freeze (message_list); + + different_folder = + message_list->folder != NULL && + folder != message_list->folder; + + /* Chain up to interface's default set_folder() method. */ + default_iface = g_type_default_interface_peek (E_TYPE_MAIL_READER); + default_iface->set_folder (reader, folder, folder_uri); + + if (folder == NULL) + goto exit; + + mail_refresh_folder (folder, NULL, NULL); + + /* This function gets triggered several times at startup, + * so we don't want to reset the message suppression state + * unless we're actually switching to a different folder. */ + if (different_folder) + priv->suppress_message_selection = FALSE; + + /* This is a one-time-only callback. */ + if (message_list->cursor_uid == NULL && priv->message_list_built_id == 0) + priv->message_list_built_id = g_signal_connect_swapped ( + message_list, "message-list-built", + G_CALLBACK (mail_shell_content_message_list_built_cb), + reader); + +exit: + message_list_thaw (message_list); +} + +static void +mail_shell_content_show_search_bar (EMailReader *reader) +{ + EMailShellContentPrivate *priv; + + priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (reader); + + gtk_widget_show (priv->search_bar); +} + +static void +mail_shell_content_class_init (EMailShellContentClass *class) +{ + GObjectClass *object_class; + EShellContentClass *shell_content_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMailShellContentPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_shell_content_set_property; + object_class->get_property = mail_shell_content_get_property; + object_class->dispose = mail_shell_content_dispose; + object_class->constructed = mail_shell_content_constructed; + + shell_content_class = E_SHELL_CONTENT_CLASS (class); + shell_content_class->new_search_context = em_search_context_new; + shell_content_class->check_state = mail_shell_content_check_state; + + g_object_class_install_property ( + object_class, + PROP_PREVIEW_VISIBLE, + g_param_spec_boolean ( + "preview-visible", + _("Preview is Visible"), + _("Whether the preview pane is visible"), + TRUE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SHOW_DELETED, + g_param_spec_boolean ( + "show-deleted", + "Show Deleted", + NULL, + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_VERTICAL_VIEW, + g_param_spec_boolean ( + "vertical-view", + _("Vertical View"), + _("Whether vertical view is enabled"), + FALSE, + G_PARAM_READWRITE)); +} + +static void +mail_shell_content_iface_init (EMailReaderIface *iface) +{ + iface->get_action_group = mail_shell_content_get_action_group; + iface->get_hide_deleted = mail_shell_content_get_hide_deleted; + iface->get_html_display = mail_shell_content_get_html_display; + iface->get_message_list = mail_shell_content_get_message_list; + iface->get_shell_backend = mail_shell_content_get_shell_backend; + iface->get_window = mail_shell_content_get_window; + iface->set_folder = mail_shell_content_set_folder; + iface->show_search_bar = mail_shell_content_show_search_bar; +} + +static void +mail_shell_content_init (EMailShellContent *mail_shell_content) +{ + mail_shell_content->priv = + E_MAIL_SHELL_CONTENT_GET_PRIVATE (mail_shell_content); + + mail_shell_content->priv->preview_visible = TRUE; + + /* Postpone widget construction until we have a shell view. */ +} + +GType +e_mail_shell_content_get_type (void) +{ + return mail_shell_content_type; +} + +void +e_mail_shell_content_register_type (GTypeModule *type_module) +{ + static const GTypeInfo type_info = { + sizeof (EMailShellContentClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) mail_shell_content_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMailShellContent), + 0, /* n_preallocs */ + (GInstanceInitFunc) mail_shell_content_init, + NULL /* value_table */ + }; + + static const GInterfaceInfo iface_info = { + (GInterfaceInitFunc) mail_shell_content_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL /* interface_data */ + }; + + mail_shell_content_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_CONTENT, + "EMailShellContent", &type_info, 0); + + g_type_module_add_interface ( + type_module, mail_shell_content_type, + E_TYPE_MAIL_READER, &iface_info); +} + +GtkWidget * +e_mail_shell_content_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_MAIL_SHELL_CONTENT, + "shell-view", shell_view, NULL); +} + +gboolean +e_mail_shell_content_get_preview_visible (EMailShellContent *mail_shell_content) +{ + g_return_val_if_fail ( + E_IS_MAIL_SHELL_CONTENT (mail_shell_content), FALSE); + + return mail_shell_content->priv->preview_visible; +} + +void +e_mail_shell_content_set_preview_visible (EMailShellContent *mail_shell_content, + gboolean preview_visible) +{ + GtkPaned *paned; + GtkWidget *child; + + g_return_if_fail (E_IS_MAIL_SHELL_CONTENT (mail_shell_content)); + + if (preview_visible == mail_shell_content->priv->preview_visible) + return; + + paned = GTK_PANED (mail_shell_content->priv->paned); + child = gtk_paned_get_child2 (paned); + + if (preview_visible) + gtk_widget_show (child); + else + gtk_widget_hide (child); + + mail_shell_content->priv->preview_visible = preview_visible; + + g_object_notify (G_OBJECT (mail_shell_content), "preview-visible"); +} + +gboolean +e_mail_shell_content_get_show_deleted (EMailShellContent *mail_shell_content) +{ + g_return_val_if_fail ( + E_IS_MAIL_SHELL_CONTENT (mail_shell_content), FALSE); + + return mail_shell_content->priv->show_deleted; +} + +void +e_mail_shell_content_set_show_deleted (EMailShellContent *mail_shell_content, + gboolean show_deleted) +{ + g_return_if_fail (E_IS_MAIL_SHELL_CONTENT (mail_shell_content)); + + mail_shell_content->priv->show_deleted = show_deleted; + + g_object_notify (G_OBJECT (mail_shell_content), "show-deleted"); +} + +gboolean +e_mail_shell_content_get_vertical_view (EMailShellContent *mail_shell_content) +{ + g_return_val_if_fail ( + E_IS_MAIL_SHELL_CONTENT (mail_shell_content), FALSE); + + return mail_shell_content->priv->vertical_view; +} + +void +e_mail_shell_content_set_vertical_view (EMailShellContent *mail_shell_content, + gboolean vertical_view) +{ + GConfBridge *bridge; + GtkWidget *old_paned; + GtkWidget *new_paned; + GtkWidget *child1; + GtkWidget *child2; + guint binding_id; + const gchar *key; + + g_return_if_fail (E_IS_MAIL_SHELL_CONTENT (mail_shell_content)); + + if (vertical_view == mail_shell_content->priv->vertical_view) + return; + + bridge = gconf_bridge_get (); + old_paned = mail_shell_content->priv->paned; + binding_id = mail_shell_content->priv->paned_binding_id; + + child1 = gtk_paned_get_child1 (GTK_PANED (old_paned)); + child2 = gtk_paned_get_child2 (GTK_PANED (old_paned)); + + if (binding_id > 0) + gconf_bridge_unbind (bridge, binding_id); + + if (vertical_view) { + new_paned = gtk_hpaned_new (); + key = "/apps/evolution/mail/display/hpaned_size"; + } else { + new_paned = gtk_vpaned_new (); + key = "/apps/evolution/mail/display/paned_size"; + } + + gtk_widget_reparent (child1, new_paned); + gtk_widget_reparent (child2, new_paned); + gtk_widget_show (new_paned); + + gtk_widget_destroy (old_paned); + gtk_container_add (GTK_CONTAINER (mail_shell_content), new_paned); + + binding_id = gconf_bridge_bind_property_delayed ( + bridge, key, G_OBJECT (new_paned), "position"); + + mail_shell_content->priv->vertical_view = vertical_view; + mail_shell_content->priv->paned_binding_id = binding_id; + mail_shell_content->priv->paned = g_object_ref (new_paned); + + e_mail_shell_content_update_view_instance (mail_shell_content); + + g_object_notify (G_OBJECT (mail_shell_content), "vertical-view"); +} + +GalViewInstance * +e_mail_shell_content_get_view_instance (EMailShellContent *mail_shell_content) +{ + g_return_val_if_fail ( + E_IS_MAIL_SHELL_CONTENT (mail_shell_content), NULL); + + return mail_shell_content->priv->view_instance; +} + +void +e_mail_shell_content_set_search_strings (EMailShellContent *mail_shell_content, + GSList *search_strings) +{ + EMailSearchBar *search_bar; + ESearchingTokenizer *tokenizer; + + g_return_if_fail (E_IS_MAIL_SHELL_CONTENT (mail_shell_content)); + + search_bar = E_MAIL_SEARCH_BAR (mail_shell_content->priv->search_bar); + tokenizer = e_mail_search_bar_get_tokenizer (search_bar); + + e_searching_tokenizer_set_secondary_case_sensitivity (tokenizer, FALSE); + e_searching_tokenizer_set_secondary_search_string (tokenizer, NULL); + + while (search_strings != NULL) { + e_searching_tokenizer_add_secondary_search_string ( + tokenizer, search_strings->data); + search_strings = g_slist_next (search_strings); + } + + e_mail_search_bar_changed (search_bar); +} + +void +e_mail_shell_content_update_view_instance (EMailShellContent *mail_shell_content) +{ + EMailReader *reader; + EShellContent *shell_content; + EShellView *shell_view; + EShellViewClass *shell_view_class; + GalViewCollection *view_collection; + GalViewInstance *view_instance; + MessageList *message_list; + gboolean outgoing_folder; + gboolean show_vertical_view; + gchar *view_id; + + g_return_if_fail (E_IS_MAIL_SHELL_CONTENT (mail_shell_content)); + + shell_content = E_SHELL_CONTENT (mail_shell_content); + shell_view = e_shell_content_get_shell_view (shell_content); + shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); + view_collection = shell_view_class->view_collection; + + reader = E_MAIL_READER (mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + /* If no folder is selected, return silently. */ + if (message_list->folder == NULL) + return; + + /* If we have a folder, we should also have a URI. */ + g_return_if_fail (message_list->folder_uri != NULL); + + if (mail_shell_content->priv->view_instance != NULL) { + g_object_unref (mail_shell_content->priv->view_instance); + mail_shell_content->priv->view_instance = NULL; + } + + view_id = mail_config_folder_to_safe_url (message_list->folder); + view_instance = e_shell_view_new_view_instance (shell_view, view_id); + mail_shell_content->priv->view_instance = view_instance; + + show_vertical_view = + e_mail_shell_content_get_vertical_view (mail_shell_content); + + if (show_vertical_view) { + gchar *filename; + gchar *safe_view_id; + + /* Force the view instance into vertical view. */ + + g_free (view_instance->custom_filename); + g_free (view_instance->current_view_filename); + + safe_view_id = g_strdup (view_id); + e_filename_make_safe (safe_view_id); + + filename = g_strdup_printf ( + "custom_wide_view-%s.xml", safe_view_id); + view_instance->custom_filename = g_build_filename ( + view_collection->local_dir, filename, NULL); + g_free (filename); + + filename = g_strdup_printf ( + "current_wide_view-%s.xml", safe_view_id); + view_instance->current_view_filename = g_build_filename ( + view_collection->local_dir, filename, NULL); + g_free (filename); + + g_free (safe_view_id); + } + + g_free (view_id); + + outgoing_folder = + em_utils_folder_is_drafts ( + message_list->folder, message_list->folder_uri) || + em_utils_folder_is_outbox ( + message_list->folder, message_list->folder_uri) || + em_utils_folder_is_sent ( + message_list->folder, message_list->folder_uri); + + if (outgoing_folder) { + if (show_vertical_view) + gal_view_instance_set_default_view ( + view_instance, "Wide_View_Sent"); + else + gal_view_instance_set_default_view ( + view_instance, "As_Sent_Folder"); + } else if (show_vertical_view) { + gal_view_instance_set_default_view ( + view_instance, "Wide_View_Normal"); + } + + gal_view_instance_load (view_instance); + + if (!gal_view_instance_exists (view_instance)) { + gchar *state_filename; + + state_filename = mail_config_folder_to_cachename ( + message_list->folder, "et-header-"); + + if (g_file_test (state_filename, G_FILE_TEST_IS_REGULAR)) { + ETableSpecification *spec; + ETableState *state; + GalView *view; + gchar *spec_filename; + + spec = e_table_specification_new (); + spec_filename = g_build_filename ( + EVOLUTION_ETSPECDIR, + "message-list.etspec", + NULL); + e_table_specification_load_from_file ( + spec, spec_filename); + g_free (spec_filename); + + state = e_table_state_new (); + view = gal_view_etable_new (spec, ""); + + e_table_state_load_from_file ( + state, state_filename); + gal_view_etable_set_state ( + GAL_VIEW_ETABLE (view), state); + gal_view_instance_set_custom_view ( + view_instance, view); + + g_object_unref (state); + g_object_unref (view); + g_object_unref (spec); + } + + g_free (state_filename); + } + + g_signal_connect ( + view_instance, "display-view", + G_CALLBACK (mail_shell_content_display_view_cb), + mail_shell_content); + + mail_shell_content_display_view_cb ( + mail_shell_content, + gal_view_instance_get_current_view (view_instance)); +} diff --git a/modules/mail/e-mail-shell-content.h b/modules/mail/e-mail-shell-content.h new file mode 100644 index 0000000000..57d2438705 --- /dev/null +++ b/modules/mail/e-mail-shell-content.h @@ -0,0 +1,94 @@ +/* + * e-mail-shell-content.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_SHELL_CONTENT_H +#define E_MAIL_SHELL_CONTENT_H + +#include +#include + +#include + +/* Standard GObject macros */ +#define E_TYPE_MAIL_SHELL_CONTENT \ + (e_mail_shell_content_get_type ()) +#define E_MAIL_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_SHELL_CONTENT, EMailShellContent)) +#define E_MAIL_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_SHELL_CONTENT, EMailShellContentClass)) +#define E_IS_MAIL_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_SHELL_CONTENT)) +#define E_IS_MAIL_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_SHELL_CONTENT)) +#define E_MAIL_SHELL_CONTENT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_SHELL_CONTENT, EMailShellContentClass)) + +G_BEGIN_DECLS + +typedef struct _EMailShellContent EMailShellContent; +typedef struct _EMailShellContentClass EMailShellContentClass; +typedef struct _EMailShellContentPrivate EMailShellContentPrivate; + +struct _EMailShellContent { + EShellContent parent; + EMailShellContentPrivate *priv; +}; + +struct _EMailShellContentClass { + EShellContentClass parent_class; +}; + +GType e_mail_shell_content_get_type (void); +void e_mail_shell_content_register_type + (GTypeModule *type_module); +GtkWidget * e_mail_shell_content_new(EShellView *shell_view); +gboolean e_mail_shell_content_get_preview_visible + (EMailShellContent *mail_shell_content); +void e_mail_shell_content_set_preview_visible + (EMailShellContent *mail_shell_content, + gboolean preview_visible); +gboolean e_mail_shell_content_get_show_deleted + (EMailShellContent *mail_shell_content); +void e_mail_shell_content_set_show_deleted + (EMailShellContent *mail_shell_content, + gboolean show_deleted); +gboolean e_mail_shell_content_get_vertical_view + (EMailShellContent *mail_shell_content); +void e_mail_shell_content_set_vertical_view + (EMailShellContent *mail_shell_content, + gboolean vertical_view); +GalViewInstance * + e_mail_shell_content_get_view_instance + (EMailShellContent *mail_shell_content); +void e_mail_shell_content_set_search_strings + (EMailShellContent *mail_shell_content, + GSList *search_strings); +void e_mail_shell_content_update_view_instance + (EMailShellContent *mail_shell_content); + +G_END_DECLS + +#endif /* E_MAIL_SHELL_CONTENT_H */ diff --git a/modules/mail/e-mail-shell-migrate.c b/modules/mail/e-mail-shell-migrate.c new file mode 100644 index 0000000000..2158580bf9 --- /dev/null +++ b/modules/mail/e-mail-shell-migrate.c @@ -0,0 +1,3104 @@ +/* + * e-mail-shell-migrate.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-shell-migrate.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "e-util/e-account-utils.h" +#include "e-util/e-bconf-map.h" +#include "e-util/e-error.h" +#include "e-util/e-util-private.h" +#include "e-util/e-plugin.h" +#include "e-util/e-signature-utils.h" + +#include "e-mail-shell-backend.h" +#include "shell/e-shell-migrate.h" + +#include "e-mail-store.h" +#include "mail-config.h" +#include "em-utils.h" + +#define d(x) x + +#ifndef G_OS_WIN32 +/* No versions previous to 2.8 or thereabouts have been available on + * Windows, so don't bother with upgrade support from earlier versions + * on Win32. Do try to support upgrades from 2.12 and later to the + * current version. + */ + +/* upgrade helper functions */ +static xmlDocPtr +emm_load_xml (const gchar *dirname, const gchar *filename) +{ + xmlDocPtr doc; + struct stat st; + gchar *path; + + path = g_strdup_printf ("%s/%s", dirname, filename); + if (stat (path, &st) == -1 || !(doc = xmlParseFile (path))) { + g_free (path); + return NULL; + } + + g_free (path); + + return doc; +} + +static gint +emm_save_xml (xmlDocPtr doc, const gchar *dirname, const gchar *filename) +{ + gchar *path; + gint retval; + + path = g_strdup_printf ("%s/%s", dirname, filename); + retval = e_xml_save_file (path, doc); + g_free (path); + + return retval; +} + +static xmlNodePtr +xml_find_node (xmlNodePtr parent, const gchar *name) +{ + xmlNodePtr node; + + node = parent->children; + while (node != NULL) { + if (node->name && !strcmp ((gchar *)node->name, name)) + return node; + + node = node->next; + } + + return NULL; +} + +static void +upgrade_xml_uris (xmlDocPtr doc, gchar * (* upgrade_uri) (const gchar *uri)) +{ + xmlNodePtr root, node; + gchar *uri, *new; + + if (!doc || !(root = xmlDocGetRootElement (doc))) + return; + + if (!root->name || strcmp ((gchar *)root->name, "filteroptions") != 0) { + /* root node is not , nothing to upgrade */ + return; + } + + if (!(node = xml_find_node (root, "ruleset"))) { + /* no ruleset node, nothing to upgrade */ + return; + } + + node = node->children; + while (node != NULL) { + if (node->name && !strcmp ((gchar *)node->name, "rule")) { + xmlNodePtr actionset, part, val, n; + + if ((actionset = xml_find_node (node, "actionset"))) { + /* filters.xml */ + part = actionset->children; + while (part != NULL) { + if (part->name && !strcmp ((gchar *)part->name, "part")) { + val = part->children; + while (val != NULL) { + if (val->name && !strcmp ((gchar *)val->name, "value")) { + gchar *type; + + type = (gchar *)xmlGetProp (val, (const guchar *)"type"); + if (type && !strcmp ((gchar *)type, "folder")) { + if ((n = xml_find_node (val, "folder"))) { + uri = (gchar *)xmlGetProp (n, (const guchar *)"uri"); + new = upgrade_uri (uri); + xmlFree (uri); + + xmlSetProp (n, (const guchar *)"uri", (guchar *)new); + g_free (new); + } + } + + xmlFree (type); + } + + val = val->next; + } + } + + part = part->next; + } + } else if ((actionset = xml_find_node (node, "sources"))) { + /* vfolders.xml */ + n = actionset->children; + while (n != NULL) { + if (n->name && !strcmp ((gchar *)n->name, "folder")) { + uri = (gchar *)xmlGetProp (n, (const guchar *)"uri"); + new = upgrade_uri (uri); + xmlFree (uri); + + xmlSetProp (n, (const guchar *)"uri", (guchar *)new); + g_free (new); + } + + n = n->next; + } + } + } + + node = node->next; + } +} + +/* 1.0 upgrade functions & data */ + +/* as much info as we have on a given account */ +struct _account_info_1_0 { + gchar *name; + gchar *uri; + gchar *base_uri; + union { + struct { + /* for imap */ + gchar *namespace; + gchar *namespace_full; + guint32 capabilities; + GHashTable *folders; + gchar dir_sep; + } imap; + } u; +}; + +struct _imap_folder_info_1_0 { + gchar *folder; + /* encoded? decoded? canonicalised? */ + gchar dir_sep; +}; + +static GHashTable *accounts_1_0 = NULL; +static GHashTable *accounts_name_1_0 = NULL; + +static void +imap_folder_info_1_0_free (struct _imap_folder_info_1_0 *fi) +{ + g_free(fi->folder); + g_free(fi); +} + +static void +account_info_1_0_free (struct _account_info_1_0 *ai) +{ + g_free(ai->name); + g_free(ai->uri); + g_free(ai->base_uri); + g_free(ai->u.imap.namespace); + g_free(ai->u.imap.namespace_full); + g_hash_table_destroy(ai->u.imap.folders); + g_free(ai); +} + +static gchar * +get_base_uri(const gchar *val) +{ + const gchar *tmp; + + tmp = strchr(val, ':'); + if (tmp) { + tmp++; + if (strncmp(tmp, "//", 2) == 0) + tmp += 2; + tmp = strchr(tmp, '/'); + } + + if (tmp) + return g_strndup(val, tmp-val); + else + return g_strdup(val); +} + +static gchar * +upgrade_xml_uris_1_0 (const gchar *uri) +{ + gchar *out = NULL; + + /* upgrades camel uri's */ + if (strncmp (uri, "imap:", 5) == 0) { + gchar *base_uri, dir_sep, *folder, *p; + struct _account_info_1_0 *ai; + + /* add namespace, canonicalise dir_sep to / */ + base_uri = get_base_uri (uri); + ai = g_hash_table_lookup (accounts_1_0, base_uri); + + if (ai == NULL) { + g_free (base_uri); + return NULL; + } + + dir_sep = ai->u.imap.dir_sep; + if (dir_sep == 0) { + /* no dir_sep listed, try get it from the namespace, if set */ + if (ai->u.imap.namespace != NULL) { + p = ai->u.imap.namespace; + while ((dir_sep = *p++)) { + if (dir_sep < '0' + || (dir_sep > '9' && dir_sep < 'A') + || (dir_sep > 'Z' && dir_sep < 'a') + || (dir_sep > 'z')) { + break; + } + p++; + } + } + + /* give up ... */ + if (dir_sep == 0) { + g_free (base_uri); + return NULL; + } + } + + folder = g_strdup (uri + strlen (base_uri) + 1); + + /* Add the namespace before the mailbox name, unless the mailbox is INBOX */ + if (ai->u.imap.namespace && strcmp ((gchar *)folder, "INBOX") != 0) + out = g_strdup_printf ("%s/%s/%s", base_uri, ai->u.imap.namespace, folder); + else + out = g_strdup_printf ("%s/%s", base_uri, folder); + + p = out; + while (*p) { + if (*p == dir_sep) + *p = '/'; + p++; + } + + g_free (folder); + g_free (base_uri); + } else if (strncmp (uri, "exchange:", 9) == 0) { + gchar *base_uri, *folder, *p; + + /* exchange://user@host/exchange/ * -> exchange://user@host/personal/ * */ + /* Any url encoding (%xx) in the folder name is also removed */ + base_uri = get_base_uri (uri); + uri += strlen (base_uri) + 1; + if (strncmp (uri, "exchange/", 9) == 0) { + folder = e_bconf_url_decode (uri + 9); + p = strchr (folder, '/'); + out = g_strdup_printf ("%s/personal%s", base_uri, p ? p : "/"); + g_free (folder); + } + } else if (strncmp (uri, "exchanget:", 10) == 0) { + /* these should be converted in the accounts table when it is loaded */ + g_warning ("exchanget: uri not converted: '%s'", uri); + } + + return out; +} + +static gchar * +parse_lsub (const gchar *lsub, gchar *dir_sep) +{ + static gint comp; + static regex_t pat; + regmatch_t match[3]; + const gchar *m = "^\\* LSUB \\([^)]*\\) \"?([^\" ]+)\"? \"?(.*)\"?$"; + + if (!comp) { + if (regcomp (&pat, m, REG_EXTENDED|REG_ICASE) == -1) { + g_warning ("reg comp '%s' failed: %s", m, g_strerror (errno)); + return NULL; + } + comp = 1; + } + + if (regexec (&pat, lsub, 3, match, 0) == 0) { + if (match[1].rm_so != -1 && match[2].rm_so != -1) { + if (dir_sep) + *dir_sep = (match[1].rm_eo - match[1].rm_so == 1) ? lsub[match[1].rm_so] : 0; + return g_strndup (lsub + match[2].rm_so, match[2].rm_eo - match[2].rm_so); + } + } + + return NULL; +} + +static gboolean +read_imap_storeinfo (struct _account_info_1_0 *si) +{ + FILE *storeinfo; + guint32 tmp; + gchar *buf, *folder, dir_sep, *path, *name, *p; + struct _imap_folder_info_1_0 *fi; + + si->u.imap.folders = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) NULL, + (GDestroyNotify) imap_folder_info_1_0_free); + + /* get details from uri first */ + name = strstr (si->uri, ";override_namespace"); + if (name) { + name = strstr (si->uri, ";namespace="); + if (name) { + gchar *end; + + name += strlen (";namespace="); + if (*name == '\"') { + name++; + end = strchr (name, '\"'); + } else { + end = strchr (name, ';'); + } + + if (end) { + /* try get the dir_sep from the namespace */ + si->u.imap.namespace = g_strndup (name, end-name); + + p = si->u.imap.namespace; + while ((dir_sep = *p++)) { + if (dir_sep < '0' + || (dir_sep > '9' && dir_sep < 'A') + || (dir_sep > 'Z' && dir_sep < 'a') + || (dir_sep > 'z')) { + si->u.imap.dir_sep = dir_sep; + break; + } + p++; + } + } + } + } + + /* now load storeinfo if it exists */ + path = g_build_filename (g_get_home_dir (), "evolution", "mail", "imap", si->base_uri + 7, "storeinfo", NULL); + storeinfo = fopen (path, "r"); + g_free (path); + if (storeinfo == NULL) { + g_warning ("could not find imap store info '%s'", path); + return FALSE; + } + + /* ignore version */ + camel_file_util_decode_uint32 (storeinfo, &tmp); + camel_file_util_decode_uint32 (storeinfo, &si->u.imap.capabilities); + g_free (si->u.imap.namespace); + camel_file_util_decode_string (storeinfo, &si->u.imap.namespace); + camel_file_util_decode_uint32 (storeinfo, &tmp); + si->u.imap.dir_sep = tmp; + /* strip trailing dir_sep or / */ + if (si->u.imap.namespace + && (si->u.imap.namespace[strlen (si->u.imap.namespace) - 1] == si->u.imap.dir_sep + || si->u.imap.namespace[strlen (si->u.imap.namespace) - 1] == '/')) { + si->u.imap.namespace[strlen (si->u.imap.namespace) - 1] = 0; + } + + d(printf ("namespace '%s' dir_sep '%c'\n", si->u.imap.namespace, si->u.imap.dir_sep ? si->u.imap.dir_sep : '?')); + + while (camel_file_util_decode_string (storeinfo, &buf) == 0) { + folder = parse_lsub (buf, &dir_sep); + if (folder) { + fi = g_new0 (struct _imap_folder_info_1_0, 1); + fi->folder = folder; + fi->dir_sep = dir_sep; +#if d(!)0 + printf (" add folder '%s' ", folder); + if (dir_sep) + printf ("'%c'\n", dir_sep); + else + printf ("NIL\n"); +#endif + g_hash_table_insert (si->u.imap.folders, fi->folder, fi); + } else { + g_warning ("Could not parse LIST result '%s'\n", buf); + } + } + + fclose (storeinfo); + + return TRUE; +} + +static gboolean +load_accounts_1_0 (xmlDocPtr doc) +{ + xmlNodePtr source; + gchar *val, *tmp; + gint count = 0, i; + gchar key[32]; + + if (!(source = e_bconf_get_path (doc, "/Mail/Accounts"))) + return TRUE; + + if ((val = e_bconf_get_value (source, "num"))) { + count = atoi (val); + xmlFree (val); + } + + /* load account upgrade info for each account */ + for (i = 0; i < count; i++) { + struct _account_info_1_0 *ai; + gchar *rawuri; + + sprintf (key, "source_url_%d", i); + if (!(rawuri = e_bconf_get_value (source, key))) + continue; + + ai = g_malloc0 (sizeof (struct _account_info_1_0)); + ai->uri = e_bconf_hex_decode (rawuri); + ai->base_uri = get_base_uri (ai->uri); + sprintf (key, "account_name_%d", i); + ai->name = e_bconf_get_string (source, key); + + d(printf("load account '%s'\n", ai->uri)); + + if (!strncmp (ai->uri, "imap:", 5)) { + read_imap_storeinfo (ai); + } else if (!strncmp (ai->uri, "exchange:", 9)) { + xmlNodePtr node; + + d(printf (" upgrade exchange account\n")); + /* small hack, poke the source_url into the transport_url for exchanget: transports + - this will be picked up later in the conversion */ + sprintf (key, "transport_url_%d", i); + node = e_bconf_get_entry (source, key); + if (node && (val = (gchar *)xmlGetProp (node, (const guchar *)"value"))) { + tmp = e_bconf_hex_decode (val); + xmlFree (val); + if (strncmp (tmp, "exchanget:", 10) == 0) + xmlSetProp (node, (const guchar *)"value", (guchar *)rawuri); + g_free (tmp); + } else { + d(printf (" couldn't find transport uri?\n")); + } + } + xmlFree (rawuri); + + g_hash_table_insert (accounts_1_0, ai->base_uri, ai); + if (ai->name) + g_hash_table_insert (accounts_name_1_0, ai->name, ai); + } + + return TRUE; +} + +static gboolean +em_migrate_1_0 (const gchar *data_dir, xmlDocPtr config_xmldb, xmlDocPtr filters, xmlDocPtr vfolders, GError **error) +{ + accounts_1_0 = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) NULL, + (GDestroyNotify) account_info_1_0_free); + accounts_name_1_0 = g_hash_table_new (g_str_hash, g_str_equal); + load_accounts_1_0 (config_xmldb); + + upgrade_xml_uris(filters, upgrade_xml_uris_1_0); + upgrade_xml_uris(vfolders, upgrade_xml_uris_1_0); + + g_hash_table_destroy (accounts_1_0); + g_hash_table_destroy (accounts_name_1_0); + + return TRUE; +} + +/* 1.2 upgrade functions */ +static gboolean +is_xml1encoded (const gchar *txt) +{ + const guchar *p; + gint isxml1 = FALSE; + gint is8bit = FALSE; + + p = (const guchar *)txt; + while (*p) { + if (p[0] == '\\' && p[1] == 'U' && p[2] == '+' + && isxdigit (p[3]) && isxdigit (p[4]) && isxdigit (p[5]) && isxdigit (p[6]) + && p[7] == '\\') { + isxml1 = TRUE; + p+=7; + } else if (p[0] >= 0x80) + is8bit = TRUE; + p++; + } + + /* check for invalid utf8 that needs cleaning */ + if (is8bit && !isxml1) + isxml1 = !g_utf8_validate (txt, -1, NULL); + + return isxml1; +} + +static gchar * +decode_xml1 (const gchar *txt) +{ + GString *out = g_string_new (""); + const guchar *p; + gchar *res; + + /* convert: + \U+XXXX\ -> utf8 + 8 bit characters -> utf8 (iso-8859-1) */ + + p = (const guchar *) txt; + while (*p) { + if (p[0] > 0x80 + || (p[0] == '\\' && p[1] == 'U' && p[2] == '+' + && isxdigit (p[3]) && isxdigit (p[4]) && isxdigit (p[5]) && isxdigit (p[6]) + && p[7] == '\\')) { + gchar utf8[8]; + gunichar u; + + if (p[0] == '\\') { + memcpy (utf8, p + 3, 4); + utf8[4] = 0; + u = strtoul (utf8, NULL, 16); + p+=7; + } else + u = p[0]; + utf8[g_unichar_to_utf8 (u, utf8)] = 0; + g_string_append (out, utf8); + } else { + g_string_append_c (out, *p); + } + p++; + } + + res = out->str; + g_string_free (out, FALSE); + + return res; +} + +static gchar * +utf8_reencode (const gchar *txt) +{ + GString *out = g_string_new (""); + gchar *p; + gchar *res; + + /* convert: + libxml1 8 bit utf8 converted to xml entities byte-by-byte chars -> utf8 */ + + p = (gchar *)txt; + + while (*p) { + g_string_append_c (out, (gchar)g_utf8_get_char ((const gchar *)p)); + p = (gchar *)g_utf8_next_char (p); + } + + res = out->str; + if (g_utf8_validate (res, -1, NULL)) { + g_string_free (out, FALSE); + return res; + } else { + g_string_free (out, TRUE); + return g_strdup (txt); + } +} + +static gboolean +upgrade_xml_1_2_rec (xmlNodePtr node) +{ + const gchar *value_tags[] = { "string", "address", "regex", "file", "command", NULL }; + const gchar *rule_tags[] = { "title", NULL }; + const gchar *item_props[] = { "name", NULL }; + struct { + const gchar *name; + const gchar **tags; + const gchar **props; + } tags[] = { + { "value", value_tags, NULL }, + { "rule", rule_tags, NULL }, + { "item", NULL, item_props }, + { 0 }, + }; + xmlNodePtr work; + gint i,j; + gchar *txt, *tmp; + + /* upgrades the content of a node, if the node has a specific parent/node name */ + + for (i = 0; tags[i].name; i++) { + if (!strcmp ((gchar *)node->name, tags[i].name)) { + if (tags[i].tags != NULL) { + work = node->children; + while (work) { + for (j = 0; tags[i].tags[j]; j++) { + if (!strcmp ((gchar *)work->name, tags[i].tags[j])) { + txt = (gchar *)xmlNodeGetContent (work); + if (is_xml1encoded (txt)) { + tmp = decode_xml1 (txt); + d(printf ("upgrading xml node %s/%s '%s' -> '%s'\n", + tags[i].name, tags[i].tags[j], txt, tmp)); + xmlNodeSetContent (work, (guchar *)tmp); + g_free (tmp); + } + xmlFree (txt); + } + } + work = work->next; + } + break; + } + + if (tags[i].props != NULL) { + for (j = 0; tags[i].props[j]; j++) { + txt = (gchar *)xmlGetProp (node, (guchar *)tags[i].props[j]); + tmp = utf8_reencode (txt); + d(printf ("upgrading xml property %s on node %s '%s' -> '%s'\n", + tags[i].props[j], tags[i].name, txt, tmp)); + xmlSetProp (node, (const guchar *)tags[i].props[j], (guchar *)tmp); + g_free (tmp); + xmlFree (txt); + } + } + } + } + + node = node->children; + while (node) { + upgrade_xml_1_2_rec (node); + node = node->next; + } + + return TRUE; +} + +static gboolean +em_upgrade_xml_1_2 (xmlDocPtr doc) +{ + xmlNodePtr root; + + if (!doc || !(root = xmlDocGetRootElement (doc))) + return TRUE; + + return upgrade_xml_1_2_rec (root); +} + +/* ********************************************************************** */ +/* Tables for converting flat bonobo conf -> gconf xml blob */ +/* ********************************************************************** */ + +/* Mail/Accounts/ * */ +static e_bconf_map_t cc_map[] = { + { "account_always_cc_%i", "always", E_BCONF_MAP_BOOL }, + { "account_always_cc_addrs_%i", "recipients", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, + { NULL }, +}; + +static e_bconf_map_t bcc_map[] = { + { "account_always_cc_%i", "always", E_BCONF_MAP_BOOL }, + { "account_always_bcc_addrs_%i", "recipients", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, + { NULL }, +}; + +static e_bconf_map_t pgp_map[] = { + { "account_pgp_encrypt_to_self_%i", "encrypt-to-self", E_BCONF_MAP_BOOL }, + { "account_pgp_always_trust_%i", "always-trust", E_BCONF_MAP_BOOL }, + { "account_pgp_always_sign_%i", "always-sign", E_BCONF_MAP_BOOL }, + { "account_pgp_no_imip_sign_%i", "no-imip-sign", E_BCONF_MAP_BOOL }, + { "account_pgp_key_%i", "key-id", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, + { NULL }, +}; + +static e_bconf_map_t smime_map[] = { + { "account_smime_encrypt_to_self_%i", "encrypt-to-self", E_BCONF_MAP_BOOL }, + { "account_smime_always_sign_%i", "always-sign", E_BCONF_MAP_BOOL }, + { "account_smime_key_%i", "key-id", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, + { NULL }, +}; + +static e_bconf_map_t identity_sig_map[] = { + { "identity_autogenerated_signature_%i", "auto", E_BCONF_MAP_BOOL }, + { "identity_def_signature_%i", "default", E_BCONF_MAP_LONG }, + { NULL }, +}; + +static e_bconf_map_t identity_map[] = { + { "identity_name_%i", "name", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, + { "identity_address_%i", "addr-spec", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, + { "identity_reply_to_%i", "reply-to", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, + { "identity_organization_%i", "organization", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, + { NULL, "signature", E_BCONF_MAP_CHILD, identity_sig_map }, + { NULL }, +}; + +static e_bconf_map_t source_map[] = { + { "source_save_passwd_%i", "save-passwd", E_BCONF_MAP_BOOL }, + { "source_keep_on_server_%i", "keep-on-server", E_BCONF_MAP_BOOL }, + { "source_auto_check_%i", "auto-check", E_BCONF_MAP_BOOL }, + { "source_auto_check_time_%i", "auto-check-timeout", E_BCONF_MAP_LONG }, + { "source_url_%i", "url", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, + { NULL }, +}; + +static e_bconf_map_t transport_map[] = { + { "transport_save_passwd_%i", "save-passwd", E_BCONF_MAP_BOOL }, + { "transport_url_%i", "url", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, + { NULL }, +}; + +static e_bconf_map_t account_map[] = { + { "account_name_%i", "name", E_BCONF_MAP_STRING }, + { "source_enabled_%i", "enabled", E_BCONF_MAP_BOOL }, + { NULL, "identity", E_BCONF_MAP_CHILD, identity_map }, + { NULL, "source", E_BCONF_MAP_CHILD, source_map }, + { NULL, "transport", E_BCONF_MAP_CHILD, transport_map }, + { "account_drafts_folder_uri_%i", "drafts-folder", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, + { "account_sent_folder_uri_%i", "sent-folder", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, + { NULL, "auto-cc", E_BCONF_MAP_CHILD, cc_map }, + { NULL, "auto-bcc", E_BCONF_MAP_CHILD, bcc_map }, + { NULL, "pgp", E_BCONF_MAP_CHILD, pgp_map }, + { NULL, "smime", E_BCONF_MAP_CHILD, smime_map }, + { NULL }, +}; + +/* /Mail/Signatures/ * */ +static e_bconf_map_t signature_format_map[] = { + { "text/plain", }, + { "text/html", }, + { NULL } +}; + +static e_bconf_map_t signature_map[] = { + { "name_%i", "name", E_BCONF_MAP_STRING }, + { "html_%i", "format", E_BCONF_MAP_ENUM, signature_format_map }, + { "filename_%i", "filename", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, + { "script_%i", "script", E_BCONF_MAP_STRING|E_BCONF_MAP_CONTENT }, + { NULL }, +}; + +/* ********************************************************************** */ +/* Tables for bonobo conf -> gconf conversion */ +/* ********************************************************************** */ + +static e_gconf_map_t mail_accounts_map[] = { + /* /Mail/Accounts - most entries are processed via the xml blob routine */ + /* This also works because the initial uid mapping is 1:1 with the list order */ + { "default_account", "mail/default_account", E_GCONF_MAP_SIMPLESTRING }, + { 0 }, +}; + +static e_gconf_map_t mail_display_map[] = { + /* /Mail/Display */ + { "side_bar_search", "mail/display/side_bar_search", E_GCONF_MAP_BOOL }, + { "thread_list", "mail/display/thread_list", E_GCONF_MAP_BOOL }, + { "thread_subject", "mail/display/thread_subject", E_GCONF_MAP_BOOL }, + { "hide_deleted", "mail/display/show_deleted", E_GCONF_MAP_BOOLNOT }, + { "preview_pane", "mail/display/show_preview", E_GCONF_MAP_BOOL }, + { "paned_size", "mail/display/paned_size", E_GCONF_MAP_INT }, + { "seen_timeout", "mail/display/mark_seen_timeout", E_GCONF_MAP_INT }, + { "do_seen_timeout", "mail/display/mark_seen", E_GCONF_MAP_BOOL }, + { "http_images", "mail/display/load_http_images", E_GCONF_MAP_INT }, + { "citation_highlight", "mail/display/mark_citations", E_GCONF_MAP_BOOL }, + { "citation_color", "mail/display/citation_colour", E_GCONF_MAP_COLOUR }, + { 0 }, +}; + +static e_gconf_map_t mail_format_map[] = { + /* /Mail/Format */ + { "message_display_style", "mail/display/message_style", E_GCONF_MAP_INT }, + { "send_html", "mail/composer/send_html", E_GCONF_MAP_BOOL }, + { "default_reply_style", "mail/format/reply_style", E_GCONF_MAP_INT }, + { "default_forward_style", "mail/format/forward_style", E_GCONF_MAP_INT }, + { "default_charset", "mail/composer/charset", E_GCONF_MAP_STRING }, + { "confirm_unwanted_html", "mail/prompts/unwanted_html", E_GCONF_MAP_BOOL }, + { 0 }, +}; + +static e_gconf_map_t mail_trash_map[] = { + /* /Mail/Trash */ + { "empty_on_exit", "mail/trash/empty_on_exit", E_GCONF_MAP_BOOL }, + { 0 }, +}; + +static e_gconf_map_t mail_prompts_map[] = { + /* /Mail/Prompts */ + { "confirm_expunge", "mail/prompts/expunge", E_GCONF_MAP_BOOL }, + { "empty_subject", "mail/prompts/empty_subject", E_GCONF_MAP_BOOL }, + { "only_bcc", "mail/prompts/only_bcc", E_GCONF_MAP_BOOL }, + { 0 } +}; + +static e_gconf_map_t mail_filters_map[] = { + /* /Mail/Filters */ + { "log", "mail/filters/log", E_GCONF_MAP_BOOL }, + { "log_path", "mail/filters/logfile", E_GCONF_MAP_STRING }, + { 0 } +}; + +static e_gconf_map_t mail_notify_map[] = { + /* /Mail/Notify */ + { "new_mail_notification", "mail/notify/type", E_GCONF_MAP_INT }, + { "new_mail_notification_sound_file", "mail/notify/sound", E_GCONF_MAP_STRING }, + { 0 } +}; + +static e_gconf_map_t mail_filesel_map[] = { + /* /Mail/Filesel */ + { "last_filesel_dir", "mail/save_dir", E_GCONF_MAP_STRING }, + { 0 } +}; + +static e_gconf_map_t mail_composer_map[] = { + /* /Mail/Composer */ + { "ViewFrom", "mail/composer/view/From", E_GCONF_MAP_BOOL }, + { "ViewReplyTo", "mail/composer/view/ReplyTo", E_GCONF_MAP_BOOL }, + { "ViewCC", "mail/composer/view/Cc", E_GCONF_MAP_BOOL }, + { "ViewBCC", "mail/composer/view/Bcc", E_GCONF_MAP_BOOL }, + { "ViewSubject", "mail/composer/view/Subject", E_GCONF_MAP_BOOL }, + { 0 }, +}; + +/* ********************************************************************** */ + +static e_gconf_map_t importer_elm_map[] = { + /* /Importer/Elm */ + { "mail", "importer/elm/mail", E_GCONF_MAP_BOOL }, + { "mail-imported", "importer/elm/mail-imported", E_GCONF_MAP_BOOL }, + { 0 }, +}; + +static e_gconf_map_t importer_pine_map[] = { + /* /Importer/Pine */ + { "mail", "importer/elm/mail", E_GCONF_MAP_BOOL }, + { "address", "importer/elm/address", E_GCONF_MAP_BOOL }, + { 0 }, +}; + +static e_gconf_map_t importer_netscape_map[] = { + /* /Importer/Netscape */ + { "mail", "importer/netscape/mail", E_GCONF_MAP_BOOL }, + { "settings", "importer/netscape/settings", E_GCONF_MAP_BOOL }, + { "filters", "importer/netscape/filters", E_GCONF_MAP_BOOL }, + { 0 }, +}; + +/* ********************************************************************** */ + +static e_gconf_map_list_t gconf_remap_list[] = { + { "/Mail/Accounts", mail_accounts_map }, + { "/Mail/Display", mail_display_map }, + { "/Mail/Format", mail_format_map }, + { "/Mail/Trash", mail_trash_map }, + { "/Mail/Prompts", mail_prompts_map }, + { "/Mail/Filters", mail_filters_map }, + { "/Mail/Notify", mail_notify_map }, + { "/Mail/Filesel", mail_filesel_map }, + { "/Mail/Composer", mail_composer_map }, + + { "/Importer/Elm", importer_elm_map }, + { "/Importer/Pine", importer_pine_map }, + { "/Importer/Netscape", importer_netscape_map }, + + { 0 }, +}; + +static struct { + const gchar *label; + const gchar *colour; +} label_default[5] = { + { N_("Important"), "#EF2929" }, /* red */ + { N_("Work"), "#F57900" }, /* orange */ + { N_("Personal"), "#4E9A06" }, /* green */ + { N_("To Do"), "#3465A4" }, /* blue */ + { N_("Later"), "#75507B" } /* purple */ +}; + +/* remaps mail config from bconf to gconf */ +static gboolean +bconf_import(GConfClient *gconf, xmlDocPtr config_xmldb) +{ + xmlNodePtr source; + gchar labx[16], colx[16]; + gchar *val, *lab, *col; + GSList *list, *l; + gint i; + + e_bconf_import(gconf, config_xmldb, gconf_remap_list); + + /* Labels: + label string + label colour as integer + -> label string:# colour as hex */ + source = e_bconf_get_path(config_xmldb, "/Mail/Labels"); + if (source) { + list = NULL; + for (i = 0; i < 5; i++) { + sprintf(labx, "label_%d", i); + sprintf(colx, "color_%d", i); + lab = e_bconf_get_string(source, labx); + if ((col = e_bconf_get_value(source, colx))) { + sprintf(colx, "#%06x", atoi(col) & 0xffffff); + g_free(col); + } else + strcpy(colx, label_default[i].colour); + + val = g_strdup_printf("%s:%s", lab ? lab : label_default[i].label, colx); + list = g_slist_append(list, val); + g_free(lab); + } + + gconf_client_set_list(gconf, "/apps/evolution/mail/labels", GCONF_VALUE_STRING, list, NULL); + while (list) { + l = list->next; + g_free(list->data); + g_slist_free_1(list); + list = l; + } + } else { + g_warning("could not find /Mail/Labels in old config database, skipping"); + } + + /* Accounts: The flat bonobo-config structure is remapped to a list of xml blobs. Upgrades as necessary */ + e_bconf_import_xml_blob(gconf, config_xmldb, account_map, "/Mail/Accounts", + "/apps/evolution/mail/accounts", "account", "uid"); + + /* Same for signatures */ + e_bconf_import_xml_blob(gconf, config_xmldb, signature_map, "/Mail/Signatures", + "/apps/evolution/mail/signatures", "signature", NULL); + + return TRUE; +} + +static gboolean +em_migrate_1_2(const gchar *data_dir, xmlDocPtr config_xmldb, xmlDocPtr filters, xmlDocPtr vfolders, GError **error) +{ + GConfClient *gconf; + + gconf = gconf_client_get_default(); + bconf_import(gconf, config_xmldb); + g_object_unref(gconf); + + em_upgrade_xml_1_2(filters); + em_upgrade_xml_1_2(vfolders); + + return TRUE; +} + +/* 1.4 upgrade functions */ + +#define EM_MIGRATE_SESSION_TYPE (em_migrate_session_get_type ()) +#define EM_MIGRATE_SESSION(obj) (CAMEL_CHECK_CAST((obj), EM_MIGRATE_SESSION_TYPE, EMMigrateSession)) +#define EM_MIGRATE_SESSION_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), EM_MIGRATE_SESSION_TYPE, EMMigrateSessionClass)) +#define EM_MIGRATE_IS_SESSION(o) (CAMEL_CHECK_TYPE((o), EM_MIGRATE_SESSION_TYPE)) + +typedef struct _EMMigrateSession { + CamelSession parent_object; + + CamelStore *store; /* new folder tree store */ + gchar *srcdir; /* old folder tree path */ +} EMMigrateSession; + +typedef struct _EMMigrateSessionClass { + CamelSessionClass parent_class; + +} EMMigrateSessionClass; + +static CamelType em_migrate_session_get_type (void); +static CamelSession *em_migrate_session_new (const gchar *path); + +static void +class_init (EMMigrateSessionClass *klass) +{ + ; +} + +static CamelType +em_migrate_session_get_type (void) +{ + static CamelType type = CAMEL_INVALID_TYPE; + + if (type == CAMEL_INVALID_TYPE) { + type = camel_type_register ( + camel_session_get_type (), + "EMMigrateSession", + sizeof (EMMigrateSession), + sizeof (EMMigrateSessionClass), + (CamelObjectClassInitFunc) class_init, + NULL, + NULL, + NULL); + } + + return type; +} + +static CamelSession * +em_migrate_session_new (const gchar *path) +{ + CamelSession *session; + + session = CAMEL_SESSION (camel_object_new (EM_MIGRATE_SESSION_TYPE)); + + camel_session_construct (session, path); + + return session; +} + + +#endif /* !G_OS_WIN32 */ + +static GtkWidget *window; +static GtkLabel *label; +static GtkProgressBar *progress; + +static void +em_migrate_setup_progress_dialog (const gchar *title, const gchar *desc) +{ + GtkWidget *vbox, *hbox, *w; + gchar *markup; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title ((GtkWindow *) window, _("Migrating...")); + gtk_window_set_modal ((GtkWindow *) window, TRUE); + gtk_container_set_border_width ((GtkContainer *) window, 6); + + vbox = gtk_vbox_new (FALSE, 6); + gtk_widget_show (vbox); + gtk_container_add ((GtkContainer *) window, vbox); + + w = gtk_label_new (desc); + + gtk_label_set_line_wrap ((GtkLabel *) w, TRUE); + gtk_widget_show (w); + gtk_box_pack_start_defaults ((GtkBox *) vbox, w); + + hbox = gtk_hbox_new (FALSE, 6); + gtk_widget_show (hbox); + gtk_box_pack_start_defaults ((GtkBox *) vbox, hbox); + + label = (GtkLabel *) gtk_label_new (""); + gtk_widget_show ((GtkWidget *) label); + gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) label); + + progress = (GtkProgressBar *) gtk_progress_bar_new (); + gtk_widget_show ((GtkWidget *) progress); + gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) progress); + + /* Prepare the message */ + vbox = gtk_vbox_new (FALSE, 12); + gtk_widget_show (vbox); + gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); + + w = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.0); + markup = g_strconcat ("", title ? title : _("Migration"), "", NULL); + gtk_label_set_markup (GTK_LABEL (w), markup); + gtk_box_pack_start (GTK_BOX (vbox), w, TRUE, TRUE, 0); + g_free (markup); + + w = gtk_label_new (desc); + gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.0); + gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); + gtk_box_pack_start (GTK_BOX (vbox), w, TRUE, TRUE, 0); + + /* Progress bar */ + w = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (vbox), w, TRUE, TRUE, 0); + + label = GTK_LABEL (gtk_label_new ("")); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0); + gtk_label_set_line_wrap (label, TRUE); + gtk_widget_show (GTK_WIDGET (label)); + gtk_box_pack_start (GTK_BOX (w), GTK_WIDGET (label), TRUE, TRUE, 0); + + progress = GTK_PROGRESS_BAR (gtk_progress_bar_new ()); + gtk_widget_show (GTK_WIDGET (progress)); + gtk_box_pack_start (GTK_BOX (w), GTK_WIDGET (progress), TRUE, TRUE, 0); + + gtk_container_add (GTK_CONTAINER (window), hbox); + gtk_widget_show_all (hbox); + gtk_widget_show (window); +} + +static void +em_migrate_close_progress_dialog (void) +{ + gtk_widget_destroy ((GtkWidget *) window); +} + +static void +em_migrate_set_folder_name (const gchar *folder_name) +{ + gchar *text; + + text = g_strdup_printf (_("Migrating '%s':"), folder_name); + gtk_label_set_text (label, text); + g_free (text); + + gtk_progress_bar_set_fraction (progress, 0.0); + while (gtk_events_pending ()) + gtk_main_iteration (); +} + +static void +em_migrate_set_progress (double percent) +{ + gchar text[5]; + + snprintf (text, sizeof (text), "%d%%", (gint) (percent * 100.0f)); + + gtk_progress_bar_set_fraction (progress, percent); + gtk_progress_bar_set_text (progress, text); + + while (gtk_events_pending ()) + gtk_main_iteration (); +} + +#ifndef G_OS_WIN32 + +static gboolean +is_mail_folder (const gchar *metadata) +{ + xmlNodePtr node; + xmlDocPtr doc; + gchar *type; + + if (!(doc = xmlParseFile (metadata))) { + g_warning ("Cannot parse `%s'", metadata); + return FALSE; + } + + if (!(node = xmlDocGetRootElement (doc))) { + g_warning ("`%s' corrupt: document contains no root node", metadata); + xmlFreeDoc (doc); + return FALSE; + } + + if (!node->name || strcmp ((gchar *)node->name, "efolder") != 0) { + g_warning ("`%s' corrupt: root node is not 'efolder'", metadata); + xmlFreeDoc (doc); + return FALSE; + } + + node = node->children; + while (node != NULL) { + if (node->name && !strcmp ((gchar *)node->name, "type")) { + type = (gchar *)xmlNodeGetContent (node); + if (!strcmp ((gchar *)type, "mail")) { + xmlFreeDoc (doc); + xmlFree (type); + + return TRUE; + } + + xmlFree (type); + + break; + } + + node = node->next; + } + + xmlFreeDoc (doc); + + return FALSE; +} + +static gboolean +get_local_et_expanded (const gchar *dirname) +{ + xmlNodePtr node; + xmlDocPtr doc; + struct stat st; + gchar *buf, *p; + gint thread_list; + + buf = g_strdup_printf ("%s/evolution/config/file:%s", g_get_home_dir (), dirname); + p = buf + strlen (g_get_home_dir ()) + strlen ("/evolution/config/file:"); + e_filename_make_safe (p); + + if (stat (buf, &st) == -1) { + g_free (buf); + return FALSE; + } + + if (!(doc = xmlParseFile (buf))) { + g_free (buf); + return FALSE; + } + + g_free (buf); + + if (!(node = xmlDocGetRootElement (doc)) || strcmp ((gchar *)node->name, "expanded_state") != 0) { + xmlFreeDoc (doc); + return FALSE; + } + + if (!(buf = (gchar *)xmlGetProp (node, (const guchar *)"default"))) { + xmlFreeDoc (doc); + return FALSE; + } + + thread_list = strcmp (buf, "0") == 0 ? 0 : 1; + xmlFree (buf); + + xmlFreeDoc (doc); + + return thread_list; +} + +static gchar * +get_local_store_uri (const gchar *dirname, gchar **namep, gint *indexp) +{ + gchar *name, *protocol, *metadata, *tmp; + gint index; + struct stat st; + xmlNodePtr node; + xmlDocPtr doc; + + metadata = g_build_filename(dirname, "local-metadata.xml", NULL); + + /* in 1.4, any errors are treated as defaults, this function cannot fail */ + + /* defaults */ + name = (gchar *) "mbox"; + protocol = (gchar *) "mbox"; + index = TRUE; + + if (stat (metadata, &st) == -1 || !S_ISREG (st.st_mode)) + goto nofile; + + doc = xmlParseFile(metadata); + if (doc == NULL) + goto nofile; + + node = doc->children; + if (strcmp((gchar *)node->name, "folderinfo")) + goto dodefault; + + for (node = node->children; node; node = node->next) { + if (node->name && !strcmp ((gchar *)node->name, "folder")) { + tmp = (gchar *)xmlGetProp (node, (const guchar *)"type"); + if (tmp) { + protocol = alloca(strlen(tmp)+1); + strcpy(protocol, tmp); + xmlFree(tmp); + } + tmp = (gchar *)xmlGetProp (node, (const guchar *)"name"); + if (tmp) { + name = alloca(strlen(tmp)+1); + strcpy(name, tmp); + xmlFree(tmp); + } + tmp = (gchar *)xmlGetProp (node, (const guchar *)"index"); + if (tmp) { + index = atoi(tmp); + xmlFree(tmp); + } + } + } +dodefault: + xmlFreeDoc (doc); +nofile: + g_free(metadata); + + *namep = g_strdup(name); + *indexp = index; + + return g_strdup_printf("%s:%s", protocol, dirname); +} + +#endif /* !G_OS_WIN32 */ + +enum { + CP_UNIQUE = 0, + CP_OVERWRITE, + CP_APPEND +}; + +static gint open_flags[3] = { + O_WRONLY | O_CREAT | O_TRUNC, + O_WRONLY | O_CREAT | O_TRUNC, + O_WRONLY | O_CREAT | O_APPEND, +}; + +static gboolean +cp (const gchar *src, const gchar *dest, gboolean show_progress, gint mode) +{ + guchar readbuf[65536]; + gssize nread, nwritten; + gint errnosav, readfd, writefd; + gsize total = 0; + struct stat st; + struct utimbuf ut; + + /* if the dest file exists and has content, abort - we don't + * want to corrupt their existing data */ + if (g_stat (dest, &st) == 0 && st.st_size > 0 && mode == CP_UNIQUE) { + errno = EEXIST; + return FALSE; + } + + if (g_stat (src, &st) == -1 + || (readfd = g_open (src, O_RDONLY | O_BINARY, 0)) == -1) + return FALSE; + + if ((writefd = g_open (dest, open_flags[mode] | O_BINARY, 0666)) == -1) { + errnosav = errno; + close (readfd); + errno = errnosav; + return FALSE; + } + + do { + do { + nread = read (readfd, readbuf, sizeof (readbuf)); + } while (nread == -1 && errno == EINTR); + + if (nread == 0) + break; + else if (nread < 0) + goto exception; + + do { + nwritten = write (writefd, readbuf, nread); + } while (nwritten == -1 && errno == EINTR); + + if (nwritten < nread) + goto exception; + + total += nwritten; + if (show_progress) + em_migrate_set_progress (((double) total) / ((double) st.st_size)); + } while (total < st.st_size); + + if (fsync (writefd) == -1) + goto exception; + + close (readfd); + if (close (writefd) == -1) + goto failclose; + + ut.actime = st.st_atime; + ut.modtime = st.st_mtime; + utime (dest, &ut); + chmod (dest, st.st_mode); + + return TRUE; + + exception: + + errnosav = errno; + close (readfd); + close (writefd); + errno = errnosav; + + failclose: + + errnosav = errno; + unlink (dest); + errno = errnosav; + + return FALSE; +} + +#ifndef G_OS_WIN32 + +static gboolean +cp_r (const gchar *src, const gchar *dest, const gchar *pattern, gint mode) +{ + GString *srcpath, *destpath; + struct dirent *dent; + gsize slen, dlen; + struct stat st; + DIR *dir; + + if (g_mkdir_with_parents (dest, 0777) == -1) + return FALSE; + + if (!(dir = opendir (src))) + return FALSE; + + srcpath = g_string_new (src); + g_string_append_c (srcpath, '/'); + slen = srcpath->len; + + destpath = g_string_new (dest); + g_string_append_c (destpath, '/'); + dlen = destpath->len; + + while ((dent = readdir (dir))) { + if (!strcmp (dent->d_name, ".") || !strcmp (dent->d_name, "..")) + continue; + + g_string_truncate (srcpath, slen); + g_string_truncate (destpath, dlen); + + g_string_append (srcpath, dent->d_name); + g_string_append (destpath, dent->d_name); + + if (stat (srcpath->str, &st) == -1) + continue; + + if (S_ISDIR (st.st_mode)) { + cp_r (srcpath->str, destpath->str, pattern, mode); + } else if (!pattern || !strcmp (dent->d_name, pattern)) { + cp (srcpath->str, destpath->str, FALSE, mode); + } + } + + closedir (dir); + + g_string_free (destpath, TRUE); + g_string_free (srcpath, TRUE); + + return TRUE; +} + +static void +mbox_build_filename (GString *path, const gchar *toplevel_dir, const gchar *full_name) +{ + const gchar *start, *inptr = full_name; + gint subdirs = 0; + + while (*inptr != '\0') { + if (*inptr == '/') + subdirs++; + inptr++; + } + + g_string_assign(path, toplevel_dir); + g_string_append_c (path, '/'); + + inptr = full_name; + while (*inptr != '\0') { + start = inptr; + while (*inptr != '/' && *inptr != '\0') + inptr++; + + g_string_append_len (path, start, inptr - start); + + if (*inptr == '/') { + g_string_append (path, ".sbd/"); + inptr++; + + /* strip extranaeous '/'s */ + while (*inptr == '/') + inptr++; + } + } +} + +static gboolean +em_migrate_folder(EMMigrateSession *session, const gchar *dirname, const gchar *full_name, GError **error) +{ + CamelFolder *old_folder = NULL, *new_folder = NULL; + CamelStore *local_store = NULL; + CamelException ex; + gchar *name, *uri; + GPtrArray *uids; + struct stat st; + gboolean thread_list; + gint index, i; + GString *src, *dest; + gboolean success = FALSE; + + camel_exception_init (&ex); + + src = g_string_new(""); + + g_string_printf(src, "%s/folder-metadata.xml", dirname); + if (stat (src->str, &st) == -1 + || !S_ISREG (st.st_mode) + || !is_mail_folder(src->str)) { + /* Not an evolution mail folder */ + g_string_free(src, TRUE); + return TRUE; + } + + dest = g_string_new(""); + uri = get_local_store_uri(dirname, &name, &index); + em_migrate_set_folder_name (full_name); + thread_list = get_local_et_expanded (dirname); + + /* Manually copy local mbox files, its much faster */ + if (!strncmp (uri, "mbox:", 5)) { + static const gchar *meta_ext[] = { ".summary", ".ibex.index", ".ibex.index.data" }; + gsize slen, dlen; + FILE *fp; + gchar *p; + gint mode; + + g_string_printf (src, "%s/%s", uri + 5, name); + mbox_build_filename (dest, ((CamelService *)session->store)->url->path, full_name); + p = strrchr (dest->str, '/'); + *p = '\0'; + + slen = src->len; + dlen = dest->len; + + if (g_mkdir_with_parents (dest->str, 0777) == -1 && errno != EEXIST) { + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Unable to create new folder `%s': %s"), + dest->str, g_strerror (errno)); + goto fatal; + } + + *p = '/'; + mode = CP_UNIQUE; + retry_copy: + if (!cp (src->str, dest->str, TRUE, mode)) { + if (errno == EEXIST) { + gint save = errno; + + switch (e_error_run(NULL, "mail:ask-migrate-existing", src->str, dest->str, NULL)) { + case GTK_RESPONSE_ACCEPT: + mode = CP_OVERWRITE; + goto retry_copy; + case GTK_RESPONSE_OK: + mode = CP_APPEND; + goto retry_copy; + case GTK_RESPONSE_REJECT: + goto ignore; + } + + errno = save; + } + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Unable to copy folder `%s' to `%s': %s"), + src->str, dest->str, g_strerror (errno)); + goto fatal; + } + ignore: + + /* create a .cmeta file specifying to index and/or thread the folder */ + g_string_truncate (dest, dlen); + g_string_append (dest, ".cmeta"); + if ((fp = fopen (dest->str, "w")) != NULL) { + gint fd = fileno (fp); + + /* write the magic string */ + if (fwrite ("CLMD", 4, 1, fp) != 1) + goto cmeta_err; + + /* write the version (1) */ + if (camel_file_util_encode_uint32 (fp, 1) == -1) + goto cmeta_err; + + /* write the meta count */ + if (camel_file_util_encode_uint32 (fp, thread_list ? 1 : 0) == -1) + goto cmeta_err; + + if (!thread_list) { + if (camel_file_util_encode_string (fp, "evolution:thread_list") == -1) + goto cmeta_err; + + if (camel_file_util_encode_string (fp, !thread_list ? "1" : "0") == -1) + goto cmeta_err; + } + + /* write the prop count (only prop is the index prop) */ + if (camel_file_util_encode_uint32 (fp, 1) == -1) + goto cmeta_err; + + /* write the index prop tag (== CAMEL_FOLDER_ARG_LAST|CAMEL_ARG_BOO) */ + if (camel_file_util_encode_uint32 (fp, CAMEL_FOLDER_ARG_LAST|CAMEL_ARG_BOO) == -1) + goto cmeta_err; + + /* write the index prop value */ + if (camel_file_util_encode_uint32 (fp, 1) == -1) + goto cmeta_err; + + fflush (fp); + + if (fsync (fd) == -1) { + cmeta_err: + fclose (fp); + unlink (dest->str); + } else { + fclose (fp); + } + } + + /* copy over the metadata files */ + for (i = 0; i < sizeof(meta_ext)/sizeof(meta_ext[0]); i++) { + g_string_truncate (src, slen); + g_string_truncate (dest, dlen); + + g_string_append (src, meta_ext[i]); + g_string_append (dest, meta_ext[i]); + cp (src->str, dest->str, FALSE, CP_OVERWRITE); + } + } else { + guint32 flags = CAMEL_STORE_FOLDER_CREATE; + + if (!(local_store = camel_session_get_store ((CamelSession *) session, uri, &ex)) + || !(old_folder = camel_store_get_folder (local_store, name, 0, &ex))) + goto fatal; + + flags |= (index ? CAMEL_STORE_FOLDER_BODY_INDEX : 0); + if (!(new_folder = camel_store_get_folder (session->store, full_name, flags, &ex))) + goto fatal; + + if (!thread_list) { + camel_object_meta_set (new_folder, "evolution:thread_list", !thread_list ? "1" : "0"); + camel_object_state_write (new_folder); + } + + uids = camel_folder_get_uids (old_folder); + for (i = 0; i < uids->len; i++) { + CamelMimeMessage *message; + CamelMessageInfo *info; + + if (!(info = camel_folder_get_message_info (old_folder, uids->pdata[i]))) + continue; + + if (!(message = camel_folder_get_message (old_folder, uids->pdata[i], &ex))) { + camel_folder_free_message_info (old_folder, info); + camel_folder_free_uids (old_folder, uids); + goto fatal; + } + + camel_folder_append_message (new_folder, message, info, NULL, &ex); + camel_folder_free_message_info (old_folder, info); + camel_object_unref (message); + + if (camel_exception_is_set (&ex)) + break; + + em_migrate_set_progress (((double) i + 1) / ((double) uids->len)); + } + + camel_folder_free_uids (old_folder, uids); + + if (camel_exception_is_set (&ex)) + goto fatal; + } + success = TRUE; +fatal: + g_free (uri); + g_free (name); + g_string_free(src, TRUE); + g_string_free(dest, TRUE); + if (local_store) + camel_object_unref(local_store); + if (old_folder) + camel_object_unref(old_folder); + if (new_folder) + camel_object_unref(new_folder); + + if (camel_exception_is_set (&ex)) { + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + "%s", camel_exception_get_description (&ex)); + camel_exception_clear (&ex); + } + + return success; +} + +static gboolean +em_migrate_dir (EMMigrateSession *session, const gchar *dirname, const gchar *full_name, GError **error) +{ + gchar *path; + DIR *dir; + struct stat st; + struct dirent *dent; + gboolean success = TRUE; + + if (!em_migrate_folder(session, dirname, full_name, error)) + return FALSE; + + /* no subfolders, not readable, don't care */ + path = g_strdup_printf ("%s/subfolders", dirname); + if (stat (path, &st) == -1 || !S_ISDIR (st.st_mode)) { + g_free (path); + return TRUE; + } + + if (!(dir = opendir (path))) { + g_free (path); + return TRUE; + } + + while (success && (dent = readdir (dir))) { + gchar *full_path; + gchar *name; + + if (dent->d_name[0] == '.') + continue; + + full_path = g_strdup_printf ("%s/%s", path, dent->d_name); + if (stat (full_path, &st) == -1 || !S_ISDIR (st.st_mode)) { + g_free (full_path); + continue; + } + + name = g_strdup_printf ("%s/%s", full_name, dent->d_name); + success = em_migrate_dir (session, full_path, name, error); + g_free (full_path); + g_free (name); + } + + closedir (dir); + + g_free (path); + + return success; +} + +static gboolean +em_migrate_local_folders_1_4 (EMMigrateSession *session, GError **error) +{ + struct dirent *dent; + struct stat st; + DIR *dir; + gboolean success = TRUE; + + if (!(dir = opendir (session->srcdir))) { + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Unable to scan for existing mailboxes at " + "`%s': %s"), session->srcdir, g_strerror (errno)); + return FALSE; + } + + em_migrate_setup_progress_dialog ( + _("Migrating Folders"), + _("The location and hierarchy of the Evolution mailbox " + "folders has changed since Evolution 1.x.\n\nPlease be " + "patient while Evolution migrates your folders...")); + + while (success && (dent = readdir (dir))) { + gchar *full_path; + + if (dent->d_name[0] == '.') + continue; + + full_path = g_strdup_printf ("%s/%s", session->srcdir, dent->d_name); + if (stat (full_path, &st) == -1 || !S_ISDIR (st.st_mode)) { + g_free (full_path); + continue; + } + + success = em_migrate_dir (session, full_path, dent->d_name, error); + g_free (full_path); + } + + closedir (dir); + + em_migrate_close_progress_dialog (); + + return success; +} + +static gchar * +upgrade_xml_uris_1_4 (const gchar *uri) +{ + gchar *path, *prefix, *p; + CamelURL *url; + + if (!strncmp (uri, "file:", 5)) { + url = camel_url_new (uri, NULL); + camel_url_set_protocol (url, "email"); + camel_url_set_user (url, "local"); + camel_url_set_host (url, "local"); + + prefix = g_build_filename (g_get_home_dir (), "evolution", "local", NULL); + if (strncmp (url->path, prefix, strlen (prefix)) != 0) { + /* uri is busticated - user probably copied from another user's home directory */ + camel_url_free (url); + g_free (prefix); + + return g_strdup (uri); + } + path = g_strdup (url->path + strlen (prefix)); + g_free (prefix); + + /* modify the path in-place */ + p = path + strlen (path) - 12; + while (p > path) { + if (!strncmp (p, "/subfolders/", 12)) + memmove (p, p + 11, strlen (p + 11) + 1); + + p--; + } + + camel_url_set_path (url, path); + g_free (path); + + path = camel_url_to_string (url, 0); + camel_url_free (url); + + return path; + } else { + return em_uri_from_camel (uri); + } +} + +static void +upgrade_vfolder_sources_1_4 (xmlDocPtr doc) +{ + xmlNodePtr root, node; + + if (!doc || !(root = xmlDocGetRootElement (doc))) + return; + + if (!root->name || strcmp ((gchar *)root->name, "filteroptions") != 0) { + /* root node is not , nothing to upgrade */ + return; + } + + if (!(node = xml_find_node (root, "ruleset"))) { + /* no ruleset node, nothing to upgrade */ + return; + } + + node = node->children; + while (node != NULL) { + if (node->name && !strcmp ((gchar *)node->name, "rule")) { + xmlNodePtr sources; + gchar *src; + + if (!(src = (gchar *)xmlGetProp (node, (const guchar *)"source"))) + src = (gchar *)xmlStrdup ((const guchar *)"local"); /* default to all local folders? */ + + xmlSetProp (node, (const guchar *)"source", (const guchar *)"incoming"); + + if (!(sources = xml_find_node (node, "sources"))) + sources = xmlNewChild (node, NULL, (const guchar *)"sources", NULL); + + xmlSetProp (sources, (const guchar *)"with", (guchar *)src); + xmlFree (src); + } + + node = node->next; + } +} + +static gchar * +get_nth_sig (gint id) +{ + ESignatureList *list; + ESignature *sig; + EIterator *iter; + gchar *uid = NULL; + gint i = 0; + + list = e_get_signature_list (); + iter = e_list_get_iterator ((EList *) list); + + while (e_iterator_is_valid (iter) && i < id) { + e_iterator_next (iter); + i++; + } + + if (i == id && e_iterator_is_valid (iter)) { + sig = (ESignature *) e_iterator_get (iter); + uid = g_strdup (sig->uid); + } + + g_object_unref (iter); + + return uid; +} + +static void +em_upgrade_accounts_1_4 (void) +{ + EAccountList *accounts; + EIterator *iter; + + if (!(accounts = e_get_account_list ())) + return; + + iter = e_list_get_iterator ((EList *) accounts); + while (e_iterator_is_valid (iter)) { + EAccount *account = (EAccount *) e_iterator_get (iter); + gchar *url; + + if (account->drafts_folder_uri) { + url = upgrade_xml_uris_1_4 (account->drafts_folder_uri); + g_free (account->drafts_folder_uri); + account->drafts_folder_uri = url; + } + + if (account->sent_folder_uri) { + url = upgrade_xml_uris_1_4 (account->sent_folder_uri); + g_free (account->sent_folder_uri); + account->sent_folder_uri = url; + } + + if (account->id->sig_uid && !strncmp (account->id->sig_uid, "::", 2)) { + gint sig_id; + + sig_id = strtol (account->id->sig_uid + 2, NULL, 10); + g_free (account->id->sig_uid); + account->id->sig_uid = get_nth_sig (sig_id); + } + + e_iterator_next (iter); + } + + g_object_unref (iter); + + e_account_list_save (accounts); +} + +static gboolean +em_migrate_pop_uid_caches_1_4 (const gchar *data_dir, GError **error) +{ + GString *oldpath, *newpath; + struct dirent *dent; + gsize olen, nlen; + gchar *cache_dir; + DIR *dir; + gboolean success = TRUE; + + /* Sigh, too many unique strings to translate, for cases which shouldn't ever happen */ + + /* open the old cache dir */ + cache_dir = g_build_filename (g_get_home_dir (), "evolution", "mail", "pop3", NULL); + if (!(dir = opendir (cache_dir))) { + if (errno == ENOENT) { + g_free(cache_dir); + return TRUE; + } + + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Unable to open old POP keep-on-server data " + "`%s': %s"), cache_dir, g_strerror (errno)); + g_free (cache_dir); + return FALSE; + } + + oldpath = g_string_new (cache_dir); + g_string_append_c (oldpath, '/'); + olen = oldpath->len; + g_free (cache_dir); + + cache_dir = g_build_filename (data_dir, "pop", NULL); + if (g_mkdir_with_parents (cache_dir, 0777) == -1) { + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Unable to create POP3 keep-on-server data " + "directory `%s': %s"), cache_dir, + g_strerror (errno)); + g_string_free (oldpath, TRUE); + g_free (cache_dir); + closedir (dir); + return FALSE; + } + + newpath = g_string_new (cache_dir); + g_string_append_c (newpath, '/'); + nlen = newpath->len; + g_free (cache_dir); + + while (success && (dent = readdir (dir))) { + if (strncmp (dent->d_name, "cache-pop:__", 12) != 0) + continue; + + g_string_truncate (oldpath, olen); + g_string_truncate (newpath, nlen); + + g_string_append (oldpath, dent->d_name); + g_string_append (newpath, dent->d_name + 12); + + /* strip the trailing '_' */ + g_string_truncate (newpath, newpath->len - 1); + + if (g_mkdir_with_parents (newpath->str, 0777) == -1 + || !cp(oldpath->str, (g_string_append(newpath, "/uid-cache"))->str, FALSE, CP_UNIQUE)) { + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Unable to copy POP3 keep-on-server data " + "`%s': %s"), oldpath->str, + g_strerror (errno)); + success = FALSE; + } + + } + + g_string_free (oldpath, TRUE); + g_string_free (newpath, TRUE); + + closedir (dir); + + return success; +} + +static gboolean +em_migrate_imap_caches_1_4 (const gchar *data_dir, GError **error) +{ + gchar *src, *dest; + struct stat st; + + src = g_build_filename (g_get_home_dir (), "evolution", "mail", "imap", NULL); + if (stat (src, &st) == -1 || !S_ISDIR (st.st_mode)) { + g_free (src); + return TRUE; + } + + dest = g_build_filename (data_dir, "imap", NULL); + + /* we don't care if this fails, it's only a cache... */ + cp_r (src, dest, "summary", CP_OVERWRITE); + + g_free (dest); + g_free (src); + + return TRUE; +} + +static gboolean +em_migrate_folder_expand_state_1_4 (const gchar *data_dir, GError **error) +{ + GString *srcpath, *destpath; + gsize slen, dlen, rlen; + gchar *evo14_mbox_root; + struct dirent *dent; + struct stat st; + DIR *dir; + + srcpath = g_string_new (g_get_home_dir ()); + g_string_append (srcpath, "/evolution/config"); + if (stat (srcpath->str, &st) == -1 || !S_ISDIR (st.st_mode)) { + g_string_free (srcpath, TRUE); + return TRUE; + } + + destpath = g_string_new (data_dir); + g_string_append (destpath, "/config"); + if (g_mkdir_with_parents (destpath->str, 0777) == -1 || !(dir = opendir (srcpath->str))) { + g_string_free (destpath, TRUE); + g_string_free (srcpath, TRUE); + return TRUE; + } + + g_string_append (srcpath, "/et-expanded-"); + slen = srcpath->len; + g_string_append (destpath, "/et-expanded-"); + dlen = destpath->len; + + evo14_mbox_root = g_build_filename (g_get_home_dir (), "evolution", "local", NULL); + e_filename_make_safe (evo14_mbox_root); + rlen = strlen (evo14_mbox_root); + evo14_mbox_root = g_realloc (evo14_mbox_root, rlen + 2); + evo14_mbox_root[rlen++] = '_'; + evo14_mbox_root[rlen] = '\0'; + + while ((dent = readdir (dir))) { + gchar *full_name, *inptr, *buf = NULL; + const gchar *filename; + GString *new; + + if (strncmp (dent->d_name, "et-expanded-", 12) != 0) + continue; + + if (!strncmp (dent->d_name + 12, "file:", 5)) { + /* need to munge the filename */ + inptr = dent->d_name + 17; + + if (!strncmp (inptr, evo14_mbox_root, rlen)) { + /* this should always be the case afaik... */ + inptr += rlen; + new = g_string_new ("mbox:"); + g_string_append_printf (new, "%s/local#", data_dir); + + full_name = g_strdup (inptr); + inptr = full_name + strlen (full_name) - 12; + while (inptr > full_name) { + if (!strncmp (inptr, "_subfolders_", 12)) + memmove (inptr, inptr + 11, strlen (inptr + 11) + 1); + + inptr--; + } + + g_string_append (new, full_name); + g_free (full_name); + + filename = buf = new->str; + g_string_free (new, FALSE); + e_filename_make_safe (buf); + } else { + /* but just in case... */ + filename = dent->d_name + 12; + } + } else { + /* no munging needed */ + filename = dent->d_name + 12; + } + + g_string_append (srcpath, dent->d_name + 12); + g_string_append (destpath, filename); + g_free (buf); + + cp (srcpath->str, destpath->str, FALSE, CP_UNIQUE); + + g_string_truncate (srcpath, slen); + g_string_truncate (destpath, dlen); + } + + closedir (dir); + + g_free (evo14_mbox_root); + g_string_free (destpath, TRUE); + g_string_free (srcpath, TRUE); + + return TRUE; +} + +static gboolean +em_migrate_folder_view_settings_1_4 (const gchar *data_dir, GError **error) +{ + GString *srcpath, *destpath; + gsize slen, dlen, rlen; + gchar *evo14_mbox_root; + struct dirent *dent; + struct stat st; + DIR *dir; + + srcpath = g_string_new (g_get_home_dir ()); + g_string_append (srcpath, "/evolution/views/mail"); + if (stat (srcpath->str, &st) == -1 || !S_ISDIR (st.st_mode)) { + g_string_free (srcpath, TRUE); + return TRUE; + } + + destpath = g_string_new (data_dir); + g_string_append (destpath, "/views"); + if (g_mkdir_with_parents (destpath->str, 0777) == -1 || !(dir = opendir (srcpath->str))) { + g_string_free (destpath, TRUE); + g_string_free (srcpath, TRUE); + return TRUE; + } + + g_string_append_c (srcpath, '/'); + slen = srcpath->len; + g_string_append_c (destpath, '/'); + dlen = destpath->len; + + evo14_mbox_root = g_build_filename (g_get_home_dir (), "evolution", "local", NULL); + e_filename_make_safe (evo14_mbox_root); + rlen = strlen (evo14_mbox_root); + evo14_mbox_root = g_realloc (evo14_mbox_root, rlen + 2); + evo14_mbox_root[rlen++] = '_'; + evo14_mbox_root[rlen] = '\0'; + + while ((dent = readdir (dir))) { + gchar *full_name, *inptr, *buf = NULL; + const gchar *filename, *ext; + gsize prelen = 0; + GString *new; + + if (dent->d_name[0] == '.') + continue; + + if (!(ext = strrchr (dent->d_name, '.'))) + continue; + + if (!strcmp (ext, ".galview") || !strcmp ((gchar *)dent->d_name, "galview.xml")) { + /* just copy the file */ + filename = dent->d_name; + goto copy; + } else if (strcmp (ext, ".xml") != 0) { + continue; + } + + if (!strncmp ((const gchar *)dent->d_name, "current_view-", 13)) { + prelen = 13; + } else if (!strncmp ((const gchar *)dent->d_name, "custom_view-", 12)) { + prelen = 12; + } else { + /* huh? wtf is this file? */ + continue; + } + + if (!strncmp (dent->d_name + prelen, "file:", 5)) { + /* need to munge the filename */ + inptr = dent->d_name + prelen + 5; + + if (!strncmp (inptr, evo14_mbox_root, rlen)) { + /* this should always be the case afaik... */ + inptr += rlen; + new = g_string_new ("mbox:"); + g_string_append_printf (new, "%s/local#", data_dir); + + full_name = g_strdup (inptr); + inptr = full_name + strlen (full_name) - 12; + while (inptr > full_name) { + if (!strncmp (inptr, "_subfolders_", 12)) + memmove (inptr, inptr + 11, strlen (inptr + 11) + 1); + + inptr--; + } + + g_string_append (new, full_name); + g_free (full_name); + + filename = buf = new->str; + g_string_free (new, FALSE); + e_filename_make_safe (buf); + } else { + /* but just in case... */ + filename = dent->d_name + prelen; + } + } else { + /* no munging needed */ + filename = dent->d_name + prelen; + } + + copy: + g_string_append (srcpath, dent->d_name); + if (prelen > 0) + g_string_append_len (destpath, dent->d_name, prelen); + g_string_append (destpath, filename); + g_free (buf); + + cp (srcpath->str, destpath->str, FALSE, CP_UNIQUE); + + g_string_truncate (srcpath, slen); + g_string_truncate (destpath, dlen); + } + + closedir (dir); + + g_free (evo14_mbox_root); + g_string_free (destpath, TRUE); + g_string_free (srcpath, TRUE); + + return TRUE; +} + +#define SUBFOLDER_DIR_NAME "subfolders" +#define SUBFOLDER_DIR_NAME_LEN 10 + +static gchar * +e_path_to_physical (const gchar *prefix, const gchar *vpath) +{ + const gchar *p, *newp; + gchar *dp; + gchar *ppath; + gint ppath_len; + gint prefix_len; + + while (*vpath == '/') + vpath++; + if (!prefix) + prefix = ""; + + /* Calculate the length of the real path. */ + ppath_len = strlen (vpath); + ppath_len++; /* For the ending zero. */ + + prefix_len = strlen (prefix); + ppath_len += prefix_len; + ppath_len++; /* For the separating slash. */ + + /* Take account of the fact that we need to translate every + * separator into `subfolders/'. + */ + p = vpath; + while (1) { + newp = strchr (p, '/'); + if (newp == NULL) + break; + + ppath_len += SUBFOLDER_DIR_NAME_LEN; + ppath_len++; /* For the separating slash. */ + + /* Skip consecutive slashes. */ + while (*newp == '/') + newp++; + + p = newp; + }; + + ppath = g_malloc (ppath_len); + dp = ppath; + + memcpy (dp, prefix, prefix_len); + dp += prefix_len; + *(dp++) = '/'; + + /* Copy the mangled path. */ + p = vpath; + while (1) { + newp = strchr (p, '/'); + if (newp == NULL) { + strcpy (dp, p); + break; + } + + memcpy (dp, p, newp - p + 1); /* `+ 1' to copy the slash too. */ + dp += newp - p + 1; + + memcpy (dp, SUBFOLDER_DIR_NAME, SUBFOLDER_DIR_NAME_LEN); + dp += SUBFOLDER_DIR_NAME_LEN; + + *(dp++) = '/'; + + /* Skip consecutive slashes. */ + while (*newp == '/') + newp++; + + p = newp; + } + + return ppath; +} + +static gboolean +em_migrate_imap_cmeta_1_4(const gchar *data_dir, GError **error) +{ + GConfClient *gconf; + GSList *paths, *p; + EAccountList *accounts; + const EAccount *account; + + if (!(accounts = e_get_account_list ())) + return TRUE; + + gconf = gconf_client_get_default(); + paths = gconf_client_get_list(gconf, "/apps/evolution/shell/offline/folder_paths", GCONF_VALUE_STRING, NULL); + for (p = paths;p;p = g_slist_next(p)) { + gchar *name, *path; + + name = p->data; + if (*name) + name++; + path = strchr(name, '/'); + if (path) { + *path++ = 0; + account = e_account_list_find(accounts, E_ACCOUNT_FIND_NAME, name); + if (account && !strncmp(account->source->url, "imap:", 5)) { + CamelURL *url = camel_url_new(account->source->url, NULL); + + if (url) { + gchar *dir, *base; + + base = g_strdup_printf("%s/imap/%s@%s/folders", + data_dir, + url->user?url->user:"", + url->host?url->host:""); + + dir = e_path_to_physical(base, path); + if (g_mkdir_with_parents(dir, 0777) == 0) { + gchar *cmeta; + FILE *fp; + + cmeta = g_build_filename(dir, "cmeta", NULL); + fp = fopen(cmeta, "w"); + if (fp) { + /* header/version */ + fwrite("CLMD", 4, 1, fp); + camel_file_util_encode_uint32(fp, 1); + /* meta count, do we have any metadata? */ + camel_file_util_encode_uint32(fp, 0); + /* prop count */ + camel_file_util_encode_uint32(fp, 1); + /* sync offline property */ + camel_file_util_encode_uint32(fp, CAMEL_DISCO_FOLDER_OFFLINE_SYNC); + camel_file_util_encode_uint32(fp, 1); + fclose(fp); + } else { + g_warning("couldn't create imap folder cmeta file '%s'", cmeta); + } + g_free(cmeta); + } else { + g_warning("couldn't create imap folder directory '%s'", dir); + } + g_free(dir); + g_free(base); + camel_url_free(url); + } + } else + g_warning("can't find offline folder '%s' '%s'", name, path); + } + g_free(p->data); + } + g_slist_free(paths); + g_object_unref(gconf); + + /* we couldn't care less if this doesn't work */ + + return TRUE; +} + +static void +remove_system_searches(xmlDocPtr searches) +{ + xmlNodePtr node; + + /* in pre 2.0, system searches were stored in the user + * searches.xml file with the source set to 'demand'. In 2.0+ + * the system searches are stored in the system + * searchtypes.xml file instead */ + + node = xmlDocGetRootElement(searches); + if (!node->name || strcmp((gchar *)node->name, "filteroptions")) + return; + + if (!(node = xml_find_node(node, "ruleset"))) + return; + + node = node->children; + while (node != NULL) { + xmlNodePtr nnode = node->next; + + if (node->name && !strcmp ((gchar *)node->name, "rule")) { + gchar *src; + + src = (gchar *)xmlGetProp(node, (guchar *)"source"); + if (src && !strcmp((gchar *)src, "demand")) { + xmlUnlinkNode(node); + xmlFreeNodeList(node); + } + xmlFree (src); + } + + node = nnode; + } +} + +static gboolean +em_migrate_1_4 (const gchar *data_dir, xmlDocPtr filters, xmlDocPtr vfolders, GError **error) +{ + EMMigrateSession *session; + CamelException lex; + struct stat st; + gchar *path; + xmlDocPtr searches; + + camel_init (data_dir, TRUE); + camel_provider_init(); + session = (EMMigrateSession *) em_migrate_session_new (data_dir); + + session->srcdir = g_build_filename (g_get_home_dir (), "evolution", "local", NULL); + + path = g_strdup_printf ("mbox:%s/.evolution/mail/local", g_get_home_dir ()); + if (stat (path + 5, &st) == -1) { + if (errno != ENOENT || g_mkdir_with_parents (path + 5, 0777) == -1) { + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Failed to create local mail storage " + "`%s': %s"), path + 5, g_strerror (errno)); + g_free (session->srcdir); + camel_object_unref (session); + g_free (path); + return FALSE; + } + } + + camel_exception_init (&lex); + if (!(session->store = camel_session_get_store ((CamelSession *) session, path, &lex))) { + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Failed to create local mail storage `%s': %s"), + path, lex.desc); + g_free (session->srcdir); + camel_object_unref (session); + camel_exception_clear (&lex); + g_free (path); + return FALSE; + } + g_free (path); + + if (!em_migrate_local_folders_1_4 (session, error)) + return FALSE; + + camel_object_unref (session->store); + g_free (session->srcdir); + + camel_object_unref (session); + + em_upgrade_accounts_1_4(); + + upgrade_xml_uris(filters, upgrade_xml_uris_1_4); + upgrade_vfolder_sources_1_4(vfolders); + upgrade_xml_uris(vfolders, upgrade_xml_uris_1_4); + + path = g_build_filename(g_get_home_dir(), "evolution", NULL); + searches = emm_load_xml(path, "searches.xml"); + g_free(path); + if (searches) { + remove_system_searches(searches); + emm_save_xml(searches, data_dir, "searches.xml"); + xmlFreeDoc(searches); + } + + if (!em_migrate_pop_uid_caches_1_4 (data_dir, error)) + return FALSE; + + /* these are non-fatal */ + em_migrate_imap_caches_1_4 (data_dir, error); + g_clear_error (error); + em_migrate_folder_expand_state_1_4 (data_dir, error); + g_clear_error (error); + em_migrate_folder_view_settings_1_4 (data_dir, error); + g_clear_error (error); + em_migrate_imap_cmeta_1_4 (data_dir, error); + g_clear_error (error); + + return TRUE; +} + +static void +em_update_accounts_2_11 (void) +{ + EAccountList *accounts; + EIterator *iter; + gboolean changed = FALSE; + + if (!(accounts = e_get_account_list ())) + return; + + iter = e_list_get_iterator ((EList *) accounts); + while (e_iterator_is_valid (iter)) { + EAccount *account = (EAccount *) e_iterator_get (iter); + + if (g_str_has_prefix (account->source->url, "spool://")) { + if (g_file_test (account->source->url + 8, G_FILE_TEST_IS_DIR)) { + gchar *str = g_strdup_printf ("spooldir://%s", account->source->url + 8); + + g_free (account->source->url); + account->source->url = str; + changed = TRUE; + } + } + + e_iterator_next (iter); + } + + g_object_unref (iter); + + if (changed) + e_account_list_save (accounts); +} + +#endif /* !G_OS_WIN32 */ + +static gboolean +emm_setup_initial(const gchar *data_dir) +{ + GDir *dir; + const gchar *d; + gchar *local = NULL, *base; + const gchar * const *language_names; + + /* special-case - this means brand new install of evolution */ + /* FIXME: create default folders and stuff... */ + + d(printf("Setting up initial mail tree\n")); + + base = g_build_filename(data_dir, "local", NULL); + if (g_mkdir_with_parents(base, 0777) == -1 && errno != EEXIST) { + g_free(base); + return FALSE; + } + + /* e.g. try en-AU then en, etc */ + language_names = g_get_language_names (); + while (*language_names != NULL) { + local = g_build_filename ( + EVOLUTION_PRIVDATADIR, "default", + *language_names, "mail", "local", NULL); + if (g_file_test (local, G_FILE_TEST_EXISTS)) + break; + g_free (local); + language_names++; + } + + /* Make sure we found one. */ + g_return_val_if_fail (*language_names != NULL, FALSE); + + dir = g_dir_open(local, 0, NULL); + if (dir) { + while ((d = g_dir_read_name(dir))) { + gchar *src, *dest; + + src = g_build_filename(local, d, NULL); + dest = g_build_filename(base, d, NULL); + + cp(src, dest, FALSE, CP_UNIQUE); + g_free(dest); + g_free(src); + } + g_dir_close(dir); + } + + g_free(local); + g_free(base); + + return TRUE; +} + +static gboolean +is_in_plugs_list (GSList *list, const gchar *value) +{ + GSList *l; + + for (l = list; l; l = l->next) { + if (l->data && !strcmp (l->data, value)) + return TRUE; + } + + return FALSE; +} + +/* + * em_update_message_notify_settings_2_21 + * DBus plugin and sound email notification was merged to mail-notification plugin, + * so move these options to new locations. + */ +static void +em_update_message_notify_settings_2_21 (void) +{ + GConfClient *client; + GConfValue *is_key; + gboolean dbus, status; + GSList *list; + gchar *str; + gint val; + + client = gconf_client_get_default (); + + is_key = gconf_client_get (client, "/apps/evolution/eplugin/mail-notification/dbus-enabled", NULL); + if (is_key) { + /* already migrated, so do not migrate again */ + gconf_value_free (is_key); + g_object_unref (client); + + return; + } + + gconf_client_set_bool (client, "/apps/evolution/eplugin/mail-notification/status-blink-icon", + gconf_client_get_bool (client, "/apps/evolution/mail/notification/blink-status-icon", NULL), NULL); + gconf_client_set_bool (client, "/apps/evolution/eplugin/mail-notification/status-notification", + gconf_client_get_bool (client, "/apps/evolution/mail/notification/notification", NULL), NULL); + + list = gconf_client_get_list (client, "/apps/evolution/eplugin/disabled", GCONF_VALUE_STRING, NULL); + dbus = !is_in_plugs_list (list, "org.gnome.evolution.new_mail_notify"); + status = !is_in_plugs_list (list, "org.gnome.evolution.mail_notification"); + + gconf_client_set_bool (client, "/apps/evolution/eplugin/mail-notification/dbus-enabled", dbus, NULL); + gconf_client_set_bool (client, "/apps/evolution/eplugin/mail-notification/status-enabled", status, NULL); + + if (!status) { + /* enable this plugin, because it holds all those other things */ + GSList *plugins, *l; + + plugins = e_plugin_list_plugins (); + + for (l = plugins; l; l = l->next) { + EPlugin *p = l->data; + + if (p && p->id && !strcmp (p->id, "org.gnome.evolution.mail_notification")) { + e_plugin_enable (p, 1); + break; + } + } + + g_slist_foreach (plugins, (GFunc)g_object_unref, NULL); + g_slist_free (plugins); + } + + g_slist_foreach (list, (GFunc) g_free, NULL); + g_slist_free (list); + + val = gconf_client_get_int (client, "/apps/evolution/mail/notify/type", NULL); + gconf_client_set_bool (client, "/apps/evolution/eplugin/mail-notification/sound-enabled", val == 1 || val == 2, NULL); + gconf_client_set_bool (client, "/apps/evolution/eplugin/mail-notification/sound-beep", val == 0 || val == 1, NULL); + + str = gconf_client_get_string (client, "/apps/evolution/mail/notify/sound", NULL); + gconf_client_set_string (client, "/apps/evolution/eplugin/mail-notification/sound-file", str ? str : "", NULL); + g_free (str); + + g_object_unref (client); +} + +/* fixing typo in SpamAssassin name */ +static void +em_update_sa_junk_setting_2_23 (void) +{ + GConfClient *client; + GConfValue *key; + + client = gconf_client_get_default (); + + key = gconf_client_get (client, "/apps/evolution/mail/junk/default_plugin", NULL); + if (key) { + const gchar *str = gconf_value_get_string (key); + + if (str && strcmp (str, "Spamassasin") == 0) + gconf_client_set_string (client, "/apps/evolution/mail/junk/default_plugin", "SpamAssassin", NULL); + + gconf_value_free (key); + g_object_unref (client); + + return; + } + + g_object_unref (client); +} + +static gboolean +update_progress_in_main_thread (double *progress) +{ + em_migrate_set_progress (*progress); + return FALSE; +} + +static void +migrate_folders(CamelStore *store, gboolean is_local, CamelFolderInfo *fi, const gchar *acc, CamelException *ex, gboolean *done, gint *nth_folder, gint total_folders) +{ + CamelFolder *folder; + + while (fi) { + double progress; + gchar *tmp; + + *nth_folder = *nth_folder + 1; + + tmp = g_strdup_printf ("%s/%s", acc, fi->full_name); + em_migrate_set_folder_name (tmp); + g_free (tmp); + + progress = (double) (*nth_folder) / total_folders; + g_idle_add ((GSourceFunc) update_progress_in_main_thread, &progress); + + if (is_local) + folder = camel_store_get_folder (store, fi->full_name, CAMEL_STORE_IS_MIGRATING, ex); + else + folder = camel_store_get_folder (store, fi->full_name, 0, ex); + + if (folder != NULL) + camel_folder_summary_migrate_infos (folder->summary); + migrate_folders(store, is_local, fi->child, acc, ex, done, nth_folder, total_folders); + fi = fi->next; + } + + if ((*nth_folder) == (total_folders - 1)) + *done = TRUE; +} + +/* This could be in CamelStore.ch */ +static void +count_folders (CamelFolderInfo *fi, gint *count) +{ + while (fi) { + *count = *count + 1; + count_folders (fi->child, count); + fi = fi->next; + } +} + +static CamelStore * +setup_local_store (EShellBackend *shell_backend, + EMMigrateSession *session) +{ + CamelURL *url; + const gchar *data_dir; + gchar *tmp; + CamelStore *store; + + url = camel_url_new("mbox:", NULL); + data_dir = e_shell_backend_get_data_dir (shell_backend); + tmp = g_build_filename (data_dir, "local", NULL); + camel_url_set_path(url, tmp); + g_free(tmp); + tmp = camel_url_to_string(url, 0); + store = (CamelStore *)camel_session_get_service(CAMEL_SESSION (session), tmp, CAMEL_PROVIDER_STORE, NULL); + g_free(tmp); + + return store; +} + +struct migrate_folders_to_db_structure { + gchar *account_name; + CamelException ex; + CamelStore *store; + CamelFolderInfo *info; + gboolean done; + gboolean is_local_store; +}; + +static void +migrate_folders_to_db_thread (struct migrate_folders_to_db_structure *migrate_dbs) +{ + gint num_of_folders = 0, nth_folder = 0; + count_folders (migrate_dbs->info, &num_of_folders); + migrate_folders (migrate_dbs->store, migrate_dbs->is_local_store, migrate_dbs->info, + migrate_dbs->account_name, &(migrate_dbs->ex), &(migrate_dbs->done), + &nth_folder, num_of_folders); +} + +static void +migrate_to_db (EShellBackend *shell_backend) +{ + EMMigrateSession *session; + EAccountList *accounts; + EIterator *iter; + gint i=0, len; + CamelStore *store = NULL; + CamelFolderInfo *info; + const gchar *data_dir; + + if (!(accounts = e_get_account_list ())) + return; + + iter = e_list_get_iterator ((EList *) accounts); + len = e_list_length ((EList *) accounts); + + data_dir = e_shell_backend_get_data_dir (shell_backend); + session = (EMMigrateSession *) em_migrate_session_new (data_dir); + camel_session_set_online ((CamelSession *) session, FALSE); + em_migrate_setup_progress_dialog ( + _("Migrating Folders"), + _("The summary format of the Evolution mailbox " + "folders has been moved to SQLite since Evolution 2.24.\n\nPlease be " + "patient while Evolution migrates your folders...")); + + em_migrate_set_progress ( (double)i/(len+1)); + store = setup_local_store (shell_backend, session); + info = camel_store_get_folder_info (store, NULL, CAMEL_STORE_FOLDER_INFO_RECURSIVE|CAMEL_STORE_FOLDER_INFO_FAST|CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, NULL); + if (info) { + GThread *thread; + struct migrate_folders_to_db_structure migrate_dbs; + + if (g_str_has_suffix (((CamelService *)store)->url->path, ".evolution/mail/local")) + migrate_dbs.is_local_store = TRUE; + else + migrate_dbs.is_local_store = FALSE; + camel_exception_init (&migrate_dbs.ex); + migrate_dbs.account_name = _("On This Computer"); + migrate_dbs.info = info; + migrate_dbs.store = store; + migrate_dbs.done = FALSE; + + thread = g_thread_create ((GThreadFunc) migrate_folders_to_db_thread, &migrate_dbs, TRUE, NULL); + while (!migrate_dbs.done) + g_main_context_iteration (NULL, TRUE); + } + i++; + em_migrate_set_progress ( (double)i/(len+1)); + + + while (e_iterator_is_valid (iter)) { + EAccount *account = (EAccount *) e_iterator_get (iter); + EAccountService *service; + const gchar *name; + + + service = account->source; + name = account->name; + em_migrate_set_progress ( (double)i/(len+1)); + if (account->enabled + && service->url != NULL + && service->url[0] + && strncmp(service->url, "mbox:", 5) != 0) { + + CamelException ex; + + camel_exception_init (&ex); + e_mail_store_add_by_uri (service->url, name); + + store = (CamelStore *) camel_session_get_service (CAMEL_SESSION (session), service->url, CAMEL_PROVIDER_STORE, &ex); + info = camel_store_get_folder_info (store, NULL, CAMEL_STORE_FOLDER_INFO_RECURSIVE|CAMEL_STORE_FOLDER_INFO_FAST|CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, &ex); + if (info) { + GThread *thread; + struct migrate_folders_to_db_structure migrate_dbs; + + migrate_dbs.ex = ex; + migrate_dbs.account_name = account->name; + migrate_dbs.info = info; + migrate_dbs.store = store; + migrate_dbs.done = FALSE; + + thread = g_thread_create ((GThreadFunc) migrate_folders_to_db_thread, &migrate_dbs, TRUE, NULL); + while (!migrate_dbs.done) + g_main_context_iteration (NULL, TRUE); + } else + printf("%s:%s: failed to get folder infos \n", G_STRLOC, G_STRFUNC); + camel_exception_clear(&ex); + + } + i++; + e_iterator_next (iter); + + } + + //camel_session_set_online ((CamelSession *) session, TRUE); + + g_object_unref (iter); + em_migrate_close_progress_dialog (); + + g_object_unref (session); +} + +gboolean +e_mail_shell_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint micro, + GError **error) +{ + struct stat st; + const gchar *data_dir; + gchar *path; + + /* make sure ~/.evolution/mail exists */ + data_dir = e_shell_backend_get_data_dir (shell_backend); + if (g_stat (data_dir, &st) == -1) { + if (errno != ENOENT || g_mkdir_with_parents (data_dir, 0777) == -1) { + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Unable to create local mail folders at " + "`%s': %s"), data_dir, g_strerror (errno)); + return FALSE; + } + } + + if (major == 0) + return emm_setup_initial (data_dir); + + if (major == 1 && minor < 5) { +#ifndef G_OS_WIN32 + xmlDocPtr config_xmldb = NULL, filters, vfolders; + + path = g_build_filename (g_get_home_dir (), "evolution", NULL); + if (minor <= 2 && !(config_xmldb = emm_load_xml (path, "config.xmldb"))) { + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Unable to read settings from previous " + "Evolution install, `evolution/config.xmldb' " + "does not exist or is corrupt.")); + return FALSE; + } + filters = emm_load_xml (path, "filters.xml"); + vfolders = emm_load_xml (path, "vfolders.xml"); + g_free (path); + + if (minor == 0) { + if (!em_migrate_1_0 (data_dir, config_xmldb, filters, vfolders, error)) { + xmlFreeDoc (config_xmldb); + xmlFreeDoc (filters); + xmlFreeDoc (vfolders); + return FALSE; + } + } + + if (minor <= 2) { + if (!em_migrate_1_2 (data_dir, config_xmldb, filters, vfolders, error)) { + xmlFreeDoc (config_xmldb); + xmlFreeDoc (filters); + xmlFreeDoc (vfolders); + return FALSE; + } + + xmlFreeDoc (config_xmldb); + } + + if (minor <= 4) { + if (!em_migrate_1_4 (data_dir, filters, vfolders, error)) { + xmlFreeDoc (filters); + xmlFreeDoc (vfolders); + return FALSE; + } + } + + if (filters) { + emm_save_xml (filters, path, "filters.xml"); + xmlFreeDoc (filters); + } + + if (vfolders) { + emm_save_xml (vfolders, path, "vfolders.xml"); + xmlFreeDoc (vfolders); + } + + g_free (path); +#else + g_error ("Upgrading from ancient versions not supported on Windows"); +#endif + } + + if (major < 2 || (major == 2 && minor < 12)) { +#ifndef G_OS_WIN32 + em_update_accounts_2_11 (); +#else + g_error ("Upgrading from ancient versions not supported on Windows"); +#endif + } + + + if (major < 2 || (major == 2 && minor < 22)) + em_update_message_notify_settings_2_21 (); + + if (major < 2 || (major == 2 && minor < 24)) { + em_update_sa_junk_setting_2_23 (); + migrate_to_db (shell_backend); + } + + return TRUE; +} diff --git a/modules/mail/e-mail-shell-migrate.h b/modules/mail/e-mail-shell-migrate.h new file mode 100644 index 0000000000..8f3057ec0d --- /dev/null +++ b/modules/mail/e-mail-shell-migrate.h @@ -0,0 +1,38 @@ +/* + * e-mail-shell-migrate.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_SHELL_BACKEND_MIGRATE_H +#define E_MAIL_SHELL_BACKEND_MIGRATE_H + +#include +#include + +G_BEGIN_DECLS + +gboolean e_mail_shell_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint micro, + GError **error); + +G_END_DECLS + +#endif /* E_MAIL_SHELL_BACKEND_MIGRATE_H */ diff --git a/modules/mail/e-mail-shell-settings.c b/modules/mail/e-mail-shell-settings.c new file mode 100644 index 0000000000..8237924e3c --- /dev/null +++ b/modules/mail/e-mail-shell-settings.c @@ -0,0 +1,521 @@ +/* + * e-mail-shell-settings.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-shell-settings.h" + +#include +#include + +#include "e-util/e-signature-list.h" +#include "mail/e-mail-label-list-store.h" +#include "mail/mail-session.h" + +void +e_mail_shell_settings_init (EShell *shell) +{ + EShellSettings *shell_settings; + gpointer object; + + shell_settings = e_shell_get_shell_settings (shell); + + /* XXX Default values should match the GConf schema. + * Yes it's redundant, but we're stuck with GConf. */ + + /*** Global Objects ***/ + + e_shell_settings_install_property ( + g_param_spec_object ( + "mail-label-list-store", + NULL, + NULL, + E_TYPE_MAIL_LABEL_LIST_STORE, + G_PARAM_READWRITE)); + + object = e_mail_label_list_store_new (); + e_shell_settings_set_object ( + shell_settings, "mail-label-list-store", object); + g_object_unref (object); + + e_shell_settings_install_property ( + g_param_spec_pointer ( + "mail-session", + NULL, + NULL, + G_PARAM_READWRITE)); + + camel_object_ref (session); + e_shell_settings_set_pointer ( + shell_settings, "mail-session", session); + + /*** Mail Preferences ***/ + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-address-compress", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-address-compress", + "/apps/evolution/mail/display/address_compress"); + + e_shell_settings_install_property ( + g_param_spec_int ( + "mail-address-count", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-address-count", + "/apps/evolution/mail/display/address_count"); + + e_shell_settings_install_property ( + g_param_spec_string ( + "mail-charset-default", + NULL, + NULL, + NULL, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-charset-default", + "/apps/evolution/mail/display/charset"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-check-for-junk", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-check-for-junk", + "/apps/evolution/mail/junk/check_incoming"); + + e_shell_settings_install_property ( + g_param_spec_string ( + "mail-citation-color", + NULL, + NULL, + "#737373", + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-citation-color", + "/apps/evolution/mail/display/citation_colour"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-confirm-expunge", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-confirm-expunge", + "/apps/evolution/mail/prompts/expunge"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-confirm-unwanted-html", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-confirm-unwanted-html", + "/apps/evolution/mail/prompts/unwanted_html"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-empty-trash-on-exit", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-empty-trash-on-exit", + "/apps/evolution/mail/trash/empty_on_exit"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-enable-search-folders", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-enable-search-folders", + "/apps/evolution/mail/display/enable_vfolders"); + + e_shell_settings_install_property ( + g_param_spec_string ( + "mail-font-monospace", + NULL, + NULL, + "", + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-font-monospace", + "/apps/evolution/mail/display/fonts/monospace"); + + e_shell_settings_install_property ( + g_param_spec_string ( + "mail-font-variable", + NULL, + NULL, + "", + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-font-variable", + "/apps/evolution/mail/display/fonts/variable"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-force-message-limit", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-force-message-limit", + "/apps/evolution/mail/display/force_message_limit"); + + /* This value corresponds to MailConfigForwardStyle enum. */ + e_shell_settings_install_property ( + g_param_spec_int ( + "mail-forward-style", + NULL, + NULL, + 0, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-forward-style", + "/apps/evolution/mail/format/forward_style"); + + /* This value corresponds to MailConfigHTTPMode enum. */ + e_shell_settings_install_property ( + g_param_spec_int ( + "mail-image-loading-policy", + NULL, + NULL, + 0, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-image-loading-policy", + "/apps/evolution/mail/display/load_http_images"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-magic-spacebar", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-magic-spacebar", + "/apps/evolution/mail/display/magic_spacebar"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-mark-citations", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-mark-citations", + "/apps/evolution/mail/display/mark_citations"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-mark-seen", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-mark-seen", + "/apps/evolution/mail/display/mark_seen"); + + e_shell_settings_install_property ( + g_param_spec_int ( + "mail-mark-seen-timeout", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-mark-seen-timeout", + "/apps/evolution/mail/display/mark_seen_timeout"); + + e_shell_settings_install_property ( + g_param_spec_int ( + "mail-message-text-part-limit", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-message-text-part-limit", + "/apps/evolution/mail/display/message_text_part_limit"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-only-local-photos", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-only-local-photos", + "/apps/evolution/mail/display/photo_local"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-prompt-delete-in-vfolder", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-prompt-delete-in-vfolder", + "/apps/evolution/mail/prompts/delete_in_vfolder"); + + /* This value corresponds to MailConfigReplyStyle enum, + * but the ordering of the combo box items in preferences + * has changed. We use transformation functions there. */ + e_shell_settings_install_property ( + g_param_spec_int ( + "mail-reply-style", + NULL, + NULL, + 0, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-reply-style", + "/apps/evolution/mail/format/reply_style"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-show-animated-images", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-show-animated-images", + "/apps/evolution/mail/display/animated_images"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-show-sender-photo", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-show-sender-photo", + "/apps/evolution/mail/display/sender_photo"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-use-custom-fonts", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-use-custom-fonts", + "/apps/evolution/mail/display/fonts/use_custom"); + + + /*** Composer Preferences ***/ + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-format-html", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-format-html", + "/apps/evolution/mail/composer/send_html"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-inline-spelling", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-inline-spelling", + "/apps/evolution/mail/composer/inline_spelling"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-magic-links", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-magic-links", + "/apps/evolution/mail/composer/magic_links"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-magic-smileys", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-magic-smileys", + "/apps/evolution/mail/composer/magic_smileys"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-outlook-filenames", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-outlook-filenames", + "/apps/evolution/mail/composer/outlook_filenames"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-prompt-only-bcc", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-prompt-only-bcc", + "/apps/evolution/mail/prompts/only_bcc"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-prompt-empty-subject", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-prompt-empty-subject", + "/apps/evolution/mail/prompts/empty_subject"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-reply-start-bottom", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-reply-start-bottom", + "/apps/evolution/mail/composer/reply_start_bottom"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-request-receipt", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-request-receipt", + "/apps/evolution/mail/composer/request_receipt"); + + e_shell_settings_install_property ( + g_param_spec_string ( + "composer-spell-color", + NULL, + NULL, + "#ff0000", + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-spell-color", + "/apps/evolution/mail/composer/spell_color"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-top-signature", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-top-signature", + "/apps/evolution/mail/composer/top_signature"); +} diff --git a/modules/mail/e-mail-shell-settings.h b/modules/mail/e-mail-shell-settings.h new file mode 100644 index 0000000000..4267fd8a60 --- /dev/null +++ b/modules/mail/e-mail-shell-settings.h @@ -0,0 +1,33 @@ +/* + * e-mail-shell-settings.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_SHELL_SETTINGS_H +#define E_MAIL_SHELL_SETTINGS_H + +#include + +G_BEGIN_DECLS + +void e_mail_shell_settings_init (EShell *shell); + +G_END_DECLS + +#endif /* E_MAIL_SHELL_SETTINGS_H */ diff --git a/modules/mail/e-mail-shell-sidebar.c b/modules/mail/e-mail-shell-sidebar.c new file mode 100644 index 0000000000..2e5dffcb96 --- /dev/null +++ b/modules/mail/e-mail-shell-sidebar.c @@ -0,0 +1,644 @@ +/* + * e-mail-shell-sidebar.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-shell-sidebar.h" + +#include +#include + +#include "em-utils.h" +#include "em-folder-utils.h" + +#include "e-mail-local.h" +#include "e-mail-store.h" + +#define E_MAIL_SHELL_SIDEBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_SHELL_SIDEBAR, EMailShellSidebarPrivate)) + +#define STATE_KEY_EXPANDED "Expanded" + +struct _EMailShellSidebarPrivate { + GtkWidget *folder_tree; +}; + +enum { + PROP_0, + PROP_FOLDER_TREE +}; + +static gpointer parent_class; +static GType mail_shell_sidebar_type; + +static void +mail_shell_sidebar_restore_state (EMailShellSidebar *mail_shell_sidebar) +{ + EShellView *shell_view; + EShellSidebar *shell_sidebar; + EMFolderTree *folder_tree; + GtkTreeModel *tree_model; + GtkTreeView *tree_view; + GtkTreeIter iter; + GKeyFile *key_file; + gboolean valid; + gchar *selected; + gchar **groups; + gint ii; + + shell_sidebar = E_SHELL_SIDEBAR (mail_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + key_file = e_shell_view_get_state_key_file (shell_view); + + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + + tree_view = GTK_TREE_VIEW (folder_tree); + tree_model = gtk_tree_view_get_model (tree_view); + + /* Restore selected folder. */ + + selected = g_key_file_get_string ( + key_file, "Folder Tree", "Selected", NULL); + if (selected != NULL) { + em_folder_tree_set_selected (folder_tree, selected, FALSE); + g_free (selected); + } + + /* Set the initial folder tree expanded state in two stages: + * + * 1) Iterate over the "Store" and "Folder" state file groups + * and apply the "Expanded" keys where possible. + * + * 2) Iterate over the top-level nodes in the folder tree + * (these are all stores) and expand those that have no + * corresponding "Expanded" key in the state file. This + * ensures that new stores are expanded by default. + */ + + /* Stage 1 */ + + groups = g_key_file_get_groups (key_file, NULL); + + for (ii = 0; groups[ii] != NULL; ii++) { + GtkTreeRowReference *reference; + GtkTreePath *path; + GtkTreeIter iter; + const gchar *group_name = groups[ii]; + const gchar *key = STATE_KEY_EXPANDED; + const gchar *uri; + gboolean expanded; + + if (g_str_has_prefix (group_name, "Store ")) { + uri = group_name + 6; + expanded = TRUE; + } else if (g_str_has_prefix (group_name, "Folder ")) { + uri = group_name + 7; + expanded = FALSE; + } else + continue; + + if (g_key_file_has_key (key_file, group_name, key, NULL)) + expanded = g_key_file_get_boolean ( + key_file, group_name, key, NULL); + + if (!expanded) + continue; + + reference = em_folder_tree_model_lookup_uri ( + EM_FOLDER_TREE_MODEL (tree_model), uri); + if (reference == NULL) + continue; + + path = gtk_tree_row_reference_get_path (reference); + gtk_tree_model_get_iter (tree_model, &iter, path); + gtk_tree_view_expand_row (tree_view, path, FALSE); + gtk_tree_path_free (path); + } + + g_strfreev (groups); + + /* Stage 2 */ + + valid = gtk_tree_model_get_iter_first (tree_model, &iter); + + while (valid) { + const gchar *key = STATE_KEY_EXPANDED; + gchar *group_name; + gchar *uri; + + gtk_tree_model_get ( + tree_model, &iter, COL_STRING_URI, &uri, -1); + + if (uri == NULL) + goto next; + + group_name = g_strdup_printf ("Store %s", uri); + + if (!g_key_file_has_key (key_file, group_name, key, NULL)) { + GtkTreePath *path; + + path = gtk_tree_model_get_path (tree_model, &iter); + gtk_tree_view_expand_row (tree_view, path, FALSE); + gtk_tree_path_free (path); + } + + g_free (group_name); + g_free (uri); + + next: + valid = gtk_tree_model_iter_next (tree_model, &iter); + } +} + +static void +mail_shell_sidebar_row_collapsed_cb (EShellSidebar *shell_sidebar, + GtkTreeIter *iter, + GtkTreePath *path, + GtkTreeView *tree_view) +{ + EShellView *shell_view; + GtkTreeModel *model; + GKeyFile *key_file; + const gchar *key; + gboolean is_folder; + gboolean is_store; + gchar *group_name; + gchar *uri; + + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + key_file = e_shell_view_get_state_key_file (shell_view); + + model = gtk_tree_view_get_model (tree_view); + + gtk_tree_model_get ( + model, iter, + COL_STRING_URI, &uri, + COL_BOOL_IS_STORE, &is_store, + COL_BOOL_IS_FOLDER, &is_folder, -1); + + g_return_if_fail (is_store || is_folder); + + key = STATE_KEY_EXPANDED; + if (is_store) + group_name = g_strdup_printf ("Store %s", uri); + else + group_name = g_strdup_printf ("Folder %s", uri); + + g_key_file_set_boolean (key_file, group_name, key, FALSE); + e_shell_view_set_state_dirty (shell_view); + + g_free (group_name); + g_free (uri); +} + +static void +mail_shell_sidebar_row_expanded_cb (EShellSidebar *shell_sidebar, + GtkTreeIter *unused, + GtkTreePath *path, + GtkTreeView *tree_view) +{ + EShellView *shell_view; + GtkTreeModel *model; + GKeyFile *key_file; + const gchar *key; + gboolean is_folder; + gboolean is_store; + gchar *group_name; + gchar *uri; + + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + key_file = e_shell_view_get_state_key_file (shell_view); + + path = gtk_tree_path_copy (path); + model = gtk_tree_view_get_model (tree_view); + + /* Expand the node and all ancestors. */ + while (gtk_tree_path_get_depth (path) > 0) { + GtkTreeIter iter; + + gtk_tree_model_get_iter (model, &iter, path); + + gtk_tree_model_get ( + model, &iter, + COL_STRING_URI, &uri, + COL_BOOL_IS_STORE, &is_store, + COL_BOOL_IS_FOLDER, &is_folder, -1); + + g_return_if_fail (is_store || is_folder); + + key = STATE_KEY_EXPANDED; + if (is_store) + group_name = g_strdup_printf ("Store %s", uri); + else + group_name = g_strdup_printf ("Folder %s", uri); + + g_key_file_set_boolean (key_file, group_name, key, TRUE); + e_shell_view_set_state_dirty (shell_view); + + g_free (group_name); + g_free (uri); + + gtk_tree_path_up (path); + } + + gtk_tree_path_free (path); +} + +static void +mail_shell_sidebar_model_loaded_row_cb (EMailShellSidebar *mail_shell_sidebar, + GtkTreePath *path, + GtkTreeIter *iter, + GtkTreeModel *model) +{ + EShellSidebar *shell_sidebar; + EShellView *shell_view; + GtkTreeView *tree_view; + GKeyFile *key_file; + gboolean is_folder; + gboolean is_store; + const gchar *key; + gchar *group_name; + gchar *uri; + gboolean expanded; + + shell_sidebar = E_SHELL_SIDEBAR (mail_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + key_file = e_shell_view_get_state_key_file (shell_view); + + tree_view = GTK_TREE_VIEW (mail_shell_sidebar->priv->folder_tree); + + gtk_tree_model_get ( + model, iter, + COL_STRING_URI, &uri, + COL_BOOL_IS_STORE, &is_store, + COL_BOOL_IS_FOLDER, &is_folder, -1); + + g_return_if_fail (is_store || is_folder); + + key = STATE_KEY_EXPANDED; + if (is_store) { + group_name = g_strdup_printf ("Store %s", uri); + expanded = TRUE; + } else { + group_name = g_strdup_printf ("Folder %s", uri); + expanded = FALSE; + } + + if (g_key_file_has_key (key_file, group_name, key, NULL)) + expanded = g_key_file_get_boolean ( + key_file, group_name, key, NULL); + + if (expanded) + gtk_tree_view_expand_row (tree_view, path, FALSE); + + g_free (group_name); + g_free (uri); +} + +static void +mail_shell_sidebar_selection_changed_cb (EShellSidebar *shell_sidebar, + GtkTreeSelection *selection) +{ + EShellView *shell_view; + EShellViewClass *shell_view_class; + GtkTreeModel *model; + GtkTreeIter iter; + GKeyFile *key_file; + const gchar *icon_name; + gchar *display_name = NULL; + gchar *uri = NULL; + gboolean is_folder = FALSE; + guint flags = 0; + + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); + key_file = e_shell_view_get_state_key_file (shell_view); + + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + gtk_tree_model_get ( + model, &iter, + COL_STRING_DISPLAY_NAME, &display_name, + COL_STRING_URI, &uri, + COL_BOOL_IS_FOLDER, &is_folder, + COL_UINT_FLAGS, &flags, -1); + + if (uri != NULL) + g_key_file_set_string ( + key_file, "Folder Tree", "Selected", uri); + else + g_key_file_remove_key ( + key_file, "Folder Tree", "Selected", NULL); + + e_shell_view_set_state_dirty (shell_view); + + if (is_folder) + icon_name = em_folder_utils_get_icon_name (flags); + else { + icon_name = shell_view_class->icon_name; + display_name = g_strdup (shell_view_class->label); + } + + e_shell_sidebar_set_icon_name (shell_sidebar, icon_name); + e_shell_sidebar_set_primary_text (shell_sidebar, display_name); + + g_free (display_name); + g_free (uri); +} + +static void +mail_shell_sidebar_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_FOLDER_TREE: + g_value_set_object ( + value, e_mail_shell_sidebar_get_folder_tree ( + E_MAIL_SHELL_SIDEBAR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_shell_sidebar_dispose (GObject *object) +{ + EMailShellSidebarPrivate *priv; + + priv = E_MAIL_SHELL_SIDEBAR_GET_PRIVATE (object); + + if (priv->folder_tree != NULL) { + g_object_unref (priv->folder_tree); + priv->folder_tree = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +mail_shell_sidebar_finalize (GObject *object) +{ + EMailShellSidebarPrivate *priv; + + priv = E_MAIL_SHELL_SIDEBAR_GET_PRIVATE (object); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +mail_shell_sidebar_constructed (GObject *object) +{ + EMailShellSidebar *mail_shell_sidebar; + EShellSidebar *shell_sidebar; + EShellView *shell_view; + GtkTreeSelection *selection; + GtkTreeView *tree_view; + GtkTreeModel *model; + GtkWidget *container; + GtkWidget *widget; + + /* Chain up to parent's constructed method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_sidebar = E_SHELL_SIDEBAR (object); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + + mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (object); + + /* Build sidebar widgets. */ + + container = GTK_WIDGET (object); + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = em_folder_tree_new (); + em_folder_tree_set_excluded (EM_FOLDER_TREE (widget), 0); + em_folder_tree_enable_drag_and_drop (EM_FOLDER_TREE (widget)); + gtk_container_add (GTK_CONTAINER (container), widget); + mail_shell_sidebar->priv->folder_tree = g_object_ref (widget); + gtk_widget_show (widget); + + tree_view = GTK_TREE_VIEW (mail_shell_sidebar->priv->folder_tree); + selection = gtk_tree_view_get_selection (tree_view); + model = gtk_tree_view_get_model (tree_view); + + if (em_folder_tree_model_get_selection ( + EM_FOLDER_TREE_MODEL (model)) == NULL) + mail_shell_sidebar_restore_state (mail_shell_sidebar); + + em_folder_tree_model_set_selection ( + EM_FOLDER_TREE_MODEL (model), selection); + + g_signal_connect_swapped ( + tree_view, "row-collapsed", + G_CALLBACK (mail_shell_sidebar_row_collapsed_cb), + shell_sidebar); + + g_signal_connect_swapped ( + tree_view, "row-expanded", + G_CALLBACK (mail_shell_sidebar_row_expanded_cb), + shell_sidebar); + + g_signal_connect_swapped ( + model, "loaded-row", + G_CALLBACK (mail_shell_sidebar_model_loaded_row_cb), + shell_sidebar); + + g_signal_connect_swapped ( + selection, "changed", + G_CALLBACK (mail_shell_sidebar_selection_changed_cb), + shell_sidebar); +} + +static guint32 +mail_shell_sidebar_check_state (EShellSidebar *shell_sidebar) +{ + EMailShellSidebar *mail_shell_sidebar; + EShellView *shell_view; + EMFolderTree *folder_tree; + GtkTreeSelection *selection; + GtkTreeView *tree_view; + GtkTreeModel *model; + GtkTreeIter iter; + CamelFolder *folder; + CamelStore *local_store; + CamelStore *store; + gchar *full_name; + gchar *uri; + gboolean allows_children = TRUE; + gboolean can_delete = TRUE; + gboolean is_junk = FALSE; + gboolean is_outbox = FALSE; + gboolean is_store; + gboolean is_trash = FALSE; + guint32 folder_flags = 0; + guint32 state = 0; + + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + + local_store = e_mail_local_get_store (); + + mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar); + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + tree_view = GTK_TREE_VIEW (folder_tree); + + selection = gtk_tree_view_get_selection (tree_view); + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return 0; + + gtk_tree_model_get ( + model, &iter, + COL_POINTER_CAMEL_STORE, &store, + COL_STRING_FULL_NAME, &full_name, + COL_BOOL_IS_STORE, &is_store, + COL_UINT_FLAGS, &folder_flags, + COL_STRING_URI, &uri, -1); + + if (!is_store) { + is_junk = (strcmp (full_name, CAMEL_VJUNK_NAME) == 0); + is_trash = (strcmp (full_name, CAMEL_VTRASH_NAME) == 0); + allows_children = !(is_junk || is_trash); + + /* Don't allow deletion of special local folders. */ + if (store == local_store) + can_delete = + (strcmp (full_name, "Drafts") != 0) && + (strcmp (full_name, "Inbox") != 0) && + (strcmp (full_name, "Outbox") != 0) && + (strcmp (full_name, "Sent") != 0) && + (strcmp (full_name, "Templates") != 0); + + folder = em_folder_tree_get_selected_folder (folder_tree); + is_outbox = em_utils_folder_is_outbox (folder, NULL); + can_delete &= !(folder_flags & CAMEL_FOLDER_SYSTEM); + } + + if (allows_children) + state |= E_MAIL_SHELL_SIDEBAR_FOLDER_ALLOWS_CHILDREN; + if (can_delete) + state |= E_MAIL_SHELL_SIDEBAR_FOLDER_CAN_DELETE; + if (is_junk) + state |= E_MAIL_SHELL_SIDEBAR_FOLDER_IS_JUNK; + if (is_outbox) + state |= E_MAIL_SHELL_SIDEBAR_FOLDER_IS_OUTBOX; + if (is_store) + state |= E_MAIL_SHELL_SIDEBAR_FOLDER_IS_STORE; + if (is_trash) + state |= E_MAIL_SHELL_SIDEBAR_FOLDER_IS_TRASH; + + return state; +} + +static void +mail_shell_sidebar_class_init (EMailShellSidebarClass *class) +{ + GObjectClass *object_class; + EShellSidebarClass *shell_sidebar_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMailShellSidebarPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->get_property = mail_shell_sidebar_get_property; + object_class->dispose = mail_shell_sidebar_dispose; + object_class->finalize = mail_shell_sidebar_finalize; + object_class->constructed = mail_shell_sidebar_constructed; + + shell_sidebar_class = E_SHELL_SIDEBAR_CLASS (class); + shell_sidebar_class->check_state = mail_shell_sidebar_check_state; + + g_object_class_install_property ( + object_class, + PROP_FOLDER_TREE, + g_param_spec_object ( + "folder-tree", + NULL, + NULL, + EM_TYPE_FOLDER_TREE, + G_PARAM_READABLE)); +} + +static void +mail_shell_sidebar_init (EMailShellSidebar *mail_shell_sidebar) +{ + mail_shell_sidebar->priv = + E_MAIL_SHELL_SIDEBAR_GET_PRIVATE (mail_shell_sidebar); + + /* Postpone widget construction until we have a shell view. */ +} + +GType +e_mail_shell_sidebar_get_type (void) +{ + return mail_shell_sidebar_type; +} + +void +e_mail_shell_sidebar_register_type (GTypeModule *type_module) +{ + static const GTypeInfo type_info = { + sizeof (EMailShellSidebarClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) mail_shell_sidebar_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMailShellSidebar), + 0, /* n_preallocs */ + (GInstanceInitFunc) mail_shell_sidebar_init, + NULL /* value_table */ + }; + + mail_shell_sidebar_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_SIDEBAR, + "EMailShellSidebar", &type_info, 0); +} + +GtkWidget * +e_mail_shell_sidebar_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_MAIL_SHELL_SIDEBAR, + "shell-view", shell_view, NULL); +} + +EMFolderTree * +e_mail_shell_sidebar_get_folder_tree (EMailShellSidebar *mail_shell_sidebar) +{ + g_return_val_if_fail ( + E_IS_MAIL_SHELL_SIDEBAR (mail_shell_sidebar), NULL); + + return EM_FOLDER_TREE (mail_shell_sidebar->priv->folder_tree); +} diff --git a/modules/mail/e-mail-shell-sidebar.h b/modules/mail/e-mail-shell-sidebar.h new file mode 100644 index 0000000000..10a2ff6a2a --- /dev/null +++ b/modules/mail/e-mail-shell-sidebar.h @@ -0,0 +1,81 @@ +/* + * e-mail-shell-sidebar.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_SHELL_SIDEBAR_H +#define E_MAIL_SHELL_SIDEBAR_H + +#include +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_MAIL_SHELL_SIDEBAR \ + (e_mail_shell_sidebar_get_type ()) +#define E_MAIL_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_SHELL_SIDEBAR, EMailShellSidebar)) +#define E_MAIL_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_SHELL_SIDEBAR, EMailShellSidebarClass)) +#define E_IS_MAIL_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_SHELL_SIDEBAR)) +#define E_IS_MAIL_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_SHELL_SIDEBAR)) +#define E_MAIL_SHELL_SIDEBAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_SHELL_SIDEBAR, EMailShellSidebarClass)) + +G_BEGIN_DECLS + +typedef struct _EMailShellSidebar EMailShellSidebar; +typedef struct _EMailShellSidebarClass EMailShellSidebarClass; +typedef struct _EMailShellSidebarPrivate EMailShellSidebarPrivate; + +enum { + E_MAIL_SHELL_SIDEBAR_FOLDER_ALLOWS_CHILDREN = 1 << 0, + E_MAIL_SHELL_SIDEBAR_FOLDER_CAN_DELETE = 1 << 1, + E_MAIL_SHELL_SIDEBAR_FOLDER_IS_JUNK = 1 << 2, + E_MAIL_SHELL_SIDEBAR_FOLDER_IS_OUTBOX = 1 << 3, + E_MAIL_SHELL_SIDEBAR_FOLDER_IS_STORE = 1 << 4, + E_MAIL_SHELL_SIDEBAR_FOLDER_IS_TRASH = 1 << 5 +}; + +struct _EMailShellSidebar { + EShellSidebar parent; + EMailShellSidebarPrivate *priv; +}; + +struct _EMailShellSidebarClass { + EShellSidebarClass parent_class; +}; + +GType e_mail_shell_sidebar_get_type (void); +void e_mail_shell_sidebar_register_type + (GTypeModule *type_module); +GtkWidget * e_mail_shell_sidebar_new(EShellView *shell_view); +EMFolderTree * e_mail_shell_sidebar_get_folder_tree + (EMailShellSidebar *mail_shell_sidebar); + +G_END_DECLS + +#endif /* E_MAIL_SHELL_SIDEBAR_H */ diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c new file mode 100644 index 0000000000..25e7d80da3 --- /dev/null +++ b/modules/mail/e-mail-shell-view-actions.c @@ -0,0 +1,1806 @@ +/* + * e-mail-shell-view-actions.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-shell-view-private.h" + +#define STATE_KEY_SEARCH_FILTER "SearchFilter" +#define STATE_KEY_SEARCH_SCOPE "SearchScope" +#define STATE_KEY_SEARCH_TEXT "SearchText" + +static void +action_gal_save_custom_view_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellContent *mail_shell_content; + EShellView *shell_view; + GalViewInstance *view_instance; + + /* All shell views repond to the activation of this action, + * which is defined by EShellWindow. But only the currently + * active shell view proceeds with saving the custom view. */ + shell_view = E_SHELL_VIEW (mail_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + mail_shell_content = mail_shell_view->priv->mail_shell_content; + view_instance = e_mail_shell_content_get_view_instance (mail_shell_content); + gal_view_instance_save_as (view_instance); +} + +static void +action_mail_account_disable_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellSidebar *mail_shell_sidebar; + EMFolderTree *folder_tree; + EAccountList *account_list; + EAccount *account; + gchar *folder_uri; + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + folder_uri = em_folder_tree_get_selected_uri (folder_tree); + g_return_if_fail (folder_uri != NULL); + + account_list = e_get_account_list (); + account = mail_config_get_account_by_source_url (folder_uri); + g_return_if_fail (account != NULL); + + if (e_account_list_account_has_proxies (account_list, account)) + e_account_list_remove_account_proxies (account_list, account); + + account->enabled = !account->enabled; + e_account_list_change (account_list, account); + e_mail_store_remove_by_uri (folder_uri); + + if (account->parent_uid != NULL) + e_account_list_remove (account_list, account); + + e_account_list_save (account_list); + + g_free (folder_uri); +} + +static void +action_mail_create_search_folder_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + /* FIXME */ + g_print ("Action: %s\n", gtk_action_get_name (GTK_ACTION (action))); +} + +static void +action_mail_download_foreach_cb (CamelService *service) +{ + if (CAMEL_IS_DISCO_STORE (service) || CAMEL_IS_OFFLINE_STORE (service)) + mail_store_prepare_offline (CAMEL_STORE (service)); +} + +static void +action_mail_download_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + e_mail_store_foreach ((GHFunc) action_mail_download_foreach_cb, NULL); +} + +static void +action_mail_empty_trash_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShellWindow *shell_window; + EShellView *shell_view; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + em_utils_empty_trash (GTK_WIDGET (shell_window)); +} + +static void +action_mail_flush_outbox_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + mail_send (); +} + +static void +action_mail_folder_copy_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellSidebar *mail_shell_sidebar; + CamelFolderInfo *folder_info; + EMFolderTree *folder_tree; + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + folder_info = em_folder_tree_get_selected_folder_info (folder_tree); + g_return_if_fail (folder_info != NULL); + + /* XXX Leaking folder_info? */ + em_folder_utils_copy_folder (folder_info, FALSE); +} + +static void +action_mail_folder_delete_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellSidebar *mail_shell_sidebar; + EMFolderTree *folder_tree; + CamelFolder *folder; + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + folder = em_folder_tree_get_selected_folder (folder_tree); + g_return_if_fail (folder != NULL); + + em_folder_utils_delete_folder (folder); +} + +static void +action_mail_folder_expunge_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailReader *reader; + MessageList *message_list; + EShellWindow *shell_window; + EShellView *shell_view; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + g_return_if_fail (message_list->folder != NULL); + + em_utils_expunge_folder ( + GTK_WIDGET (shell_window), message_list->folder); +} + +static void +action_mail_folder_mark_all_as_read_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailReader *reader; + MessageList *message_list; + EShellWindow *shell_window; + EShellView *shell_view; + CamelFolder *folder; + GtkWindow *parent; + GPtrArray *uids; + const gchar *key; + const gchar *prompt; + guint ii; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + parent = GTK_WINDOW (shell_window); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + folder = message_list->folder; + g_return_if_fail (folder != NULL); + + key = "/apps/evolution/mail/prompts/mark_all_read"; + prompt = "mail:ask-mark-all-read"; + + if (!em_utils_prompt_user (parent, key, prompt, NULL)) + return; + + uids = message_list_get_uids (message_list); + + camel_folder_freeze (folder); + for (ii = 0; ii < uids->len; ii++) + camel_folder_set_message_flags ( + folder, uids->pdata[ii], + CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); + camel_folder_thaw (folder); + + message_list_free_uids (message_list, uids); +} + +static void +action_mail_folder_move_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellSidebar *mail_shell_sidebar; + CamelFolderInfo *folder_info; + EMFolderTree *folder_tree; + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + folder_info = em_folder_tree_get_selected_folder_info (folder_tree); + g_return_if_fail (folder_info != NULL); + + /* XXX Leaking folder_info? */ + em_folder_utils_copy_folder (folder_info, TRUE); +} + +static void +action_mail_folder_new_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EMailShellSidebar *mail_shell_sidebar; + CamelFolderInfo *folder_info; + EMFolderTree *folder_tree; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + folder_info = em_folder_tree_get_selected_folder_info (folder_tree); + g_return_if_fail (folder_info != NULL); + + em_folder_utils_create_folder ( + folder_info, folder_tree, GTK_WINDOW (shell_window)); + camel_folder_info_free (folder_info); +} + +static void +action_mail_folder_properties_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellSidebar *mail_shell_sidebar; + EMFolderTree *folder_tree; + EShellView *shell_view; + GtkTreeSelection *selection; + GtkTreeView *tree_view; + GtkTreeModel *model; + GtkTreeIter iter; + gchar *uri; + + shell_view = E_SHELL_VIEW (mail_shell_view); + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + + tree_view = GTK_TREE_VIEW (folder_tree); + selection = gtk_tree_view_get_selection (tree_view); + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return; + + gtk_tree_model_get (model, &iter, COL_STRING_URI, &uri, -1); + em_folder_properties_show (shell_view, NULL, uri); + g_free (uri); +} + +static void +action_mail_folder_refresh_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellSidebar *mail_shell_sidebar; + EMFolderTree *folder_tree; + CamelFolder *folder; + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + folder = em_folder_tree_get_selected_folder (folder_tree); + g_return_if_fail (folder != NULL); + + mail_refresh_folder (folder, NULL, NULL); +} + +static void +action_mail_folder_rename_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellSidebar *mail_shell_sidebar; + EMFolderTree *folder_tree; + CamelFolder *folder; + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + folder = em_folder_tree_get_selected_folder (folder_tree); + g_return_if_fail (folder != NULL); + + em_folder_utils_rename_folder (folder); +} + +/* Helper for action_mail_folder_select_all_cb() */ +static gboolean +action_mail_folder_select_all_timeout_cb (MessageList *message_list) +{ + message_list_select_all (message_list); + gtk_widget_grab_focus (GTK_WIDGET (message_list)); + + return FALSE; +} + +static void +action_mail_folder_select_all_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailReader *reader; + MessageList *message_list; + EShellWindow *shell_window; + EShellView *shell_view; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + if (message_list->threaded) { + gtk_action_activate (ACTION (MAIL_THREADS_EXPAND_ALL)); + + /* XXX The timeout below is added so that the execution + * thread to expand all conversation threads would + * have completed. The timeout 505 is just to ensure + * that the value is a small delta more than the + * timeout value in mail_regen_list(). */ + g_timeout_add ( + 505, (GSourceFunc) + action_mail_folder_select_all_timeout_cb, + message_list); + } else + /* If there is no threading, just select all immediately. */ + action_mail_folder_select_all_timeout_cb (message_list); +} + +static void +action_mail_folder_select_thread_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + MessageList *message_list; + EMailReader *reader; + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + message_list_select_thread (message_list); +} + +static void +action_mail_folder_select_subthread_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + MessageList *message_list; + EMailReader *reader; + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + message_list_select_subthread (message_list); +} + +static void +action_mail_hide_deleted_cb (GtkToggleAction *action, + EMailShellView *mail_shell_view) +{ + MessageList *message_list; + EMailReader *reader; + gboolean active; + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + active = gtk_toggle_action_get_active (action); + message_list_set_hidedeleted (message_list, active); +} + +static void +action_mail_hide_read_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + MessageList *message_list; + EMailReader *reader; + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + message_list_hide_add ( + message_list, + "(match-all (system-flag \"seen\"))", + ML_HIDE_SAME, ML_HIDE_SAME); +} + +static void +action_mail_hide_selected_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + MessageList *message_list; + EMailReader *reader; + GPtrArray *uids; + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + uids = message_list_get_selected (message_list); + message_list_hide_uids (message_list, uids); + message_list_free_uids (message_list, uids); +} + +static void +action_mail_label_cb (GtkToggleAction *action, + EMailShellView *mail_shell_view) +{ + EMailReader *reader; + MessageList *message_list; + CamelFolder *folder; + GPtrArray *uids; + const gchar *tag; + gint ii; + + tag = g_object_get_data (G_OBJECT (action), "tag"); + g_return_if_fail (tag != NULL); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + folder = message_list->folder; + + uids = message_list_get_selected (message_list); + + for (ii = 0; ii < uids->len; ii++) { + if (gtk_toggle_action_get_active (action)) + camel_folder_set_message_user_flag ( + folder, uids->pdata[ii], tag, TRUE); + else { + camel_folder_set_message_user_flag ( + folder, uids->pdata[ii], tag, FALSE); + camel_folder_set_message_user_tag ( + folder, uids->pdata[ii], "label", NULL); + } + } + + message_list_free_uids (message_list, uids); +} + +static void +action_mail_label_new_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShell *shell; + EShellSettings *shell_settings; + EShellWindow *shell_window; + EShellView *shell_view; + EMailLabelDialog *label_dialog; + EMailLabelListStore *store; + EMailReader *reader; + MessageList *message_list; + CamelFolder *folder; + GtkTreeModel *model; + GtkTreeIter iter; + GtkWidget *dialog; + GPtrArray *uids; + GdkColor label_color; + const gchar *property_name; + const gchar *label_name; + gchar *label_tag; + gint n_children; + guint ii; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + dialog = e_mail_label_dialog_new (GTK_WINDOW (shell_window)); + + gtk_window_set_title (GTK_WINDOW (dialog), _("Add Label")); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) + goto exit; + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + label_dialog = E_MAIL_LABEL_DIALOG (dialog); + label_name = e_mail_label_dialog_get_label_name (label_dialog); + e_mail_label_dialog_get_label_color (label_dialog, &label_color); + + property_name = "mail-label-list-store"; + store = e_shell_settings_get_object (shell_settings, property_name); + e_mail_label_list_store_set (store, NULL, label_name, &label_color); + g_object_unref (store); + + /* XXX This is awkward. We've added a new label to the list store + * but we don't have the new label's tag nor an iterator to use + * to fetch it. We know the label was appended to the store, + * so we have to dig it out manually. EMailLabelListStore API + * probably needs some rethinking. */ + model = GTK_TREE_MODEL (store); + n_children = gtk_tree_model_iter_n_children (model, NULL); + gtk_tree_model_iter_nth_child (model, &iter, NULL, n_children - 1); + label_tag = e_mail_label_list_store_get_tag (store, &iter); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + folder = message_list->folder; + + uids = message_list_get_selected (message_list); + + for (ii = 0; ii < uids->len; ii++) + camel_folder_set_message_user_flag ( + folder, uids->pdata[ii], label_tag, TRUE); + + message_list_free_uids (message_list, uids); + + g_free (label_tag); + +exit: + gtk_widget_destroy (dialog); +} + +static void +action_mail_label_none_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShell *shell; + EShellView *shell_view; + EShellSettings *shell_settings; + EShellWindow *shell_window; + EMailReader *reader; + MessageList *message_list; + GtkTreeModel *tree_model; + CamelFolder *folder; + GtkTreeIter iter; + GPtrArray *uids; + gboolean valid; + guint ii; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + tree_model = e_shell_settings_get_object ( + shell_settings, "mail-label-list-store"); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + uids = message_list_get_selected (message_list); + folder = message_list->folder; + + valid = gtk_tree_model_get_iter_first (tree_model, &iter); + + while (valid) { + gchar *tag; + + tag = e_mail_label_list_store_get_tag ( + E_MAIL_LABEL_LIST_STORE (tree_model), &iter); + + for (ii = 0; ii < uids->len; ii++) { + camel_folder_set_message_user_flag ( + folder, uids->pdata[ii], tag, FALSE); + camel_folder_set_message_user_tag ( + folder, uids->pdata[ii], "label", NULL); + } + + g_free (tag); + + valid = gtk_tree_model_iter_next (tree_model, &iter); + } + + message_list_free_uids (message_list, uids); +} + +static void +action_mail_search_cb (GtkRadioAction *action, + GtkRadioAction *current, + EMailShellView *mail_shell_view) +{ + EShellView *shell_view; + EShellContent *shell_content; + const gchar *search_hint; + + /* XXX Figure out a way to handle this in EShellContent + * instead of every shell view having to handle it. + * The problem is EShellContent does not know what + * the search option actions are for this view. It + * would have to dig up the popup menu and retrieve + * the action for each menu item. Seems messy. */ + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + + search_hint = gtk_action_get_label (GTK_ACTION (current)); + e_shell_content_set_search_hint (shell_content, search_hint); +} + +static void +action_mail_show_hidden_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + MessageList *message_list; + EMailReader *reader; + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + message_list_hide_clear (message_list); +} + +static void +action_mail_smart_backward_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + EShellSettings *shell_settings; + EMailShellSidebar *mail_shell_sidebar; + EMFolderTree *folder_tree; + EMFormatHTMLDisplay *html_display; + EMailReader *reader; + MessageList *message_list; + GtkToggleAction *toggle_action; + GtkHTML *html; + gboolean caret_mode; + gboolean magic_spacebar; + + /* This implements the so-called "Magic Backspace". */ + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + html_display = e_mail_reader_get_html_display (reader); + message_list = e_mail_reader_get_message_list (reader); + + magic_spacebar = e_shell_settings_get_boolean ( + shell_settings, "mail-magic-spacebar"); + + toggle_action = GTK_TOGGLE_ACTION (ACTION (MAIL_CARET_MODE)); + caret_mode = gtk_toggle_action_get_active (toggle_action); + + html = EM_FORMAT_HTML (html_display)->html; + + if (gtk_html_command (html, "scroll-backward")) + return; + + if (caret_mode || !magic_spacebar) + return; + + /* XXX Are two separate calls really necessary? */ + + if (message_list_select ( + message_list, MESSAGE_LIST_SELECT_PREVIOUS, + 0, CAMEL_MESSAGE_SEEN)) + return; + + if (message_list_select ( + message_list, MESSAGE_LIST_SELECT_PREVIOUS | + MESSAGE_LIST_SELECT_WRAP, 0, CAMEL_MESSAGE_SEEN)) + return; + + em_folder_tree_select_prev_path (folder_tree, TRUE); + + gtk_widget_grab_focus (GTK_WIDGET (message_list)); +} + +static void +action_mail_smart_forward_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + EShellSettings *shell_settings; + EMailShellSidebar *mail_shell_sidebar; + EMFolderTree *folder_tree; + EMFormatHTMLDisplay *html_display; + EMailReader *reader; + MessageList *message_list; + GtkToggleAction *toggle_action; + GtkHTML *html; + gboolean caret_mode; + gboolean magic_spacebar; + + /* This implements the so-called "Magic Spacebar". */ + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + html_display = e_mail_reader_get_html_display (reader); + message_list = e_mail_reader_get_message_list (reader); + + magic_spacebar = e_shell_settings_get_boolean ( + shell_settings, "mail-magic-spacebar"); + + toggle_action = GTK_TOGGLE_ACTION (ACTION (MAIL_CARET_MODE)); + caret_mode = gtk_toggle_action_get_active (toggle_action); + + html = EM_FORMAT_HTML (html_display)->html; + + if (gtk_html_command (html, "scroll-forward")) + return; + + if (caret_mode || !magic_spacebar) + return; + + /* XXX Are two separate calls really necessary? */ + + if (message_list_select ( + message_list, MESSAGE_LIST_SELECT_NEXT, + 0, CAMEL_MESSAGE_SEEN)) + return; + + if (message_list_select ( + message_list, MESSAGE_LIST_SELECT_NEXT | + MESSAGE_LIST_SELECT_WRAP, 0, CAMEL_MESSAGE_SEEN)) + return; + + em_folder_tree_select_next_path (folder_tree, TRUE); + + gtk_widget_grab_focus (GTK_WIDGET (message_list)); +} + +static void +action_mail_stop_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + mail_cancel_all (); +} + +static void +action_mail_threads_collapse_all_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + MessageList *message_list; + EMailReader *reader; + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + message_list_set_threaded_collapse_all (message_list); +} + +static void +action_mail_threads_expand_all_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + MessageList *message_list; + EMailReader *reader; + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + message_list_set_threaded_expand_all (message_list); +} + +static void +action_mail_threads_group_by_cb (GtkToggleAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellContent *mail_shell_content; + MessageList *message_list; + EMailReader *reader; + gboolean active; + + mail_shell_content = mail_shell_view->priv->mail_shell_content; + active = gtk_toggle_action_get_active (action); + + reader = E_MAIL_READER (mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + message_list_set_threaded (message_list, active); +} + +static void +action_mail_tools_filters_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShellWindow *shell_window; + EShellView *shell_view; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + em_utils_edit_filters (GTK_WIDGET (shell_window)); +} + +static void +action_mail_tools_search_folders_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + vfolder_edit (E_SHELL_VIEW (mail_shell_view)); +} + +static void +action_mail_tools_subscriptions_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShellWindow *shell_window; + EShellView *shell_view; + GtkWidget *dialog; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + dialog = em_subscribe_editor_new (); + gtk_window_set_transient_for ( + GTK_WINDOW (dialog), GTK_WINDOW (shell_window)); + gtk_dialog_run (GTK_DIALOG (dialog)); + /* XXX Dialog destroys itself. */ +} + +static void +action_mail_view_cb (GtkRadioAction *action, + GtkRadioAction *current, + EMailShellView *mail_shell_view) +{ + EMailShellContent *mail_shell_content; + gboolean vertical_view; + + mail_shell_content = mail_shell_view->priv->mail_shell_content; + vertical_view = (gtk_radio_action_get_current_value (action) == 1); + + e_mail_shell_content_set_vertical_view ( + mail_shell_content, vertical_view); +} + +static void +action_search_execute_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShellView *shell_view; + EShellContent *shell_content; + EMailReader *reader; + MessageList *message_list; + GKeyFile *key_file; + const gchar *folder_uri; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + key_file = e_shell_view_get_state_key_file (shell_view); + + /* All shell views respond to the activation of this action, + * which is defined by EShellWindow. But only the currently + * active shell view proceeds with executing the search. */ + if (!e_shell_view_is_active (shell_view)) + return; + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + folder_uri = message_list->folder_uri; + + if (folder_uri != NULL) { + const gchar *key; + const gchar *string; + gchar *group_name; + + key = STATE_KEY_SEARCH_TEXT; + string = e_shell_content_get_search_text (shell_content); + group_name = g_strdup_printf ("Folder %s", folder_uri); + + if (string != NULL && *string != '\0') + g_key_file_set_string ( + key_file, group_name, key, string); + else + g_key_file_remove_key ( + key_file, group_name, key, NULL); + e_shell_view_set_state_dirty (shell_view); + + g_free (group_name); + } + + e_mail_shell_view_execute_search (mail_shell_view); +} + +static void +action_search_filter_cb (GtkRadioAction *action, + GtkRadioAction *current, + EMailShellView *mail_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EMailReader *reader; + MessageList *message_list; + GKeyFile *key_file; + const gchar *folder_uri; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + key_file = e_shell_view_get_state_key_file (shell_view); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + folder_uri = message_list->folder_uri; + + if (folder_uri != NULL) { + const gchar *key; + const gchar *string; + gchar *group_name; + + key = STATE_KEY_SEARCH_FILTER; + string = gtk_action_get_name (GTK_ACTION (current)); + group_name = g_strdup_printf ("Folder %s", folder_uri); + + g_key_file_set_string (key_file, group_name, key, string); + e_shell_view_set_state_dirty (shell_view); + + g_free (group_name); + } + + gtk_action_activate (ACTION (SEARCH_EXECUTE)); +} + +static void +action_search_scope_cb (GtkRadioAction *action, + GtkRadioAction *current, + EMailShellView *mail_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EMailReader *reader; + MessageList *message_list; + GKeyFile *key_file; + const gchar *folder_uri; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + key_file = e_shell_view_get_state_key_file (shell_view); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + folder_uri = message_list->folder_uri; + + if (folder_uri != NULL) { + const gchar *key; + const gchar *string; + gchar *group_name; + + key = STATE_KEY_SEARCH_SCOPE; + string = gtk_action_get_name (GTK_ACTION (current)); + group_name = g_strdup_printf ("Folder %s", folder_uri); + + g_key_file_set_string (key_file, group_name, key, string); + e_shell_view_set_state_dirty (shell_view); + + g_free (group_name); + } + + gtk_action_activate (ACTION (SEARCH_EXECUTE)); +} + +static GtkActionEntry mail_entries[] = { + + { "mail-account-disable", + NULL, + N_("_Disable Account"), + NULL, + N_("Disable this account"), + G_CALLBACK (action_mail_account_disable_cb) }, + + { "mail-create-search-folder", + NULL, + N_("C_reate Search Folder From Search..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_create_search_folder_cb) }, + + { "mail-download", + NULL, + N_("_Download Messages for Offline Usage"), + NULL, + N_("Download messages of accounts and folders marked for offline"), + G_CALLBACK (action_mail_download_cb) }, + + { "mail-empty-trash", + NULL, + N_("Empty _Trash"), + NULL, + N_("Permanently remove all the deleted messages from all folders"), + G_CALLBACK (action_mail_empty_trash_cb) }, + + { "mail-flush-outbox", + "mail-send", + N_("Fl_ush Outbox"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_flush_outbox_cb) }, + + { "mail-folder-copy", + "folder-copy", + N_("_Copy Folder To..."), + NULL, + N_("Copy the selected folder into another folder"), + G_CALLBACK (action_mail_folder_copy_cb) }, + + { "mail-folder-delete", + GTK_STOCK_DELETE, + NULL, + NULL, + N_("Permanently remove this folder"), + G_CALLBACK (action_mail_folder_delete_cb) }, + + { "mail-folder-expunge", + NULL, + N_("E_xpunge"), + "e", + N_("Permanently remove all deleted messages from this folder"), + G_CALLBACK (action_mail_folder_expunge_cb) }, + + { "mail-folder-mark-all-as-read", + "mail-read", + N_("Mar_k All Messages as Read"), + NULL, + N_("Mark all messages in the folder as read"), + G_CALLBACK (action_mail_folder_mark_all_as_read_cb) }, + + { "mail-folder-move", + "folder-move", + N_("_Move Folder To..."), + NULL, + N_("Move the selected folder into another folder"), + G_CALLBACK (action_mail_folder_move_cb) }, + + { "mail-folder-new", + "folder-new", + N_("_New..."), + NULL, + N_("Create a new folder for storing mail"), + G_CALLBACK (action_mail_folder_new_cb) }, + + { "mail-folder-properties", + GTK_STOCK_PROPERTIES, + NULL, + NULL, + N_("Change the properties of this folder"), + G_CALLBACK (action_mail_folder_properties_cb) }, + + { "mail-folder-refresh", + GTK_STOCK_REFRESH, + NULL, + "F5", + N_("Refresh the folder"), + G_CALLBACK (action_mail_folder_refresh_cb) }, + + { "mail-folder-rename", + NULL, + N_("_Rename..."), + "F2", + N_("Change the name of this folder"), + G_CALLBACK (action_mail_folder_rename_cb) }, + + { "mail-folder-select-all", + NULL, + N_("Select _All Messages"), + "a", + N_("Select all visible messages"), + G_CALLBACK (action_mail_folder_select_all_cb) }, + + { "mail-folder-select-thread", + NULL, + N_("Select Message _Thread"), + "h", + N_("Select all messages in the same thread as the selected message"), + G_CALLBACK (action_mail_folder_select_thread_cb) }, + + { "mail-folder-select-subthread", + NULL, + N_("Select Message S_ubthread"), + "h", + N_("Select all replies to the currently selected message"), + G_CALLBACK (action_mail_folder_select_subthread_cb) }, + + { "mail-label-new", + NULL, + N_("_New Label"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_label_new_cb) }, + + { "mail-label-none", + NULL, + N_("N_one"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_label_none_cb) }, + + { "mail-hide-read", + NULL, + N_("Hide _Read Messages"), + NULL, + N_("Temporarily hide all messages that have already been read"), + G_CALLBACK (action_mail_hide_read_cb) }, + + { "mail-hide-selected", + NULL, + N_("Hide S_elected Messages"), + NULL, + N_("Temporarily hide the selected messages"), + G_CALLBACK (action_mail_hide_selected_cb) }, + + { "mail-show-hidden", + NULL, + N_("Show Hidde_n Messages"), + NULL, + N_("Show messages that have been temporarily hidden"), + G_CALLBACK (action_mail_show_hidden_cb) }, + + { "mail-smart-backward", + NULL, + NULL, /* No menu item; key press only */ + NULL, + NULL, + G_CALLBACK (action_mail_smart_backward_cb) }, + + { "mail-smart-forward", + NULL, + NULL, /* No menu item; key press only */ + NULL, + NULL, + G_CALLBACK (action_mail_smart_forward_cb) }, + + { "mail-stop", + GTK_STOCK_STOP, + N_("Cancel"), + NULL, + N_("Cancel the current mail operation"), + G_CALLBACK (action_mail_stop_cb) }, + + { "mail-threads-collapse-all", + NULL, + N_("Collapse All _Threads"), + "b", + N_("Collapse all message threads"), + G_CALLBACK (action_mail_threads_collapse_all_cb) }, + + { "mail-threads-expand-all", + NULL, + N_("E_xpand All Threads"), + NULL, + N_("Expand all message threads"), + G_CALLBACK (action_mail_threads_expand_all_cb) }, + + { "mail-tools-filters", + NULL, + N_("_Message Filters"), + NULL, + N_("Create or edit rules for filtering new mail"), + G_CALLBACK (action_mail_tools_filters_cb) }, + + { "mail-tools-search-folders", + NULL, + N_("Search F_olders"), + NULL, + N_("Create or edit search folder definitions"), + G_CALLBACK (action_mail_tools_search_folders_cb) }, + + { "mail-tools-subscriptions", + NULL, + N_("_Subscriptions..."), + NULL, + N_("Subscribe or unsubscribe to folders on remote servers"), + G_CALLBACK (action_mail_tools_subscriptions_cb) }, + + /*** Menus ***/ + + { "mail-folder-menu", + NULL, + N_("F_older"), + NULL, + NULL, + NULL }, + + { "mail-label-menu", + NULL, + N_("_Label"), + NULL, + NULL, + NULL }, + + { "mail-preview-menu", + NULL, + N_("_Preview"), + NULL, + NULL, + NULL } +}; + +static EPopupActionEntry mail_popup_entries[] = { + + { "mail-popup-account-disable", + NULL, + "mail-account-disable" }, + + { "mail-popup-empty-trash", + NULL, + "mail-empty-trash" }, + + { "mail-popup-flush-outbox", + NULL, + "mail-flush-outbox" }, + + { "mail-popup-folder-copy", + NULL, + "mail-folder-copy" }, + + { "mail-popup-folder-delete", + NULL, + "mail-folder-delete" }, + + { "mail-popup-folder-move", + NULL, + "mail-folder-move" }, + + { "mail-popup-folder-new", + N_("_New Folder..."), + "mail-folder-new" }, + + { "mail-popup-folder-properties", + NULL, + "mail-folder-properties" }, + + { "mail-popup-folder-refresh", + NULL, + "mail-folder-refresh" }, + + { "mail-popup-folder-rename", + NULL, + "mail-folder-rename" } +}; + +static GtkToggleActionEntry mail_toggle_entries[] = { + + { "mail-hide-deleted", + NULL, + N_("Hide _Deleted Messages"), + NULL, + N_("Hide deleted messages rather than displaying " + "them with a line through them"), + G_CALLBACK (action_mail_hide_deleted_cb), + TRUE }, + + { "mail-preview", + NULL, + N_("Show Message _Preview"), + "m", + N_("Show message preview pane"), + NULL, /* Handled by property bindings */ + TRUE }, + + { "mail-threads-group-by", + NULL, + N_("_Group By Threads"), + "t", + N_("Threaded message list"), + G_CALLBACK (action_mail_threads_group_by_cb), + FALSE } +}; + +static GtkRadioActionEntry mail_view_entries[] = { + + /* This action represents the initial active mail view. + * It should not be visible in the UI, nor should it be + * possible to switch to it from another shell view. */ + { "mail-view-internal", + NULL, + NULL, + NULL, + NULL, + -1 }, + + { "mail-view-classic", + NULL, + N_("_Classic View"), + NULL, + N_("Show message preview below the message list"), + 0 }, + + { "mail-view-vertical", + NULL, + N_("_Vertical View"), + NULL, + N_("Show message preview alongside the message list"), + 1 } +}; + +static GtkRadioActionEntry mail_filter_entries[] = { + + { "mail-filter-all-messages", + NULL, + N_("All Messages"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_FILTER_ALL_MESSAGES }, + + { "mail-filter-important-messages", + "emblem-important", + N_("Important Messages"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_FILTER_IMPORTANT_MESSAGES }, + + { "mail-filter-last-5-days-messages", + NULL, + N_("Last 5 Days' Messages"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_FILTER_LAST_5_DAYS_MESSAGES }, + + { "mail-filter-messages-not-junk", + "mail-mark-notjunk", + N_("Messages Not Junk"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_FILTER_MESSAGES_NOT_JUNK }, + + { "mail-filter-messages-with-attachments", + "mail-attachment", + N_("Messages with Attachments"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS }, + + { "mail-filter-no-label", + NULL, + N_("No Label"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_FILTER_NO_LABEL }, + + { "mail-filter-read-messages", + "mail-read", + N_("Read Messages"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_FILTER_READ_MESSAGES }, + + { "mail-filter-recent-messages", + NULL, + N_("Recent Messages"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_FILTER_RECENT_MESSAGES }, + + { "mail-filter-unread-messages", + "mail-unread", + N_("Unread Messages"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_FILTER_UNREAD_MESSAGES } +}; + +static GtkRadioActionEntry mail_search_entries[] = { + + { "mail-search-body-contains", + NULL, + N_("Body contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SEARCH_BODY_CONTAINS }, + + { "mail-search-message-contains", + NULL, + N_("Message contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SEARCH_MESSAGE_CONTAINS }, + + { "mail-search-recipients-contain", + NULL, + N_("Recipients contain"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SEARCH_RECIPIENTS_CONTAIN }, + + { "mail-search-sender-contains", + NULL, + N_("Sender contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SEARCH_SENDER_CONTAINS }, + + { "mail-search-subject-contains", + NULL, + N_("Subject contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SEARCH_SUBJECT_CONTAINS }, + + { "mail-search-subject-or-recipients-contains", + NULL, + N_("Subject or Recipients contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SEARCH_SUBJECT_OR_RECIPIENTS_CONTAINS }, + + { "mail-search-subject-or-sender-contains", + NULL, + N_("Subject or Sender contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SEARCH_SUBJECT_OR_SENDER_CONTAINS } +}; + +static GtkRadioActionEntry mail_scope_entries[] = { + + { "mail-scope-all-accounts", + NULL, + N_("All Accounts"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SCOPE_ALL_ACCOUNTS }, + + { "mail-scope-current-account", + NULL, + N_("Current Account"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SCOPE_CURRENT_ACCOUNT }, + + { "mail-scope-current-folder", + NULL, + N_("Current Folder"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SCOPE_CURRENT_FOLDER } +}; + +void +e_mail_shell_view_actions_init (EMailShellView *mail_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellContent *shell_content; + GtkActionGroup *action_group; + GtkRadioAction *radio_action; + GConfBridge *bridge; + GObject *object; + GObject *src_object; + GObject *dst_object; + const gchar *key; + + g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + + /* Mail Actions */ + action_group = ACTION_GROUP (MAIL); + gtk_action_group_add_actions ( + action_group, mail_entries, + G_N_ELEMENTS (mail_entries), mail_shell_view); + e_action_group_add_popup_actions ( + action_group, mail_popup_entries, + G_N_ELEMENTS (mail_popup_entries)); + gtk_action_group_add_toggle_actions ( + action_group, mail_toggle_entries, + G_N_ELEMENTS (mail_toggle_entries), mail_shell_view); + gtk_action_group_add_radio_actions ( + action_group, mail_view_entries, + G_N_ELEMENTS (mail_view_entries), -1, + G_CALLBACK (action_mail_view_cb), mail_shell_view); + gtk_action_group_add_radio_actions ( + action_group, mail_search_entries, + G_N_ELEMENTS (mail_search_entries), + MAIL_SEARCH_SUBJECT_OR_SENDER_CONTAINS, + G_CALLBACK (action_mail_search_cb), mail_shell_view); + gtk_action_group_add_radio_actions ( + action_group, mail_scope_entries, + G_N_ELEMENTS (mail_scope_entries), + MAIL_SCOPE_CURRENT_FOLDER, + G_CALLBACK (action_search_scope_cb), mail_shell_view); + + radio_action = GTK_RADIO_ACTION (ACTION (MAIL_SCOPE_ALL_ACCOUNTS)); + e_shell_content_set_scope_action (shell_content, radio_action); + e_shell_content_set_scope_visible (shell_content, TRUE); + + /* Bind GObject properties for GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (ACTION (MAIL_PREVIEW)); + key = "/apps/evolution/mail/display/show_preview"; + gconf_bridge_bind_property (bridge, key, object, "active"); + + object = G_OBJECT (ACTION (MAIL_THREADS_GROUP_BY)); + key = "/apps/evolution/mail/display/thread_list"; + gconf_bridge_bind_property (bridge, key, object, "active"); + + object = G_OBJECT (ACTION (MAIL_VIEW_VERTICAL)); + key = "/apps/evolution/mail/display/layout"; + gconf_bridge_bind_property (bridge, key, object, "current-value"); + + /* Fine tuning. */ + + src_object = G_OBJECT (ACTION (MAIL_THREADS_GROUP_BY)); + + dst_object = G_OBJECT (ACTION (MAIL_FOLDER_SELECT_THREAD)); + e_binding_new (src_object, "active", dst_object, "sensitive"); + + dst_object = G_OBJECT (ACTION (MAIL_FOLDER_SELECT_SUBTHREAD)); + e_binding_new (src_object, "active", dst_object, "sensitive"); + + dst_object = G_OBJECT (ACTION (MAIL_THREADS_COLLAPSE_ALL)); + e_binding_new (src_object, "active", dst_object, "sensitive"); + + dst_object = G_OBJECT (ACTION (MAIL_THREADS_EXPAND_ALL)); + e_binding_new (src_object, "active", dst_object, "sensitive"); + + e_mutual_binding_new ( + G_OBJECT (ACTION (MAIL_PREVIEW)), "active", + G_OBJECT (shell_content), "preview-visible"); + + /* XXX The boolean sense of the GConf key is the inverse of + * the menu item, so we have to maintain two properties. */ + e_mutual_binding_new_with_negation ( + G_OBJECT (shell_content), "show-deleted", + G_OBJECT (ACTION (MAIL_HIDE_DELETED)), "active"); + + g_signal_connect ( + ACTION (GAL_SAVE_CUSTOM_VIEW), "activate", + G_CALLBACK (action_gal_save_custom_view_cb), mail_shell_view); + + g_signal_connect ( + ACTION (SEARCH_EXECUTE), "activate", + G_CALLBACK (action_search_execute_cb), mail_shell_view); +} + +/* Helper for e_mail_shell_view_update_popup_labels() */ +static void +mail_shell_view_update_label_action (GtkToggleAction *action, + MessageList *message_list, + GPtrArray *uids, + const gchar *label_tag) +{ + CamelFolder *folder; + gboolean exists = FALSE; + gboolean not_exists = FALSE; + gboolean sensitive; + guint ii; + + folder = message_list->folder; + + /* Figure out the proper label action state for the selected + * messages. If all the selected messages have the given label, + * make the toggle action active. If all the selected message + * DO NOT have the given label, make the toggle action inactive. + * If some do and some don't, make the action insensitive. */ + + for (ii = 0; ii < uids->len && (!exists || !not_exists); ii++) { + const gchar *old_label; + gchar *new_label; + + /* Check for new-style labels. */ + if (camel_folder_get_message_user_flag ( + folder, uids->pdata[ii], label_tag)) { + exists = TRUE; + continue; + } + + /* Check for old-style labels. */ + old_label = camel_folder_get_message_user_tag ( + folder, uids->pdata[ii], "label"); + if (old_label == NULL) { + not_exists = TRUE; + continue; + } + + /* Convert old-style labels ("") to "$Label". */ + new_label = g_alloca (strlen (old_label) + 10); + g_stpcpy (g_stpcpy (new_label, "$Label"), old_label); + + if (strcmp (new_label, label_tag) == 0) + exists = TRUE; + else + not_exists = TRUE; + } + + sensitive = !(exists && not_exists); + gtk_toggle_action_set_active (action, exists); + gtk_action_set_sensitive (GTK_ACTION (action), sensitive); +} + +void +e_mail_shell_view_update_popup_labels (EMailShellView *mail_shell_view) +{ + EShell *shell; + EShellSettings *shell_settings; + EShellWindow *shell_window; + EShellView *shell_view; + EMailReader *reader; + MessageList *message_list; + GtkUIManager *ui_manager; + GtkActionGroup *action_group; + GtkTreeModel *tree_model; + GtkTreeIter iter; + GPtrArray *uids; + const gchar *path; + gboolean valid; + guint merge_id; + gint ii = 0; + + g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + ui_manager = e_shell_window_get_ui_manager (shell_window); + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + tree_model = e_shell_settings_get_object ( + shell_settings, "mail-label-list-store"); + + action_group = ACTION_GROUP (MAIL_LABEL); + merge_id = mail_shell_view->priv->label_merge_id; + path = "/mail-message-popup/mail-label-menu/mail-label-actions"; + + /* Unmerge the previous menu items. */ + gtk_ui_manager_remove_ui (ui_manager, merge_id); + e_action_group_remove_all_actions (action_group); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + uids = message_list_get_selected (message_list); + + valid = gtk_tree_model_get_iter_first (tree_model, &iter); + + while (valid) { + GtkToggleAction *toggle_action; + GtkAction *action; + gchar *action_name; + gchar *stock_id; + gchar *label; + gchar *tag; + + label = e_mail_label_list_store_get_name ( + E_MAIL_LABEL_LIST_STORE (tree_model), &iter); + stock_id = e_mail_label_list_store_get_stock_id ( + E_MAIL_LABEL_LIST_STORE (tree_model), &iter); + tag = e_mail_label_list_store_get_tag ( + E_MAIL_LABEL_LIST_STORE (tree_model), &iter); + action_name = g_strdup_printf ("mail-label-%d", ii); + + /* XXX Add a tooltip! */ + toggle_action = gtk_toggle_action_new ( + action_name, label, NULL, stock_id); + + g_object_set_data_full ( + G_OBJECT (toggle_action), "tag", + tag, (GDestroyNotify) g_free); + + /* Configure the action before we connect to signals. */ + mail_shell_view_update_label_action ( + toggle_action, message_list, uids, tag); + + g_signal_connect ( + toggle_action, "toggled", + G_CALLBACK (action_mail_label_cb), mail_shell_view); + + /* The action group takes ownership of the action. */ + action = GTK_ACTION (toggle_action); + gtk_action_group_add_action (action_group, action); + g_object_unref (toggle_action); + + gtk_ui_manager_add_ui ( + ui_manager, merge_id, path, action_name, + action_name, GTK_UI_MANAGER_AUTO, FALSE); + + g_free (label); + g_free (stock_id); + g_free (action_name); + + valid = gtk_tree_model_iter_next (tree_model, &iter); + ii++; + } + + message_list_free_uids (message_list, uids); + + g_object_unref (tree_model); +} + +void +e_mail_shell_view_update_search_filter (EMailShellView *mail_shell_view) +{ + EShell *shell; + EShellContent *shell_content; + EShellSettings *shell_settings; + EShellWindow *shell_window; + EShellView *shell_view; + GtkActionGroup *action_group; + GtkRadioAction *radio_action; + GtkTreeModel *tree_model; + GtkTreeIter iter; + GList *list; + GSList *group; + gboolean valid; + gint ii = 0; + + g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + tree_model = e_shell_settings_get_object ( + shell_settings, "mail-label-list-store"); + + action_group = ACTION_GROUP (MAIL_FILTER); + e_action_group_remove_all_actions (action_group); + + /* Add the standard filter actions. */ + gtk_action_group_add_radio_actions ( + action_group, mail_filter_entries, + G_N_ELEMENTS (mail_filter_entries), + MAIL_FILTER_ALL_MESSAGES, + G_CALLBACK (action_search_filter_cb), + mail_shell_view); + + /* Retrieve the radio group from an action we just added. */ + list = gtk_action_group_list_actions (action_group); + radio_action = GTK_RADIO_ACTION (list->data); + group = gtk_radio_action_get_group (radio_action); + g_list_free (list); + + valid = gtk_tree_model_get_iter_first (tree_model, &iter); + + while (valid) { + GtkAction *action; + gchar *action_name; + gchar *stock_id; + gchar *label; + + label = e_mail_label_list_store_get_name ( + E_MAIL_LABEL_LIST_STORE (tree_model), &iter); + stock_id = e_mail_label_list_store_get_stock_id ( + E_MAIL_LABEL_LIST_STORE (tree_model), &iter); + + action_name = g_strdup_printf ("mail-filter-label-%d", ii); + radio_action = gtk_radio_action_new ( + action_name, label, NULL, stock_id, ii); + g_free (action_name); + + gtk_radio_action_set_group (radio_action, group); + group = gtk_radio_action_get_group (radio_action); + + /* The action group takes ownership of the action. */ + action = GTK_ACTION (radio_action); + gtk_action_group_add_action (action_group, action); + g_object_unref (radio_action); + + g_free (label); + g_free (stock_id); + + valid = gtk_tree_model_iter_next (tree_model, &iter); + ii++; + } + + /* Use any action in the group; doesn't matter which. */ + e_shell_content_set_filter_action (shell_content, radio_action); + + ii = MAIL_FILTER_UNREAD_MESSAGES; + e_shell_content_add_filter_separator_after (shell_content, ii); + + ii = MAIL_FILTER_READ_MESSAGES; + e_shell_content_add_filter_separator_before (shell_content, ii); + + g_object_unref (tree_model); +} diff --git a/modules/mail/e-mail-shell-view-actions.h b/modules/mail/e-mail-shell-view-actions.h new file mode 100644 index 0000000000..2a05582df8 --- /dev/null +++ b/modules/mail/e-mail-shell-view-actions.h @@ -0,0 +1,257 @@ +/* + * e-mail-shell-view-actions.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_SHELL_VIEW_ACTIONS_H +#define E_MAIL_SHELL_VIEW_ACTIONS_H + +#include + +/* Mail Actions */ +#define E_SHELL_WINDOW_ACTION_MAIL_ACCOUNT_DISABLE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-account-disable") +#define E_SHELL_WINDOW_ACTION_MAIL_ADD_SENDER(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-add-sender") +#define E_SHELL_WINDOW_ACTION_MAIL_CARET_MODE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-caret-mode") +#define E_SHELL_WINDOW_ACTION_MAIL_CHECK_FOR_JUNK(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-check-for-junk") +#define E_SHELL_WINDOW_ACTION_MAIL_CLIPBOARD_COPY(window) \ + E_SHELL_WINDOw_ACTION ((window), "mail-clipboard-copy") +#define E_SHELL_WINDOW_ACTION_MAIL_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-copy") +#define E_SHELL_WINDOW_ACTION_MAIL_CREATE_SEARCH_FOLDER(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-create-search-folder") +#define E_SHELL_WINDOW_ACTION_MAIL_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-delete") +#define E_SHELL_WINDOW_ACTION_MAIL_DOWNLOAD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-download") +#define E_SHELL_WINDOW_ACTION_MAIL_EMPTY_TRASH(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-empty-trash") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_ON_MAILING_LIST(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-on-mailing-list") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_ON_RECIPIENTS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-on-recipients") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_ON_SENDER(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-on-sender") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_ON_SUBJECT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-on-subject") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTERS_APPLY(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filters-apply") +#define E_SHELL_WINDOW_ACTION_MAIL_FIND(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-find") +#define E_SHELL_WINDOW_ACTION_MAIL_FLAG_CLEAR(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-flag-clear") +#define E_SHELL_WINDOW_ACTION_MAIL_FLAG_COMPLETED(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-flag-completed") +#define E_SHELL_WINDOW_ACTION_MAIL_FLAG_FOR_FOLLOWUP(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-flag-for-followup") +#define E_SHELL_WINDOW_ACTION_MAIL_FLUSH_OUTBOX(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-flush-outbox") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-copy") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-delete") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_EXPUNGE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-expunge") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_MARK_ALL_READ(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-mark-all-read") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_MOVE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-move") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-new") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_PROPERTIES(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-properties") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_REFRESH(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-refresh") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_RENAME(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-rename") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_SELECT_ALL(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-select-all") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_SELECT_THREAD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-select-thread") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_SELECT_SUBTHREAD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-select-subthread") +#define E_SHELL_WINDOW_ACTION_MAIL_FORWARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-forward") +#define E_SHELL_WINDOW_ACTION_MAIL_FORWARD_ATTACHED(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-forward-attached") +#define E_SHELL_WINDOW_ACTION_MAIL_FORWARD_INLINE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-forward-inline") +#define E_SHELL_WINDOW_ACTION_MAIL_FORWARD_QUOTED(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-forward-quoted") +#define E_SHELL_WINDOW_ACTION_MAIL_HIDE_DELETED(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-hide-deleted") +#define E_SHELL_WINDOW_ACTION_MAIL_HIDE_READ(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-hide-read") +#define E_SHELL_WINDOW_ACTION_MAIL_HIDE_SELECTED(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-hide-selected") +#define E_SHELL_WINDOW_ACTION_MAIL_LABEL_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-label-new") +#define E_SHELL_WINDOW_ACTION_MAIL_LABEL_NONE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-label-none") +#define E_SHELL_WINDOW_ACTION_MAIL_LOAD_IMAGES(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-load-images") +#define E_SHELL_WINDOW_ACTION_MAIL_MARK_IMPORTANT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-mark-important") +#define E_SHELL_WINDOW_ACTION_MAIL_MARK_JUNK(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-mark-junk") +#define E_SHELL_WINDOW_ACTION_MAIL_MARK_NOTJUNK(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-mark-notjunk") +#define E_SHELL_WINDOW_ACTION_MAIL_MARK_READ(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-mark-read") +#define E_SHELL_WINDOW_ACTION_MAIL_MARK_UNIMPORTANT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-mark-unimportant") +#define E_SHELL_WINDOW_ACTION_MAIL_MARK_UNREAD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-mark-unread") +#define E_SHELL_WINDOW_ACTION_MAIL_MESSAGE_EDIT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-message-edit") +#define E_SHELL_WINDOW_ACTION_MAIL_MESSAGE_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-message-new") +#define E_SHELL_WINDOW_ACTION_MAIL_MESSAGE_OPEN(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-message-open") +#define E_SHELL_WINDOW_ACTION_MAIL_MOVE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-move") +#define E_SHELL_WINDOW_ACTION_MAIL_NEXT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-next") +#define E_SHELL_WINDOW_ACTION_MAIL_NEXT_IMPORTANT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-next-important") +#define E_SHELL_WINDOW_ACTION_MAIL_NEXT_THREAD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-next-thread") +#define E_SHELL_WINDOW_ACTION_MAIL_NEXT_UNREAD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-next-unread") +#define E_SHELL_WINDOW_ACTION_MAIL_PREVIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-preview") +#define E_SHELL_WINDOW_ACTION_MAIL_PREVIOUS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-previous") +#define E_SHELL_WINDOW_ACTION_MAIL_PREVIOUS_IMPORTANT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-previous-important") +#define E_SHELL_WINDOW_ACTION_MAIL_PREVIOUS_UNREAD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-previous-unread") +#define E_SHELL_WINDOW_ACTION_MAIL_PRINT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-print") +#define E_SHELL_WINDOW_ACTION_MAIL_PRINT_PREVIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-print-preview") +#define E_SHELL_WINDOW_ACTION_MAIL_REDIRECT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-redirect") +#define E_SHELL_WINDOW_ACTION_MAIL_REPLY_ALL(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-reply-all") +#define E_SHELL_WINDOW_ACTION_MAIL_REPLY_LIST(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-reply-list") +#define E_SHELL_WINDOW_ACTION_MAIL_REPLY_SENDER(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-reply-sender") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FOLDER_FROM_MAILING_LIST(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-folder-from-mailing-list") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FOLDER_FROM_RECIPIENTS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-folder-from-recipients") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FOLDER_FROM_SENDER(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-folder-from-sender") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FOLDER_FROM_SUBJECT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-folder-from-subject") +#define E_SHELL_WINDOW_ACTION_MAIL_SELECT_ALL(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-select-all") +#define E_SHELL_WINDOW_ACTION_MAIL_SHOW_ALL_HEADERS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-show-all-headers") +#define E_SHELL_WINDOW_ACTION_MAIL_SHOW_HIDDEN(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-show-hidden") +#define E_SHELL_WINDOW_ACTION_MAIL_SHOW_SOURCE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-show-source") +#define E_SHELL_WINDOW_ACTION_MAIL_SMART_BACKWARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-smart-backward") +#define E_SHELL_WINDOW_ACTION_MAIL_SMART_FORWARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-smart-forward") +#define E_SHELL_WINDOW_ACTION_MAIL_STOP(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-stop") +#define E_SHELL_WINDOW_ACTION_MAIL_THREADS_COLLAPSE_ALL(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-threads-collapse-all") +#define E_SHELL_WINDOW_ACTION_MAIL_THREADS_EXPAND_ALL(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-threads-expand-all") +#define E_SHELL_WINDOW_ACTION_MAIL_THREADS_GROUP_BY(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-threads-group-by") +#define E_SHELL_WINDOW_ACTION_MAIL_TOOLS_FILTERS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-tools-filters") +#define E_SHELL_WINDOW_ACTION_MAIL_TOOLS_SEARCH_FOLDERS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-tools-search-folders") +#define E_SHELL_WINDOW_ACTION_MAIL_TOOLS_SUBSCRIPTIONS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-tools-subscriptions") +#define E_SHELL_WINDOW_ACTION_MAIL_UNDELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-undelete") +#define E_SHELL_WINDOW_ACTION_MAIL_VIEW_CLASSIC(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-view-classic") +#define E_SHELL_WINDOW_ACTION_MAIL_VIEW_VERTICAL(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-view-vertical") +#define E_SHELL_WINDOW_ACTION_MAIL_ZOOM_100(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-zoom-100") +#define E_SHELL_WINDOW_ACTION_MAIL_ZOOM_IN(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-zoom-in") +#define E_SHELL_WINDOW_ACTION_MAIL_ZOOM_OUT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-zoom-out") + +/* Mail Query Actions */ +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_ALL_MESSAGES(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-all-messages") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_IMPORTANT_MESSAGES(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-important-messages") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_LAST_5_DAYS_MESSAGES(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-last-5-days-messages") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_MESSAGES_NOT_JUNK(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-messages-not-junk") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-messages-with-attachments") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_NO_LABEL(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-no-label") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_READ_MESSAGES(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-read-messages") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_RECENT_MESSAGES(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-recent-messages") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_UNREAD_MESSAGES(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-unread-messages") +#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_ALL_ACCOUNTS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-scope-all-accounts") +#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_CURRENT_ACCOUNT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-scope-current-account") +#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_CURRENT_FOLDER(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-scope-current-folder") +#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_CURRENT_MESSAGE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-scope-current-message") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_BODY_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-body-contains") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_MESSAGE_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-message-contains") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_RECIPIENTS_CONTAIN(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-recipients-contain") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_SENDER_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-sender-contains") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_SUBJECT_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-subject-contains") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_SUBJECT_OR_RECIPIENTS_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-subject-or-recipients-contains") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_SUBJECT_OR_SENDER_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-subject-or-sender-contains") + +/* Action Groups */ +#define E_SHELL_WINDOW_ACTION_GROUP_MAIL(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "mail") +#define E_SHELL_WINDOW_ACTION_GROUP_MAIL_FILTER(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "mail-filter") +#define E_SHELL_WINDOW_ACTION_GROUP_MAIL_LABEL(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "mail-label") + +#endif /* E_MAIL_SHELL_VIEW_ACTIONS_H */ diff --git a/modules/mail/e-mail-shell-view-private.c b/modules/mail/e-mail-shell-view-private.c new file mode 100644 index 0000000000..f3b3b5a513 --- /dev/null +++ b/modules/mail/e-mail-shell-view-private.c @@ -0,0 +1,905 @@ +/* + * e-mail-shell-view-private.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-shell-view-private.h" + +#include "widgets/menus/gal-view-factory-etable.h" + +static void +mail_shell_view_folder_tree_selected_cb (EMailShellView *mail_shell_view, + const gchar *full_name, + const gchar *uri, + guint32 flags, + EMFolderTree *folder_tree) +{ + EShellView *shell_view; + EMailReader *reader; + gboolean folder_selected; + + shell_view = E_SHELL_VIEW (mail_shell_view); + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + + folder_selected = + !(flags & CAMEL_FOLDER_NOSELECT) && + full_name != NULL; + + if (folder_selected) + e_mail_reader_set_folder_uri (reader, uri); + else + e_mail_reader_set_folder (reader, NULL, NULL); + + e_shell_view_update_actions (shell_view); +} + +static void +mail_shell_view_folder_tree_popup_event_cb (EShellView *shell_view, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/mail-folder-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); +} + +static gboolean +mail_shell_view_key_press_event_cb (EMailShellView *mail_shell_view, + GdkEventKey *event) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkAction *action; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + if ((event->state & GDK_CONTROL_MASK) != 0) + return FALSE; + + switch (event->keyval) { + case GDK_space: + action = ACTION (MAIL_SMART_FORWARD); + break; + + case GDK_BackSpace: + action = ACTION (MAIL_SMART_BACKWARD); + break; + + default: + return FALSE; + } + + gtk_action_activate (action); + + return TRUE; +} + +static gint +mail_shell_view_message_list_key_press_cb (EMailShellView *mail_shell_view, + gint row, + ETreePath path, + gint col, + GdkEvent *event) +{ + return mail_shell_view_key_press_event_cb ( + mail_shell_view, &event->key); +} + +static gboolean +mail_shell_view_message_list_right_click_cb (EShellView *shell_view, + gint row, + ETreePath path, + gint col, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/mail-message-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); + + return TRUE; +} + +static void +mail_shell_view_reader_changed_cb (EMailShellView *mail_shell_view, + EMailReader *reader) +{ + EMailShellContent *mail_shell_content; + + mail_shell_content = mail_shell_view->priv->mail_shell_content; + e_mail_shell_content_update_view_instance (mail_shell_content); + e_mail_shell_view_update_sidebar (mail_shell_view); +} + +static void +mail_shell_view_reader_status_message_cb (EMailShellView *mail_shell_view, + const gchar *status_message) +{ + EShellView *shell_view; + EShellTaskbar *shell_taskbar; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_taskbar = e_shell_view_get_shell_taskbar (shell_view); + + e_shell_taskbar_set_message (shell_taskbar, status_message); +} + +static void +mail_shell_view_load_view_collection (EShellViewClass *shell_view_class) +{ + GalViewCollection *collection; + GalViewFactory *factory; + ETableSpecification *spec; + const gchar *base_dir; + gchar *filename; + + collection = shell_view_class->view_collection; + + base_dir = EVOLUTION_ETSPECDIR; + spec = e_table_specification_new (); + filename = g_build_filename (base_dir, ETSPEC_FILENAME, NULL); + if (!e_table_specification_load_from_file (spec, filename)) + g_critical ("Unable to load ETable specification file " + "for mail"); + g_free (filename); + + factory = gal_view_factory_etable_new (spec); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + g_object_unref (spec); + + gal_view_collection_load (collection); +} + +static void +mail_shell_view_notify_view_id_cb (EMailShellView *mail_shell_view) +{ + EMailShellContent *mail_shell_content; + GalViewInstance *view_instance; + const gchar *view_id; + + mail_shell_content = mail_shell_view->priv->mail_shell_content; + view_instance = NULL; /* FIXME */ + view_id = e_shell_view_get_view_id (E_SHELL_VIEW (mail_shell_view)); + + /* A NULL view ID implies we're in a custom view. But you can + * only get to a custom view via the "Define Views" dialog, which + * would have already modified the view instance appropriately. + * Furthermore, there's no way to refer to a custom view by ID + * anyway, since custom views have no IDs. */ + if (view_id == NULL) + return; + + gal_view_instance_set_current_view_id (view_instance, view_id); +} + +void +e_mail_shell_view_private_init (EMailShellView *mail_shell_view, + EShellViewClass *shell_view_class) +{ + if (!gal_view_collection_loaded (shell_view_class->view_collection)) + mail_shell_view_load_view_collection (shell_view_class); + + g_signal_connect ( + mail_shell_view, "notify::view-id", + G_CALLBACK (mail_shell_view_notify_view_id_cb), NULL); +} + +void +e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view) +{ + EMailShellViewPrivate *priv = mail_shell_view->priv; + EMailShellSidebar *mail_shell_sidebar; + EShell *shell; + EShellView *shell_view; + EShellBackend *shell_backend; + EShellContent *shell_content; + EShellSettings *shell_settings; + EShellSidebar *shell_sidebar; + EShellWindow *shell_window; + EMFormatHTMLDisplay *html_display; + EMFolderTree *folder_tree; + RuleContext *context; + FilterRule *rule = NULL; + GtkTreeModel *tree_model; + GtkUIManager *ui_manager; + MessageList *message_list; + EMailReader *reader; + GtkHTML *html; + const gchar *source; + guint merge_id; + gint ii = 0; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + ui_manager = e_shell_window_get_ui_manager (shell_window); + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + tree_model = e_shell_settings_get_object ( + shell_settings, "mail-label-list-store"); + + e_shell_window_add_action_group (shell_window, "mail"); + e_shell_window_add_action_group (shell_window, "mail-filter"); + e_shell_window_add_action_group (shell_window, "mail-label"); + + merge_id = gtk_ui_manager_new_merge_id (ui_manager); + priv->label_merge_id = merge_id; + + /* Cache these to avoid lots of awkward casting. */ + priv->mail_shell_backend = g_object_ref (shell_backend); + priv->mail_shell_content = g_object_ref (shell_content); + priv->mail_shell_sidebar = g_object_ref (shell_sidebar); + + reader = E_MAIL_READER (shell_content); + html_display = e_mail_reader_get_html_display (reader); + message_list = e_mail_reader_get_message_list (reader); + + mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar); + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + + html = EM_FORMAT_HTML (html_display)->html; + + g_signal_connect_swapped ( + folder_tree, "folder-selected", + G_CALLBACK (mail_shell_view_folder_tree_selected_cb), + mail_shell_view); + + g_signal_connect_swapped ( + folder_tree, "popup-event", + G_CALLBACK (mail_shell_view_folder_tree_popup_event_cb), + mail_shell_view); + + g_signal_connect_swapped ( + message_list->tree, "key-press", + G_CALLBACK (mail_shell_view_message_list_key_press_cb), + mail_shell_view); + + g_signal_connect_swapped ( + message_list->tree, "right-click", + G_CALLBACK (mail_shell_view_message_list_right_click_cb), + mail_shell_view); + + g_signal_connect_swapped ( + reader, "changed", + G_CALLBACK (mail_shell_view_reader_changed_cb), + mail_shell_view); + + /* Use the same callback as "changed". */ + g_signal_connect_swapped ( + reader, "folder-loaded", + G_CALLBACK (mail_shell_view_reader_changed_cb), + mail_shell_view); + + g_signal_connect_swapped ( + reader, "folder-loaded", + G_CALLBACK (e_mail_shell_view_restore_state), + mail_shell_view); + + g_signal_connect_swapped ( + tree_model, "row-changed", + G_CALLBACK (e_mail_shell_view_update_search_filter), + mail_shell_view); + + g_signal_connect_swapped ( + tree_model, "row-deleted", + G_CALLBACK (e_mail_shell_view_update_search_filter), + mail_shell_view); + + g_signal_connect_swapped ( + tree_model, "row-inserted", + G_CALLBACK (e_mail_shell_view_update_search_filter), + mail_shell_view); + + g_signal_connect_swapped ( + html, "key-press-event", + G_CALLBACK (mail_shell_view_key_press_event_cb), + mail_shell_view); + + g_signal_connect_swapped ( + html, "status-message", + G_CALLBACK (mail_shell_view_reader_status_message_cb), + mail_shell_view); + + e_mail_shell_view_actions_init (mail_shell_view); + e_mail_shell_view_update_search_filter (mail_shell_view); + e_mail_reader_init (reader); + + /* Populate built-in rules for search entry popup menu. + * Keep the assertions, please. If the conditions aren't + * met we're going to crash anyway, just more mysteriously. */ + context = e_shell_content_get_search_context (shell_content); + source = FILTER_SOURCE_DEMAND; + while ((rule = rule_context_next_rule (context, rule, source))) { + g_assert (ii < MAIL_NUM_SEARCH_RULES); + priv->search_rules[ii++] = g_object_ref (rule); + } + g_assert (ii == MAIL_NUM_SEARCH_RULES); +} + +void +e_mail_shell_view_private_dispose (EMailShellView *mail_shell_view) +{ + EMailShellViewPrivate *priv = mail_shell_view->priv; + gint ii; + + DISPOSE (priv->mail_shell_backend); + DISPOSE (priv->mail_shell_content); + DISPOSE (priv->mail_shell_sidebar); + + for (ii = 0; ii < MAIL_NUM_SEARCH_RULES; ii++) + DISPOSE (priv->search_rules[ii]); +} + +void +e_mail_shell_view_private_finalize (EMailShellView *mail_shell_view) +{ + /* XXX Nothing to do? */ +} + +void +e_mail_shell_view_restore_state (EMailShellView *mail_shell_view) +{ + EShellView *shell_view; + EShellContent *shell_content; + EMailReader *reader; + MessageList *message_list; + const gchar *folder_uri; + gchar *group_name; + + /* XXX Move this to EMailShellContent. */ + + g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + + reader = E_MAIL_READER (shell_content); + message_list = e_mail_reader_get_message_list (reader); + folder_uri = message_list->folder_uri; + g_return_if_fail (folder_uri != NULL); + + group_name = g_strdup_printf ("Folder %s", folder_uri); + e_shell_content_restore_state (shell_content, group_name); + g_free (group_name); +} + +void +e_mail_shell_view_execute_search (EMailShellView *mail_shell_view) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + EShellContent *shell_content; + EShellSettings *shell_settings; + EMFormatHTMLDisplay *html_display; + EMailShellContent *mail_shell_content; + MessageList *message_list; + FilterRule *rule; + EMailReader *reader; + CamelFolder *folder; + GtkAction *action; + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter tree_iter; + GString *string; + GList *iter; + GSList *search_strings = NULL; + const gchar *folder_uri; + const gchar *text; + gboolean valid; + gchar *query; + gchar *temp; + gchar *tag; + gint value; + + g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + mail_shell_content = mail_shell_view->priv->mail_shell_content; + + reader = E_MAIL_READER (shell_content); + html_display = e_mail_reader_get_html_display (reader); + message_list = e_mail_reader_get_message_list (reader); + + folder_uri = message_list->folder_uri; + folder = message_list->folder; + + /* This returns a new object reference. */ + model = e_shell_settings_get_object ( + shell_settings, "mail-label-list-store"); + + text = e_shell_content_get_search_text (shell_content); + if (text == NULL || *text == '\0') { + query = g_strdup (""); + goto filter; + } + + /* Replace variables in the selected rule with the + * current search text and extract a query string. */ + + action = ACTION (MAIL_SEARCH_SUBJECT_OR_SENDER_CONTAINS); + value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + g_return_if_fail (value >= 0 && value < MAIL_NUM_SEARCH_RULES); + rule = mail_shell_view->priv->search_rules[value]; + + for (iter = rule->parts; iter != NULL; iter = iter->next) { + FilterPart *part = iter->data; + FilterElement *element = NULL; + + if (strcmp (part->name, "subject") == 0) + element = filter_part_find_element (part, "subject"); + else if (strcmp (part->name, "body") == 0) + element = filter_part_find_element (part, "word"); + else if (strcmp (part->name, "sender") == 0) + element = filter_part_find_element (part, "sender"); + else if (strcmp (part->name, "to") == 0) + element = filter_part_find_element (part, "recipient"); + + if (strcmp (part->name, "body") == 0) { + struct _camel_search_words *words; + gint ii; + + words = camel_search_words_split ((guchar *) text); + for (ii = 0; ii < words->len; ii++) + search_strings = g_slist_prepend ( + search_strings, g_strdup ( + words->words[ii]->word)); + camel_search_words_free (words); + } + + if (element != NULL) { + FilterInput *input = FILTER_INPUT (element); + filter_input_set_value (input, text); + } + } + + string = g_string_sized_new (1024); + filter_rule_build_code (rule, string); + query = g_string_free (string, FALSE); + +filter: + + /* Apply selected filter. */ + + value = e_shell_content_get_filter_value (shell_content); + switch (value) { + case MAIL_FILTER_ALL_MESSAGES: + break; + + case MAIL_FILTER_UNREAD_MESSAGES: + temp = g_strdup_printf ( + "(and %s (match-all (not " + "(system-flag \"Seen\"))))", query); + g_free (query); + query = temp; + break; + + case MAIL_FILTER_NO_LABEL: + string = g_string_sized_new (1024); + g_string_append_printf ( + string, "(and %s (and ", query); + valid = gtk_tree_model_get_iter_first ( + model, &tree_iter); + while (valid) { + tag = e_mail_label_list_store_get_tag ( + E_MAIL_LABEL_LIST_STORE (model), + &tree_iter); + g_string_append_printf ( + string, " (match-all (not (or " + "(= (user-tag \"label\") \"%s\") " + "(user-flag \"$Label%s\") " + "(user-flag \"%s\"))))", + tag, tag, tag); + g_free (tag); + + valid = gtk_tree_model_iter_next ( + model, &tree_iter); + } + g_string_append_len (string, "))", 2); + g_free (query); + query = g_string_free (string, FALSE); + break; + + case MAIL_FILTER_READ_MESSAGES: + temp = g_strdup_printf ( + "(and %s (match-all " + "(system-flag \"Seen\")))", query); + g_free (query); + query = temp; + break; + + case MAIL_FILTER_RECENT_MESSAGES: + if (em_utils_folder_is_sent (folder, folder_uri)) + temp = g_strdup_printf ( + "(and %s (match-all " + "(> (get-sent-date) " + "(- (get-current-date) 86400))))", + query); + else + temp = g_strdup_printf ( + "(and %s (match-all " + "(> (get-received-date) " + "(- (get-current-date) 86400))))", + query); + g_free (query); + query = temp; + break; + + case MAIL_FILTER_LAST_5_DAYS_MESSAGES: + if (em_utils_folder_is_sent (folder, folder_uri)) + temp = g_strdup_printf ( + "(and %s (match-all " + "(> (get-sent-date) " + "(- (get-current-date) 432000))))", + query); + else + temp = g_strdup_printf ( + "(and %s (match-all " + "(> (get-received-date) " + "(- (get-current-date) 432000))))", + query); + g_free (query); + query = temp; + break; + + case MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS: + temp = g_strdup_printf ( + "(and %s (match-all " + "(system-flag \"Attachments\")))", query); + g_free (query); + query = temp; + break; + + case MAIL_FILTER_IMPORTANT_MESSAGES: + temp = g_strdup_printf ( + "(and %s (match-all " + "(system-flag \"Flagged\")))", query); + g_free (query); + query = temp; + break; + + case MAIL_FILTER_MESSAGES_NOT_JUNK: + temp = g_strdup_printf ( + "(and %s (match-all (not " + "(system-flag \"junk\"))))", query); + g_free (query); + query = temp; + break; + + default: + /* The action value also serves as a path for + * the label list store. That's why we number + * the label actions from zero. */ + path = gtk_tree_path_new_from_indices (value, -1); + gtk_tree_model_get_iter (model, &tree_iter, path); + gtk_tree_path_free (path); + + tag = e_mail_label_list_store_get_tag ( + E_MAIL_LABEL_LIST_STORE (model), &tree_iter); + temp = g_strdup_printf ( + "(and %s (match-all (or " + "(= (user-tag \"label\") \"%s\") " + "(user-flag \"$Label%s\") " + "(user-flag \"%s\"))))", + query, tag, tag, tag); + g_free (tag); + + g_free (query); + query = temp; + break; + } + + message_list_set_search (message_list, query); + + e_mail_shell_content_set_search_strings ( + mail_shell_content, search_strings); + + g_slist_foreach (search_strings, (GFunc) g_free, NULL); + g_slist_free (search_strings); + + g_object_unref (model); + g_free (query); +} + +/* Helper for e_mail_shell_view_create_filter_from_selected() */ +static void +mail_shell_view_create_filter_cb (CamelFolder *folder, + const gchar *uid, + CamelMimeMessage *message, + gpointer user_data) +{ + struct { + const gchar *source; + gint type; + } *filter_data = user_data; + + if (message != NULL) + filter_gui_add_from_message ( + message, filter_data->source, filter_data->type); + + g_free (filter_data); +} + +void +e_mail_shell_view_create_filter_from_selected (EMailShellView *mail_shell_view, + gint filter_type) +{ + EMailReader *reader; + MessageList *message_list; + CamelFolder *folder; + const gchar *filter_source; + const gchar *folder_uri; + GPtrArray *uids; + + struct { + const gchar *source; + gint type; + } *filter_data; + + g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + folder_uri = message_list->folder_uri; + folder = message_list->folder; + + if (em_utils_folder_is_sent (folder, folder_uri)) + filter_source = FILTER_SOURCE_OUTGOING; + else if (em_utils_folder_is_outbox (folder, folder_uri)) + filter_source = FILTER_SOURCE_OUTGOING; + else + filter_source = FILTER_SOURCE_INCOMING; + + uids = message_list_get_selected (message_list); + + if (uids->len == 1) { + filter_data = g_malloc (sizeof (*filter_data)); + filter_data->source = filter_source; + filter_data->type = filter_type; + + mail_get_message ( + folder, uids->pdata[0], + mail_shell_view_create_filter_cb, + filter_data, mail_msg_unordered_push); + } + + em_utils_uids_free (uids); +} + +/* Helper for e_mail_shell_view_create_vfolder_from_selected() */ +static void +mail_shell_view_create_vfolder_cb (CamelFolder *folder, + const gchar *uid, + CamelMimeMessage *message, + gpointer user_data) +{ + struct { + gchar *uri; + gint type; + } *vfolder_data = user_data; + + if (message != NULL) + vfolder_gui_add_from_message ( + message, vfolder_data->type, vfolder_data->uri); + + g_free (vfolder_data->uri); + g_free (vfolder_data); +} + +void +e_mail_shell_view_create_vfolder_from_selected (EMailShellView *mail_shell_view, + gint vfolder_type) +{ + EMailReader *reader; + MessageList *message_list; + CamelFolder *folder; + const gchar *folder_uri; + GPtrArray *uids; + + struct { + gchar *uri; + gint type; + } *vfolder_data; + + g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + folder_uri = message_list->folder_uri; + folder = message_list->folder; + + uids = message_list_get_selected (message_list); + + if (uids->len == 1) { + vfolder_data = g_malloc (sizeof (*vfolder_data)); + vfolder_data->uri = g_strdup (folder_uri); + vfolder_data->type = vfolder_type; + + mail_get_message ( + folder, uids->pdata[0], + mail_shell_view_create_vfolder_cb, + vfolder_data, mail_msg_unordered_push); + } + + em_utils_uids_free (uids); +} + +void +e_mail_shell_view_update_sidebar (EMailShellView *mail_shell_view) +{ + EMailShellContent *mail_shell_content; + EShellSidebar *shell_sidebar; + EShellView *shell_view; + EMailReader *reader; + MessageList *message_list; + CamelStore *local_store; + CamelFolder *folder; + GPtrArray *selected; + GString *buffer; + const gchar *display_name; + const gchar *folder_uri; + gchar *folder_name; + gchar *title; + guint32 num_deleted; + guint32 num_junked; + guint32 num_junked_not_deleted; + guint32 num_unread; + guint32 num_visible; + + g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); + + mail_shell_content = mail_shell_view->priv->mail_shell_content; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + + reader = E_MAIL_READER (mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + folder_uri = message_list->folder_uri; + folder = message_list->folder; + + local_store = e_mail_local_get_store (); + + /* If no folder is selected, reset the sidebar banners + * to their default values and stop. */ + if (folder == NULL) { + GtkAction *action; + gchar *label; + + action = e_shell_view_get_action (shell_view); + + g_object_get (action, "label", &label, NULL); + e_shell_sidebar_set_secondary_text (shell_sidebar, NULL); + e_shell_view_set_title (shell_view, label); + g_free (label); + + return; + } + + camel_object_get ( + folder, NULL, + CAMEL_FOLDER_NAME, &folder_name, + CAMEL_FOLDER_DELETED, &num_deleted, + CAMEL_FOLDER_JUNKED, &num_junked, + CAMEL_FOLDER_JUNKED_NOT_DELETED, &num_junked_not_deleted, + CAMEL_FOLDER_UNREAD, &num_unread, + CAMEL_FOLDER_VISIBLE, &num_visible, + NULL); + + buffer = g_string_sized_new (256); + selected = message_list_get_selected (message_list); + + if (selected->len > 1) + g_string_append_printf ( + buffer, ngettext ("%d selected, ", "%d selected, ", + selected->len), selected->len); + + if (CAMEL_IS_VTRASH_FOLDER (folder)) { + CamelVTrashFolder *trash_folder; + + trash_folder = (CamelVTrashFolder *) folder; + + /* "Trash" folder */ + if (trash_folder->type == CAMEL_VTRASH_FOLDER_TRASH) + g_string_append_printf ( + buffer, ngettext ("%d deleted", + "%d deleted", num_deleted), num_deleted); + + /* "Junk" folder (hide deleted messages) */ + else if (e_mail_reader_get_hide_deleted (reader)) + g_string_append_printf ( + buffer, ngettext ("%d junk", + "%d junk", num_junked_not_deleted), + num_junked_not_deleted); + + /* "Junk" folder (show deleted messages) */ + else + g_string_append_printf ( + buffer, ngettext ("%d junk", "%d junk", + num_junked), num_junked); + + /* "Drafts" folder */ + } else if (em_utils_folder_is_drafts (folder, folder_uri)) { + g_string_append_printf ( + buffer, ngettext ("%d draft", "%d drafts", + num_visible), num_visible); + + /* "Outbox" folder */ + } else if (em_utils_folder_is_outbox (folder, folder_uri)) { + g_string_append_printf ( + buffer, ngettext ("%d unsent", "%d unsent", + num_visible), num_visible); + + /* "Sent" folder */ + } else if (em_utils_folder_is_sent (folder, folder_uri)) { + g_string_append_printf ( + buffer, ngettext ("%d sent", "%d sent", + num_visible), num_visible); + + /* Normal folder */ + } else { + if (!e_mail_reader_get_hide_deleted (reader)) + num_visible += + num_deleted - num_junked + + num_junked_not_deleted; + + if (num_unread > 0 && selected->len <= 1) + g_string_append_printf ( + buffer, ngettext ("%d unread, ", + "%d unread, ", num_unread), num_unread); + g_string_append_printf ( + buffer, ngettext ("%d total", "%d total", + num_visible), num_visible); + } + + message_list_free_uids (message_list, selected); + + /* Choose a suitable folder name for displaying. */ + if (folder->parent_store == local_store && ( + strcmp (folder_name, "Drafts") == 0 || + strcmp (folder_name, "Inbox") == 0 || + strcmp (folder_name, "Outbox") == 0 || + strcmp (folder_name, "Sent") == 0 || + strcmp (folder_name, "Templates") == 0)) + display_name = _(folder_name); + else if (strcmp (folder_name, "INBOX") == 0) + display_name = _("Inbox"); + else + display_name = folder_name; + + title = g_strdup_printf ("%s (%s)", display_name, buffer->str); + e_shell_sidebar_set_secondary_text (shell_sidebar, buffer->str); + e_shell_view_set_title (shell_view, title); + g_free (title); + + camel_object_free (folder, CAMEL_FOLDER_NAME, folder_name); + g_string_free (buffer, TRUE); +} diff --git a/modules/mail/e-mail-shell-view-private.h b/modules/mail/e-mail-shell-view-private.h new file mode 100644 index 0000000000..988d494219 --- /dev/null +++ b/modules/mail/e-mail-shell-view-private.h @@ -0,0 +1,173 @@ +/* + * e-mail-shell-view-private.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_SHELL_VIEW_PRIVATE_H +#define E_MAIL_SHELL_VIEW_PRIVATE_H + +#include "e-mail-shell-view.h" + +#include +#include +#include +#include +#include +#include /* for camel_search_word */ + +#include "e-util/e-util.h" +#include "e-util/e-binding.h" +#include "e-util/gconf-bridge.h" +#include "e-util/e-account-utils.h" +#include "filter/filter-part.h" +#include "widgets/misc/e-popup-action.h" +#include "widgets/menus/gal-view-instance.h" + +#include "e-mail-label-dialog.h" +#include "e-mail-label-list-store.h" +#include "e-mail-local.h" +#include "e-mail-reader.h" +#include "e-mail-store.h" +#include "em-composer-utils.h" +#include "em-folder-properties.h" +#include "em-folder-selector.h" +#include "em-folder-utils.h" +#include "em-subscribe-editor.h" +#include "em-utils.h" +#include "mail-autofilter.h" +#include "mail-config.h" +#include "mail-ops.h" +#include "mail-send-recv.h" +#include "mail-vfolder.h" + +#include "e-mail-shell-backend.h" +#include "e-mail-shell-content.h" +#include "e-mail-shell-sidebar.h" +#include "e-mail-shell-view-actions.h" + +#define E_MAIL_SHELL_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_SHELL_VIEW, EMailShellViewPrivate)) + +/* Shorthand, requires a variable named "shell_window". */ +#define ACTION(name) \ + (E_SHELL_WINDOW_ACTION_##name (shell_window)) +#define ACTION_GROUP(name) \ + (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) + +/* For use in dispose() methods. */ +#define DISPOSE(obj) \ + G_STMT_START { \ + if ((obj) != NULL) { g_object_unref (obj); (obj) = NULL; } \ + } G_STMT_END + +/* ETable Specifications */ +#define ETSPEC_FILENAME "message-list.etspec" + +G_BEGIN_DECLS + +/* Filter items are displayed in ascending order. + * Labels are numbered from zero, so subsequent items must have + * sufficiently large values. Unfortunately this introduces an + * arbitrary upper bound on labels. */ +enum { + MAIL_FILTER_ALL_MESSAGES = -3, + MAIL_FILTER_UNREAD_MESSAGES = -2, + MAIL_FILTER_NO_LABEL = -1, + /* Labels go here */ + MAIL_FILTER_READ_MESSAGES = 5000, + MAIL_FILTER_RECENT_MESSAGES = 5001, + MAIL_FILTER_LAST_5_DAYS_MESSAGES = 5002, + MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS = 5003, + MAIL_FILTER_IMPORTANT_MESSAGES = 5004, + MAIL_FILTER_MESSAGES_NOT_JUNK = 5005 +}; + +/* Search items are displayed in ascending order. */ +enum { + MAIL_SEARCH_SUBJECT_OR_SENDER_CONTAINS, + MAIL_SEARCH_SUBJECT_OR_RECIPIENTS_CONTAINS, + MAIL_SEARCH_RECIPIENTS_CONTAIN, + MAIL_SEARCH_MESSAGE_CONTAINS, + MAIL_SEARCH_SUBJECT_CONTAINS, + MAIL_SEARCH_SENDER_CONTAINS, + MAIL_SEARCH_BODY_CONTAINS, + MAIL_NUM_SEARCH_RULES +}; + +/* Scope items are displayed in ascending order. */ +enum { + MAIL_SCOPE_CURRENT_FOLDER, + MAIL_SCOPE_CURRENT_ACCOUNT, + MAIL_SCOPE_ALL_ACCOUNTS +}; + +struct _EMailShellViewPrivate { + + /*** Other Stuff ***/ + + /* These are just for convenience. */ + EMailShellBackend *mail_shell_backend; + EMailShellContent *mail_shell_content; + EMailShellSidebar *mail_shell_sidebar; + + /* For UI merging and unmerging. */ + guint merge_id; + guint label_merge_id; + + /* Filter rules correspond to the search entry menu. */ + FilterRule *search_rules[MAIL_NUM_SEARCH_RULES]; + + guint show_deleted : 1; +}; + +void e_mail_shell_view_private_init + (EMailShellView *mail_shell_view, + EShellViewClass *shell_view_class); +void e_mail_shell_view_private_constructed + (EMailShellView *mail_shell_view); +void e_mail_shell_view_private_dispose + (EMailShellView *mail_shell_view); +void e_mail_shell_view_private_finalize + (EMailShellView *mail_shell_view); + +/* Private Utilities */ + +void e_mail_shell_view_actions_init + (EMailShellView *mail_shell_view); +void e_mail_shell_view_restore_state + (EMailShellView *mail_shell_view); +void e_mail_shell_view_execute_search + (EMailShellView *mail_shell_view); +void e_mail_shell_view_create_filter_from_selected + (EMailShellView *mail_shell_view, + gint filter_type); +void e_mail_shell_view_create_vfolder_from_selected + (EMailShellView *mail_shell_view, + gint vfolder_type); +void e_mail_shell_view_update_popup_labels + (EMailShellView *mail_shell_view); +void e_mail_shell_view_update_search_filter + (EMailShellView *mail_shell_view); +void e_mail_shell_view_update_sidebar + (EMailShellView *mail_shell_view); + +G_END_DECLS + +#endif /* E_MAIL_SHELL_VIEW_PRIVATE_H */ diff --git a/modules/mail/e-mail-shell-view.c b/modules/mail/e-mail-shell-view.c new file mode 100644 index 0000000000..8d8b4aa2b3 --- /dev/null +++ b/modules/mail/e-mail-shell-view.c @@ -0,0 +1,260 @@ +/* + * e-mail-shell-view.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-shell-view-private.h" + +static gpointer parent_class; +static GType mail_shell_view_type; + +static void +mail_shell_view_dispose (GObject *object) +{ + e_mail_shell_view_private_dispose (E_MAIL_SHELL_VIEW (object)); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +mail_shell_view_finalize (GObject *object) +{ + e_mail_shell_view_private_finalize (E_MAIL_SHELL_VIEW (object)); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +mail_shell_view_constructed (GObject *object) +{ + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + e_mail_shell_view_private_constructed (E_MAIL_SHELL_VIEW (object)); +} + +static void +mail_shell_view_toggled (EShellView *shell_view) +{ + EMailShellViewPrivate *priv; + EShellWindow *shell_window; + GtkUIManager *ui_manager; + const gchar *basename; + gboolean view_is_active; + + /* Chain up to parent's toggled() method. */ + E_SHELL_VIEW_CLASS (parent_class)->toggled (shell_view); + + priv = E_MAIL_SHELL_VIEW_GET_PRIVATE (shell_view); + + shell_window = e_shell_view_get_shell_window (shell_view); + ui_manager = e_shell_window_get_ui_manager (shell_window); + view_is_active = e_shell_view_is_active (shell_view); + basename = E_MAIL_READER_UI_DEFINITION; + + if (view_is_active && priv->merge_id == 0) { + priv->merge_id = e_load_ui_definition (ui_manager, basename); + e_mail_reader_create_charset_menu ( + E_MAIL_READER (priv->mail_shell_content), + ui_manager, priv->merge_id); + } else if (!view_is_active && priv->merge_id != 0) { + gtk_ui_manager_remove_ui (ui_manager, priv->merge_id); + priv->merge_id = 0; + } + + gtk_ui_manager_ensure_update (ui_manager); +} + +static void +mail_shell_view_update_actions (EShellView *shell_view) +{ + EMailShellView *mail_shell_view; + EMailShellSidebar *mail_shell_sidebar; + EShellContent *shell_content; + EShellSidebar *shell_sidebar; + EShellWindow *shell_window; + EMFolderTree *folder_tree; + EAccount *account = NULL; + GtkAction *action; + const gchar *label; + gchar *uri; + gboolean sensitive; + guint32 state; + + /* Be descriptive. */ + gboolean account_is_groupwise; + gboolean folder_allows_children; + gboolean folder_can_be_deleted; + gboolean folder_is_junk; + gboolean folder_is_outbox; + gboolean folder_is_store; + gboolean folder_is_trash; + + mail_shell_view = E_MAIL_SHELL_VIEW (shell_view); + + shell_window = e_shell_view_get_shell_window (shell_view); + + shell_content = e_shell_view_get_shell_content (shell_view); + e_mail_reader_update_actions (E_MAIL_READER (shell_content)); + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + state = e_shell_sidebar_check_state (shell_sidebar); + + folder_allows_children = + (state & E_MAIL_SHELL_SIDEBAR_FOLDER_ALLOWS_CHILDREN); + folder_can_be_deleted = + (state & E_MAIL_SHELL_SIDEBAR_FOLDER_CAN_DELETE); + folder_is_junk = + (state & E_MAIL_SHELL_SIDEBAR_FOLDER_IS_JUNK); + folder_is_outbox = + (state & E_MAIL_SHELL_SIDEBAR_FOLDER_IS_OUTBOX); + folder_is_store = + (state & E_MAIL_SHELL_SIDEBAR_FOLDER_IS_STORE); + folder_is_trash = + (state & E_MAIL_SHELL_SIDEBAR_FOLDER_IS_TRASH); + + uri = em_folder_tree_get_selected_uri (folder_tree); + if (uri != NULL) { + account = mail_config_get_account_by_source_url (uri); + + /* FIXME This belongs in a GroupWise plugin. */ + account_is_groupwise = + (g_strrstr (uri, "groupwise://") != NULL) && + account != NULL && account->parent_uid != NULL; + + g_free (uri); + } + + action = ACTION (MAIL_ACCOUNT_DISABLE); + sensitive = (account != NULL) && folder_is_store; + if (account_is_groupwise) + label = _("Proxy _Logout"); + else + label = _("_Disable Account"); + gtk_action_set_sensitive (action, sensitive); + g_object_set (action, "label", label, NULL); + + action = ACTION (MAIL_EMPTY_TRASH); + sensitive = folder_is_trash; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MAIL_FLUSH_OUTBOX); + sensitive = folder_is_outbox; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MAIL_FOLDER_COPY); + sensitive = !folder_is_store; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MAIL_FOLDER_DELETE); + sensitive = !folder_is_store && folder_can_be_deleted; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MAIL_FOLDER_MOVE); + sensitive = !folder_is_store && folder_can_be_deleted; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MAIL_FOLDER_NEW); + sensitive = folder_allows_children; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MAIL_FOLDER_PROPERTIES); + sensitive = !folder_is_store; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MAIL_FOLDER_REFRESH); + sensitive = !folder_is_store; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MAIL_FOLDER_RENAME); + sensitive = !folder_is_store && folder_can_be_deleted; + gtk_action_set_sensitive (action, sensitive); + + e_mail_shell_view_update_popup_labels (mail_shell_view); +} + +static void +mail_shell_view_class_init (EMailShellViewClass *class, + GTypeModule *type_module) +{ + GObjectClass *object_class; + EShellViewClass *shell_view_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMailShellViewPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->dispose = mail_shell_view_dispose; + object_class->finalize = mail_shell_view_finalize; + object_class->constructed = mail_shell_view_constructed; + + shell_view_class = E_SHELL_VIEW_CLASS (class); + shell_view_class->label = _("Mail"); + shell_view_class->icon_name = "evolution-mail"; + shell_view_class->ui_definition = "evolution-mail.ui"; + shell_view_class->ui_manager_id = "org.gnome.evolution.mail"; + shell_view_class->search_options = "/mail-search-options"; + shell_view_class->search_rules = "searchtypes.xml"; + shell_view_class->new_shell_content = e_mail_shell_content_new; + shell_view_class->new_shell_sidebar = e_mail_shell_sidebar_new; + shell_view_class->toggled = mail_shell_view_toggled; + shell_view_class->update_actions = mail_shell_view_update_actions; +} + +static void +mail_shell_view_init (EMailShellView *mail_shell_view, + EShellViewClass *shell_view_class) +{ + mail_shell_view->priv = + E_MAIL_SHELL_VIEW_GET_PRIVATE (mail_shell_view); + + e_mail_shell_view_private_init (mail_shell_view, shell_view_class); +} + +GType +e_mail_shell_view_get_type (void) +{ + return mail_shell_view_type; +} + +void +e_mail_shell_view_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (EMailShellViewClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) mail_shell_view_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMailShellView), + 0, /* n_preallocs */ + (GInstanceInitFunc) mail_shell_view_init, + NULL /* value_table */ + }; + + mail_shell_view_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_VIEW, + "EMailShellView", &type_info, 0); +} diff --git a/modules/mail/e-mail-shell-view.h b/modules/mail/e-mail-shell-view.h new file mode 100644 index 0000000000..d20bde74a6 --- /dev/null +++ b/modules/mail/e-mail-shell-view.h @@ -0,0 +1,72 @@ +/* + * e-mail-shell-view.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_SHELL_VIEW_H +#define E_MAIL_SHELL_VIEW_H + +#include + +/* Standard GObject macros */ +#define E_TYPE_MAIL_SHELL_VIEW \ + (e_mail_shell_view_get_type ()) +#define E_MAIL_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_SHELL_VIEW, EMailShellView)) +#define E_MAIL_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_SHELL_VIEW, EMailShellViewClass)) +#define E_IS_MAIL_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_SHELL_VIEW)) +#define E_IS_MAIL_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_SHELL_VIEW)) +#define E_MAIL_SHELL_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_SHELL_VIEW, EMailShellViewClass)) + +G_BEGIN_DECLS + +typedef struct _EMailShellView EMailShellView; +typedef struct _EMailShellViewClass EMailShellViewClass; +typedef struct _EMailShellViewPrivate EMailShellViewPrivate; + +struct _EMailShellView { + EShellView parent; + EMailShellViewPrivate *priv; +}; + +struct _EMailShellViewClass { + EShellViewClass parent_class; +}; + +GType e_mail_shell_view_get_type (void); +void e_mail_shell_view_register_type + (GTypeModule *type_module); +gboolean e_mail_shell_view_get_show_deleted + (EMailShellView *mail_shell_view); +void e_mail_shell_view_set_show_deleted + (EMailShellView *mail_shell_view, + gboolean show_deleted); + +G_END_DECLS + +#endif /* E_MAIL_SHELL_VIEW_H */ diff --git a/modules/mail/em-account-editor.c b/modules/mail/em-account-editor.c new file mode 100644 index 0000000000..188a2d475f --- /dev/null +++ b/modules/mail/em-account-editor.c @@ -0,0 +1,3113 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Dan Winship + * Jeffrey Stedfast + * Michael Zucchi + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/* + work before merge can occur: + + verify behaviour. + work out what to do with the startup druid. + + also need to work out: + how to remove unecessary items from a service url once + configured (removing settings from other types). + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include + +#include + +#include + +#include +#include + +#include "e-util/e-error.h" +#include "e-util/e-account-utils.h" +#include "e-util/e-signature-list.h" +#include "e-util/e-signature-utils.h" +#include "e-util/e-util-private.h" +#include "misc/e-signature-editor.h" + +#include "e-mail-local.h" +#include "em-config.h" +#include "em-folder-selection-button.h" +#include "em-account-editor.h" +#include "mail-session.h" +#include "mail-send-recv.h" +#include "em-utils.h" +#include "em-composer-prefs.h" +#include "mail-config.h" +#include "mail-ops.h" +#include "mail-mt.h" + +#if defined (HAVE_NSS) +#include "smime/gui/e-cert-selector.h" +#endif + +#define d(x) + +/* econfig item for the extra config hings */ +struct _receive_options_item { + EMConfigItem item; + + /* Only CAMEL_PROVIDER_CONF_ENTRYs GtkEntrys are stored here. + The auto-detect camel provider code will probably be removed */ + GHashTable *extra_table; +}; + +typedef struct _EMAccountEditorService { + EMAccountEditor *emae; /* parent pointer, for callbacks */ + + /* NOTE: keep all widgets together, first frame last check_dialog */ + GtkWidget *frame; + GtkWidget *container; + + GtkComboBox *providers; + + GtkLabel *description; + GtkLabel *hostlabel; + GtkEntry *hostname; + GtkLabel *userlabel; + GtkEntry *username; + GtkEntry *path; + GtkLabel *pathlabel; + GtkWidget *pathentry; + + GtkWidget *ssl_frame; + GtkComboBox *use_ssl; + GtkWidget *ssl_hbox; + GtkWidget *no_ssl; + + GtkWidget *auth_frame; + GtkComboBox *authtype; + + GtkWidget *authitem; + GtkToggleButton *remember; + GtkButton *check_supported; + GtkToggleButton *needs_auth; + + GtkWidget *check_dialog; + gint check_id; + + GList *authtypes; /* if "Check supported" */ + CamelProvider *provider; + CamelProviderType type; + + gint auth_changed_id; +} EMAccountEditorService; + +struct _EMAccountEditorPrivate { + struct _EMConfig *config; + GList *providers; + + /* signatures */ + GtkComboBox *signatures_dropdown; + guint sig_added_id; + guint sig_removed_id; + guint sig_changed_id; + const gchar *sig_uid; + + /* incoming mail */ + EMAccountEditorService source; + + /* extra incoming config */ + CamelProvider *extra_provider; + GSList *extra_items; /* this is freed by the econfig automatically */ + + /* outgoing mail */ + EMAccountEditorService transport; + + /* account management */ + GtkEntry *identity_entries[5]; + GtkToggleButton *default_account; + GtkWidget *management_frame; + + /* special folders */ + GtkButton *drafts_folder_button; + GtkButton *sent_folder_button; + GtkButton *restore_folders_button; + + /* Security */ + GtkEntry *pgp_key; + GtkToggleButton *pgp_encrypt_to_self; + GtkToggleButton *pgp_always_sign; + GtkToggleButton *pgp_no_imip_sign; + GtkToggleButton *pgp_always_trust; + + GtkToggleButton *smime_sign_default; + GtkEntry *smime_sign_key; + GtkButton *smime_sign_key_select; + GtkButton *smime_sign_key_clear; + GtkButton *smime_sign_select; + GtkToggleButton *smime_encrypt_default; + GtkToggleButton *smime_encrypt_to_self; + GtkEntry *smime_encrypt_key; + GtkButton *smime_encrypt_key_select; + GtkButton *smime_encrypt_key_clear; + + /* for e-config callbacks, each page sets up its widgets, then they are dealed out by the get_widget callback in order*/ + GtkWidget *widgets[5]; + const gchar *widgets_name[5]; + gint widgets_index; + + /* for druid page preparation */ + guint identity_set:1; + guint receive_set:1; + guint management_set:1; +}; + +static void emae_refresh_authtype(EMAccountEditor *emae, EMAccountEditorService *service); +static void em_account_editor_construct(EMAccountEditor *emae, EAccount *account, em_account_editor_t type, const gchar *id); +static void emae_account_folder_changed(EMFolderSelectionButton *folder, EMAccountEditor *emae); +static GtkVBoxClass *emae_parent; + +static void +emae_init(GObject *o) +{ + EMAccountEditor *emae = (EMAccountEditor *)o; + + emae->priv = g_malloc0(sizeof(*emae->priv)); + + emae->priv->source.emae = emae; + emae->priv->transport.emae = emae; +} + +static void +emae_finalise(GObject *o) +{ + EMAccountEditor *emae = (EMAccountEditor *)o; + EMAccountEditorPrivate *p = emae->priv; + + if (p->sig_added_id) { + ESignatureList *signatures = e_get_signature_list (); + + g_signal_handler_disconnect(signatures, p->sig_added_id); + g_signal_handler_disconnect(signatures, p->sig_removed_id); + g_signal_handler_disconnect(signatures, p->sig_changed_id); + } + + g_list_free(p->source.authtypes); + g_list_free(p->transport.authtypes); + + g_list_free(p->providers); + g_free(p); + + g_object_unref(emae->account); + if (emae->original) + g_object_unref(emae->original); + + ((GObjectClass *)emae_parent)->finalize(o); +} + +static void +emae_class_init(GObjectClass *klass) +{ + klass->finalize = emae_finalise; +} + +GType +em_account_editor_get_type(void) +{ + static GType type = 0; + + if (type == 0) { + static const GTypeInfo info = { + sizeof(EMAccountEditorClass), + NULL, NULL, + (GClassInitFunc)emae_class_init, + NULL, NULL, + sizeof(EMAccountEditor), 0, + (GInstanceInitFunc)emae_init + }; + emae_parent = g_type_class_ref(G_TYPE_OBJECT); + type = g_type_register_static(G_TYPE_OBJECT, "EMAccountEditor", &info, 0); + } + + return type; +} + +/** + * em_account_editor_new: + * @account: + * @type: + * + * Create a new account editor. If @account is NULL then this is to + * create a new account, else @account is copied to a working + * structure and is for editing an existing account. + * + * Return value: + **/ +EMAccountEditor *em_account_editor_new(EAccount *account, em_account_editor_t type, const gchar *id) +{ + EMAccountEditor *emae = g_object_new(em_account_editor_get_type(), NULL); + + em_account_editor_construct(emae, account, type, id); + + return emae; +} + +/** + * em_account_editor_new_for_pages: + * @account: + * @type: + * + * Create a new account editor. If @account is NULL then this is to + * create a new account, else @account is copied to a working + * structure and is for editing an existing account. + * + * Return value: + **/ +EMAccountEditor *em_account_editor_new_for_pages(EAccount *account, em_account_editor_t type, gchar *id, GtkWidget **pages) +{ + EMAccountEditor *emae = g_object_new(em_account_editor_get_type(), NULL); + emae->pages = pages; + em_account_editor_construct(emae, account, type, id); + + return emae; +} + +/* ********************************************************************** */ + +static struct { + const gchar *label; + const gchar *value; +} ssl_options[] = { + /* Translators: This string is a "Use secure connection" option for + the Mailer. It will not use an encrypted connection. */ + { N_("No encryption"), "never" }, + /* Translators: This string is a "Use secure connection" option for + the Mailer. TLS (Transport Layer Security) is commonly known by + this abbreviation. */ + { N_("TLS encryption"), "when-possible" }, + /* Translators: This string is a "Use secure connection" option for + the Mailer. SSL (Secure Sockets Layer) is commonly known by this + abbreviation. */ + { N_("SSL encryption"), "always" } +}; + +#define num_ssl_options (sizeof (ssl_options) / sizeof (ssl_options[0])) + +static gboolean +is_email (const gchar *address) +{ + /* This is supposed to check if the address's domain could be + an FQDN but alas, it's not worth the pain and suffering. */ + const gchar *at; + + at = strchr (address, '@'); + /* make sure we have an '@' and that it's not the first or last gchar */ + if (!at || at == address || *(at + 1) == '\0') + return FALSE; + + return TRUE; +} + +static CamelURL * +emae_account_url(EMAccountEditor *emae, gint urlid) +{ + CamelURL *url = NULL; + const gchar *uri; + + uri = e_account_get_string(emae->account, urlid); + + if (uri && uri[0]) + url = camel_url_new(uri, NULL); + + if (url == NULL) { + url = camel_url_new("dummy:", NULL); + camel_url_set_protocol(url, NULL); + } + + return url; +} + +/* ********************************************************************** */ +static void +emae_license_state(GtkToggleButton *button, GtkDialog *dialog) +{ + gtk_dialog_set_response_sensitive(dialog, GTK_RESPONSE_ACCEPT, + gtk_toggle_button_get_active(button)); +} + +static gboolean +emae_load_text(GtkTextView *view, const gchar *filename) +{ + FILE *fd; + gchar filebuf[1024]; + GtkTextIter iter; + GtkTextBuffer *buffer; + gint count; + + g_return_val_if_fail (filename != NULL , FALSE); + + fd = g_fopen (filename, "r"); + if (fd) { + buffer = gtk_text_buffer_new (NULL); + gtk_text_buffer_get_start_iter (buffer, &iter); + while (!feof (fd) && !ferror (fd)) { + count = fread (filebuf, 1, sizeof (filebuf), fd); + gtk_text_buffer_insert (buffer, &iter, filebuf, count); + } + + gtk_text_view_set_buffer(GTK_TEXT_VIEW (view), GTK_TEXT_BUFFER(buffer)); + fclose (fd); + } + + return fd != NULL; +} + +static gboolean +emae_display_license(EMAccountEditor *emae, CamelProvider *prov) +{ + GladeXML *xml; + GtkWidget *w, *dialog; + gchar *tmp; + GtkResponseType response = GTK_RESPONSE_NONE; + gchar *gladefile; + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + "mail-dialogs.glade", + NULL); + xml = glade_xml_new (gladefile, "license_dialog", NULL); + g_free (gladefile); + + dialog = glade_xml_get_widget(xml, "license_dialog"); + gtk_dialog_set_response_sensitive((GtkDialog *)dialog, GTK_RESPONSE_ACCEPT, FALSE); + tmp = g_strdup_printf(_("%s License Agreement"), prov->license); + gtk_window_set_title((GtkWindow *)dialog, tmp); + g_free(tmp); + + g_signal_connect(glade_xml_get_widget(xml, "license_checkbutton"), + "toggled", G_CALLBACK(emae_license_state), dialog); + + tmp = g_strdup_printf(_("\nPlease read carefully the license agreement\n" + "for %s displayed below\n" + "and tick the check box for accepting it\n"), prov->license); + gtk_label_set_text((GtkLabel *)glade_xml_get_widget(xml, "license_top_label"), tmp); + g_free(tmp); + + w = glade_xml_get_widget(xml, "license_textview"); + if (emae_load_text((GtkTextView *)w, prov->license_file)) { + gtk_text_view_set_editable((GtkTextView *)w, FALSE); + response = gtk_dialog_run((GtkDialog *)dialog); + } else { + e_error_run(emae->editor ? (GtkWindow *)gtk_widget_get_toplevel(emae->editor) : NULL, + "mail:no-load-license", prov->license_file, NULL); + } + + gtk_widget_destroy(dialog); + g_object_unref(xml); + + return (response == GTK_RESPONSE_ACCEPT); +} + +static gboolean +emae_check_license(EMAccountEditor *emae, CamelProvider *prov) +{ + gboolean accepted = TRUE; + + if (prov->flags & CAMEL_PROVIDER_HAS_LICENSE) { + GConfClient *gconf = mail_config_get_gconf_client(); + GSList *providers_list, *l; + + providers_list = gconf_client_get_list (gconf, "/apps/evolution/mail/licenses", GCONF_VALUE_STRING, NULL); + + for (l = providers_list, accepted = FALSE; l && !accepted; l = g_slist_next(l)) + accepted = (strcmp((gchar *)l->data, prov->protocol) == 0); + + if (!accepted + && (accepted = emae_display_license(emae, prov)) == TRUE) { + providers_list = g_slist_append(providers_list, g_strdup(prov->protocol)); + gconf_client_set_list(gconf, + "/apps/evolution/mail/licenses", + GCONF_VALUE_STRING, + providers_list, NULL); + } + + g_slist_foreach(providers_list, (GFunc)g_free, NULL); + g_slist_free(providers_list); + } + + return accepted; +} + +static void +default_folders_clicked (GtkButton *button, gpointer user_data) +{ + EMAccountEditor *emae = user_data; + const gchar *uri; + + uri = e_mail_local_get_folder_uri (E_MAIL_FOLDER_DRAFTS); + em_folder_selection_button_set_selection((EMFolderSelectionButton *)emae->priv->drafts_folder_button, uri); + emae_account_folder_changed((EMFolderSelectionButton *)emae->priv->drafts_folder_button, emae); + + uri = e_mail_local_get_folder_uri (E_MAIL_FOLDER_SENT); + em_folder_selection_button_set_selection((EMFolderSelectionButton *)emae->priv->sent_folder_button, uri); + emae_account_folder_changed((EMFolderSelectionButton *)emae->priv->sent_folder_button, emae); +} + +/* custom widget factories */ +GtkWidget *em_account_editor_folder_selector_button_new (gchar *widget_name, gchar *string1, gchar *string2, gint int1, gint int2); + +GtkWidget * +em_account_editor_folder_selector_button_new (gchar *widget_name, gchar *string1, gchar *string2, gint int1, gint int2) +{ + return (GtkWidget *)em_folder_selection_button_new ( + string1 ? string1 : _("Select Folder"), NULL); +} + +GtkWidget *em_account_editor_dropdown_new(gchar *widget_name, gchar *string1, gchar *string2, gint int1, gint int2); + +GtkWidget * +em_account_editor_dropdown_new(gchar *widget_name, gchar *string1, gchar *string2, gint int1, gint int2) +{ + return gtk_combo_box_new (); +} + +GtkWidget *em_account_editor_ssl_selector_new(gchar *widget_name, gchar *string1, gchar *string2, gint int1, gint int2); + +GtkWidget * +em_account_editor_ssl_selector_new(gchar *widget_name, gchar *string1, gchar *string2, gint int1, gint int2) +{ + GtkComboBox *dropdown = (GtkComboBox *)gtk_combo_box_new(); + GtkCellRenderer *cell = gtk_cell_renderer_text_new(); + GtkListStore *store; + gint i; + GtkTreeIter iter; + + gtk_widget_show((GtkWidget *)dropdown); + + store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); + + for (i=0;ipriv; + EMAccountEditorService *service = &gui->source; + GHashTable *auto_detected; + GSList *l; + CamelProviderConfEntry *entries; + gchar *value; + gint i; + CamelURL *url; + + if (service->provider == NULL + || (entries = service->provider->extra_conf) == NULL) + return; + + d(printf("Running auto-detect\n")); + + url = emae_account_url(emae, E_ACCOUNT_SOURCE_URL); + camel_provider_auto_detect(service->provider, url, &auto_detected, NULL); + camel_url_free(url); + if (auto_detected == NULL) { + d(printf(" no values detected\n")); + return; + } + + for (i = 0; entries[i].type != CAMEL_PROVIDER_CONF_END; i++) { + struct _receive_options_item *item; + GtkWidget *w; + + if (entries[i].name == NULL + || (value = g_hash_table_lookup (auto_detected, entries[i].name)) == NULL) + continue; + + /* only 2 providers use this, and they only do it for 3 entries only */ + g_return_if_fail (entries[i].type == CAMEL_PROVIDER_CONF_ENTRY); + + w = NULL; + for (l = emae->priv->extra_items;l;l=g_slist_next(l)) { + item = l->data; + if (item->extra_table && (w = g_hash_table_lookup(item->extra_table, entries[i].name))) + break; + } + + gtk_entry_set_text((GtkEntry *)w, value?value:""); + } + + g_hash_table_foreach(auto_detected, emae_auto_detect_free, NULL); + g_hash_table_destroy(auto_detected); +} + +static gint +provider_compare (const CamelProvider *p1, const CamelProvider *p2) +{ + /* sort providers based on "location" (ie. local or remote) */ + if (p1->flags & CAMEL_PROVIDER_IS_REMOTE) { + if (p2->flags & CAMEL_PROVIDER_IS_REMOTE) + return 0; + return -1; + } else { + if (p2->flags & CAMEL_PROVIDER_IS_REMOTE) + return 1; + return 0; + } +} + +static void +emae_signature_added(ESignatureList *signatures, ESignature *sig, EMAccountEditor *emae) +{ + GtkTreeModel *model; + GtkTreeIter iter; + + model = gtk_combo_box_get_model(emae->priv->signatures_dropdown); + + gtk_list_store_append((GtkListStore *)model, &iter); + gtk_list_store_set((GtkListStore *)model, &iter, 0, sig->autogen?_("Autogenerated"):sig->name, 1, sig->uid, -1); + + gtk_combo_box_set_active(emae->priv->signatures_dropdown, gtk_tree_model_iter_n_children(model, NULL)-1); +} + +static gint +emae_signature_get_iter(EMAccountEditor *emae, ESignature *sig, GtkTreeModel **modelp, GtkTreeIter *iter) +{ + GtkTreeModel *model; + gint found = 0; + + model = gtk_combo_box_get_model(emae->priv->signatures_dropdown); + *modelp = model; + if (!gtk_tree_model_get_iter_first(model, iter)) + return FALSE; + + do { + gchar *uid; + + gtk_tree_model_get(model, iter, 1, &uid, -1); + if (uid && !strcmp(uid, sig->uid)) + found = TRUE; + g_free(uid); + } while (!found && gtk_tree_model_iter_next(model, iter)); + + return found; +} + +static void +emae_signature_removed(ESignatureList *signatures, ESignature *sig, EMAccountEditor *emae) +{ + GtkTreeIter iter; + GtkTreeModel *model; + + if (emae_signature_get_iter(emae, sig, &model, &iter)) + gtk_list_store_remove((GtkListStore *)model, &iter); +} + +static void +emae_signature_changed(ESignatureList *signatures, ESignature *sig, EMAccountEditor *emae) +{ + GtkTreeIter iter; + GtkTreeModel *model; + + if (emae_signature_get_iter(emae, sig, &model, &iter)) + gtk_list_store_set((GtkListStore *)model, &iter, 0, sig->autogen?_("Autogenerated"):sig->name, -1); +} + +static void +emae_signaturetype_changed(GtkComboBox *dropdown, EMAccountEditor *emae) +{ + gint id = gtk_combo_box_get_active(dropdown); + GtkTreeModel *model; + GtkTreeIter iter; + gchar *uid = NULL; + + if (id != -1) { + model = gtk_combo_box_get_model(dropdown); + if (gtk_tree_model_iter_nth_child(model, &iter, NULL, id)) + gtk_tree_model_get(model, &iter, 1, &uid, -1); + } + + e_account_set_string(emae->account, E_ACCOUNT_ID_SIGNATURE, uid); + g_free(uid); +} + +static void +emae_signature_new(GtkWidget *w, EMAccountEditor *emae) +{ + EShell *shell; + EShellSettings *shell_settings; + GtkWidget *parent; + gboolean html_mode; + + shell = e_shell_get_default (); + shell_settings = e_shell_get_shell_settings (shell); + parent = gtk_widget_get_toplevel (w); + + html_mode = e_shell_settings_get_boolean ( + shell_settings, "composer-format-html"); + + em_composer_prefs_new_signature (GTK_WINDOW (parent), html_mode); +} + +static GtkWidget * +emae_setup_signatures(EMAccountEditor *emae, GladeXML *xml) +{ + EMAccountEditorPrivate *p = emae->priv; + GtkComboBox *dropdown = (GtkComboBox *)glade_xml_get_widget(xml, "signature_dropdown"); + GtkCellRenderer *cell = gtk_cell_renderer_text_new(); + GtkListStore *store; + gint i, active=0; + GtkTreeIter iter; + ESignatureList *signatures; + EIterator *it; + const gchar *current = e_account_get_string(emae->account, E_ACCOUNT_ID_SIGNATURE); + GtkWidget *button; + + emae->priv->signatures_dropdown = dropdown; + gtk_widget_show((GtkWidget *)dropdown); + + store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, _("None"), 1, NULL, -1); + + signatures = e_get_signature_list (); + + if (p->sig_added_id == 0) { + p->sig_added_id = g_signal_connect(signatures, "signature-added", G_CALLBACK(emae_signature_added), emae); + p->sig_removed_id = g_signal_connect(signatures, "signature-removed", G_CALLBACK(emae_signature_removed), emae); + p->sig_changed_id = g_signal_connect(signatures, "signature-changed", G_CALLBACK(emae_signature_changed), emae); + } + + /* we need to count the 'none' entry before using the index */ + i = 1; + it = e_list_get_iterator ((EList *) signatures); + while (e_iterator_is_valid (it)) { + ESignature *sig = (ESignature *)e_iterator_get(it); + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, sig->autogen?_("Autogenerated"):sig->name, 1, sig->uid, -1); + + if (current && !strcmp(current, sig->uid)) + active = i; + + e_iterator_next(it); + i++; + } + g_object_unref (it); + + gtk_cell_layout_pack_start((GtkCellLayout *)dropdown, cell, TRUE); + gtk_cell_layout_set_attributes((GtkCellLayout *)dropdown, cell, "text", 0, NULL); + + gtk_combo_box_set_model(dropdown, (GtkTreeModel *)store); + gtk_combo_box_set_active(dropdown, active); + + g_signal_connect(dropdown, "changed", G_CALLBACK(emae_signaturetype_changed), emae); + gtk_widget_set_sensitive((GtkWidget *)dropdown, e_account_writable(emae->account, E_ACCOUNT_ID_SIGNATURE)); + + button = glade_xml_get_widget(xml, "sigAddNew"); + g_signal_connect(button, "clicked", G_CALLBACK(emae_signature_new), emae); + gtk_widget_set_sensitive(button, + gconf_client_key_is_writable(mail_config_get_gconf_client(), + "/apps/evolution/mail/signatures", NULL)); + + return (GtkWidget *)dropdown; +} + +static void +emae_receipt_policy_changed(GtkComboBox *dropdown, EMAccountEditor *emae) +{ + gint id = gtk_combo_box_get_active(dropdown); + GtkTreeModel *model; + GtkTreeIter iter; + EAccountReceiptPolicy policy; + + if (id != -1) { + model = gtk_combo_box_get_model(dropdown); + if (gtk_tree_model_iter_nth_child(model, &iter, NULL, id)) { + gtk_tree_model_get(model, &iter, 1, &policy, -1); + e_account_set_int (emae->account, E_ACCOUNT_RECEIPT_POLICY, policy); + } + } + +} + +static GtkWidget * +emae_setup_receipt_policy (EMAccountEditor *emae, GladeXML *xml) +{ + GtkComboBox *dropdown = (GtkComboBox *)glade_xml_get_widget(xml, "receipt_policy_dropdown"); + GtkListStore *store; + gint i = 0, active = 0; + GtkTreeIter iter; + EAccountReceiptPolicy current = emae->account->receipt_policy; + static struct { + EAccountReceiptPolicy policy; + const gchar *label; + } receipt_policies[] = { + { E_ACCOUNT_RECEIPT_NEVER, N_("Never") }, + { E_ACCOUNT_RECEIPT_ALWAYS, N_("Always") }, + { E_ACCOUNT_RECEIPT_ASK, N_("Ask for each message") } + }; + + gtk_widget_show((GtkWidget *)dropdown); + + store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT); + + for (i = 0; i < 3; ++i) { + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + 0, _(receipt_policies[i].label), + 1, receipt_policies[i].policy, + -1); + if (current == receipt_policies[i].policy) + active = i; + } + + gtk_combo_box_set_model(dropdown, (GtkTreeModel *)store); + gtk_combo_box_set_active(dropdown, active); + + g_signal_connect(dropdown, "changed", G_CALLBACK(emae_receipt_policy_changed), emae); + gtk_widget_set_sensitive((GtkWidget *)dropdown, e_account_writable(emae->account, E_ACCOUNT_RECEIPT_POLICY)); + + return (GtkWidget *)dropdown; +} + +static void +emae_account_entry_changed(GtkEntry *entry, EMAccountEditor *emae) +{ + gint item = GPOINTER_TO_INT(g_object_get_data((GObject *)entry, "account-item")); + + e_account_set_string(emae->account, item, gtk_entry_get_text(entry)); +} + +static GtkEntry * +emae_account_entry(EMAccountEditor *emae, const gchar *name, gint item, GladeXML *xml) +{ + GtkEntry *entry; + const gchar *text; + + entry = (GtkEntry *)glade_xml_get_widget(xml, name); + text = e_account_get_string(emae->account, item); + if (text) + gtk_entry_set_text(entry, text); + g_object_set_data((GObject *)entry, "account-item", GINT_TO_POINTER(item)); + g_signal_connect(entry, "changed", G_CALLBACK(emae_account_entry_changed), emae); + gtk_widget_set_sensitive((GtkWidget *)entry, e_account_writable(emae->account, item)); + + return entry; +} + +static void +emae_account_toggle_changed(GtkToggleButton *toggle, EMAccountEditor *emae) +{ + gint item = GPOINTER_TO_INT(g_object_get_data((GObject *)toggle, "account-item")); + + e_account_set_bool(emae->account, item, gtk_toggle_button_get_active(toggle)); +} + +static void +emae_account_toggle_widget(EMAccountEditor *emae, GtkToggleButton *toggle, gint item) +{ + gtk_toggle_button_set_active(toggle, e_account_get_bool(emae->account, item)); + g_object_set_data((GObject *)toggle, "account-item", GINT_TO_POINTER(item)); + g_signal_connect(toggle, "toggled", G_CALLBACK(emae_account_toggle_changed), emae); + gtk_widget_set_sensitive((GtkWidget *)toggle, e_account_writable(emae->account, item)); +} + +static GtkToggleButton * +emae_account_toggle(EMAccountEditor *emae, const gchar *name, gint item, GladeXML *xml) +{ + GtkToggleButton *toggle; + + toggle = (GtkToggleButton *)glade_xml_get_widget(xml, name); + emae_account_toggle_widget(emae, toggle, item); + + return toggle; +} + +static void +emae_account_spinint_changed(GtkSpinButton *spin, EMAccountEditor *emae) +{ + gint item = GPOINTER_TO_INT(g_object_get_data((GObject *)spin, "account-item")); + + e_account_set_int(emae->account, item, gtk_spin_button_get_value(spin)); +} + +static void +emae_account_spinint_widget(EMAccountEditor *emae, GtkSpinButton *spin, gint item) +{ + gtk_spin_button_set_value(spin, e_account_get_int(emae->account, item)); + g_object_set_data((GObject *)spin, "account-item", GINT_TO_POINTER(item)); + g_signal_connect(spin, "value_changed", G_CALLBACK(emae_account_spinint_changed), emae); + gtk_widget_set_sensitive((GtkWidget *)spin, e_account_writable(emae->account, item)); +} + +#if 0 +static GtkSpinButton * +emae_account_spinint(EMAccountEditor *emae, const gchar *name, gint item) +{ + GtkSpinButton *spin; + + spin = (GtkSpinButton *)glade_xml_get_widget(emae->priv->xml, name); + emae_account_spinint_widget(emae, spin, item); + + return spin; +} +#endif + +static void +emae_account_folder_changed(EMFolderSelectionButton *folder, EMAccountEditor *emae) +{ + gint item = GPOINTER_TO_INT(g_object_get_data((GObject *)folder, "account-item")); + + e_account_set_string(emae->account, item, em_folder_selection_button_get_selection(folder)); +} + +static EMFolderSelectionButton * +emae_account_folder(EMAccountEditor *emae, const gchar *name, gint item, gint deffolder, GladeXML *xml) +{ + EMFolderSelectionButton *folder; + const gchar *uri; + + folder = (EMFolderSelectionButton *)glade_xml_get_widget(xml, name); + uri = e_account_get_string(emae->account, item); + if (uri) { + gchar *tmp = em_uri_to_camel(uri); + + em_folder_selection_button_set_selection(folder, tmp); + g_free(tmp); + } else { + const gchar *uri; + + uri = e_mail_local_get_folder_uri (deffolder); + em_folder_selection_button_set_selection(folder, uri); + } + + g_object_set_data((GObject *)folder, "account-item", GINT_TO_POINTER(item)); + g_object_set_data((GObject *)folder, "folder-default", GINT_TO_POINTER(deffolder)); + g_signal_connect(folder, "selected", G_CALLBACK(emae_account_folder_changed), emae); + gtk_widget_show((GtkWidget *)folder); + + gtk_widget_set_sensitive((GtkWidget *)folder, e_account_writable(emae->account, item)); + + return folder; +} + +#if defined (HAVE_NSS) +static void +smime_changed(EMAccountEditor *emae) +{ + EMAccountEditorPrivate *gui = emae->priv; + gint act; + const gchar *tmp; + + tmp = gtk_entry_get_text(gui->smime_sign_key); + act = tmp && tmp[0]; + gtk_widget_set_sensitive((GtkWidget *)gui->smime_sign_key_clear, act); + gtk_widget_set_sensitive((GtkWidget *)gui->smime_sign_default, act); + if (!act) + gtk_toggle_button_set_active(gui->smime_sign_default, FALSE); + + tmp = gtk_entry_get_text(gui->smime_encrypt_key); + act = tmp && tmp[0]; + gtk_widget_set_sensitive((GtkWidget *)gui->smime_encrypt_key_clear, act); + gtk_widget_set_sensitive((GtkWidget *)gui->smime_encrypt_default, act); + gtk_widget_set_sensitive((GtkWidget *)gui->smime_encrypt_to_self, act); + if (!act) { + gtk_toggle_button_set_active(gui->smime_encrypt_default, FALSE); + gtk_toggle_button_set_active(gui->smime_encrypt_to_self, FALSE); + } +} + +static void +smime_sign_key_selected(GtkWidget *dialog, const gchar *key, EMAccountEditor *emae) +{ + EMAccountEditorPrivate *gui = emae->priv; + + if (key != NULL) { + gtk_entry_set_text(gui->smime_sign_key, key); + smime_changed(emae); + } + + gtk_widget_destroy(dialog); +} + +static void +smime_sign_key_select(GtkWidget *button, EMAccountEditor *emae) +{ + EMAccountEditorPrivate *gui = emae->priv; + GtkWidget *w; + + w = e_cert_selector_new(E_CERT_SELECTOR_SIGNER, gtk_entry_get_text(gui->smime_sign_key)); + gtk_window_set_modal((GtkWindow *)w, TRUE); + gtk_window_set_transient_for((GtkWindow *)w, (GtkWindow *)gtk_widget_get_toplevel(button)); + g_signal_connect(w, "selected", G_CALLBACK(smime_sign_key_selected), emae); + gtk_widget_show(w); +} + +static void +smime_sign_key_clear(GtkWidget *w, EMAccountEditor *emae) +{ + EMAccountEditorPrivate *gui = emae->priv; + + gtk_entry_set_text(gui->smime_sign_key, ""); + smime_changed(emae); +} + +static void +smime_encrypt_key_selected(GtkWidget *dialog, const gchar *key, EMAccountEditor *emae) +{ + EMAccountEditorPrivate *gui = emae->priv; + + if (key != NULL) { + gtk_entry_set_text(gui->smime_encrypt_key, key); + smime_changed(emae); + } + + gtk_widget_destroy(dialog); +} + +static void +smime_encrypt_key_select(GtkWidget *button, EMAccountEditor *emae) +{ + EMAccountEditorPrivate *gui = emae->priv; + GtkWidget *w; + + w = e_cert_selector_new(E_CERT_SELECTOR_SIGNER, gtk_entry_get_text(gui->smime_encrypt_key)); + gtk_window_set_modal((GtkWindow *)w, TRUE); + gtk_window_set_transient_for((GtkWindow *)w, (GtkWindow *)gtk_widget_get_toplevel(button)); + g_signal_connect(w, "selected", G_CALLBACK(smime_encrypt_key_selected), emae); + gtk_widget_show(w); +} + +static void +smime_encrypt_key_clear(GtkWidget *w, EMAccountEditor *emae) +{ + EMAccountEditorPrivate *gui = emae->priv; + + gtk_entry_set_text(gui->smime_encrypt_key, ""); + smime_changed(emae); +} +#endif + +static void +emae_url_set_hostport(CamelURL *url, const gchar *txt) +{ + const gchar *port; + gchar *host; + + /* FIXME: what if this was a raw IPv6 address? */ + if (txt && (port = strchr(txt, ':'))) { + camel_url_set_port(url, atoi(port+1)); + host = g_strdup(txt); + host[port-txt] = 0; + } else { + /* "" is converted to NULL, but if we set NULL on the url, + camel_url_to_string strips lots of details */ + host = g_strdup((txt?txt:"")); + camel_url_set_port (url, 0); + } + + g_strstrip(host); + if (txt && *txt) + camel_url_set_host(url, host); + + g_free(host); +} + +/* This is used to map a funciton which will set on the url a string value. + if widgets[0] is set, it is the entry which will be called against setval() + We need our own function for host:port decoding, as above */ +struct _provider_host_info { + guint32 flag; + void (*setval)(CamelURL *, const gchar *); + glong widgets[3]; +}; + +static struct _provider_host_info emae_source_host_info[] = { + { CAMEL_URL_PART_HOST, emae_url_set_hostport, { G_STRUCT_OFFSET(EMAccountEditorService, hostname), G_STRUCT_OFFSET(EMAccountEditorService, hostlabel), }, }, + { CAMEL_URL_PART_USER, camel_url_set_user, { G_STRUCT_OFFSET(EMAccountEditorService, username), G_STRUCT_OFFSET(EMAccountEditorService, userlabel), } }, + { CAMEL_URL_PART_PATH, camel_url_set_path, { G_STRUCT_OFFSET(EMAccountEditorService, path), G_STRUCT_OFFSET(EMAccountEditorService, pathlabel), G_STRUCT_OFFSET(EMAccountEditorService, pathentry) }, }, + { CAMEL_URL_PART_AUTH, NULL, { 0, G_STRUCT_OFFSET(EMAccountEditorService, auth_frame), }, }, + { 0 }, +}; + +static struct _provider_host_info emae_transport_host_info[] = { + { CAMEL_URL_PART_HOST, emae_url_set_hostport, { G_STRUCT_OFFSET(EMAccountEditorService, hostname), G_STRUCT_OFFSET(EMAccountEditorService, hostlabel), }, }, + { CAMEL_URL_PART_USER, camel_url_set_user, { G_STRUCT_OFFSET(EMAccountEditorService, username), G_STRUCT_OFFSET(EMAccountEditorService, userlabel), } }, + { CAMEL_URL_PART_AUTH, NULL, { 0, G_STRUCT_OFFSET(EMAccountEditorService, auth_frame), }, }, + { 0 }, +}; + +/* This is used to map each of the two services in a typical account to the widgets that represent each service. + i.e. the receiving (source) service, and the sending (transport) service. + It is used throughout the following code to drive each page */ +static struct _service_info { + gint account_uri_key; + gint save_passwd_key; + + const gchar *frame; + const gchar *type_dropdown; + + const gchar *container; + const gchar *description; + const gchar *hostname; + const gchar *hostlabel; + const gchar *username; + const gchar *userlabel; + const gchar *path; + const gchar *pathlabel; + const gchar *pathentry; + + const gchar *security_frame; + const gchar *ssl_hbox; + const gchar *use_ssl; + const gchar *ssl_disabled; + + const gchar *needs_auth; + const gchar *auth_frame; + + const gchar *authtype; + const gchar *authtype_check; + + const gchar *remember_password; + + struct _provider_host_info *host_info; +} emae_service_info[CAMEL_NUM_PROVIDER_TYPES] = { + { E_ACCOUNT_SOURCE_URL, E_ACCOUNT_SOURCE_SAVE_PASSWD, + "source_frame", "source_type_dropdown", + "source_vbox", "source_description", "source_host", "source_host_label", "source_user", "source_user_label", "source_path", "source_path_label", "source_path_entry", + "source_security_frame", "source_ssl_hbox", "source_use_ssl", "source_ssl_disabled", + NULL, "source_auth_frame", + "source_auth_dropdown", "source_check_supported", + "source_remember_password", + emae_source_host_info, + }, + { E_ACCOUNT_TRANSPORT_URL, E_ACCOUNT_TRANSPORT_SAVE_PASSWD, + "transport_frame", "transport_type_dropdown", + "transport_vbox", "transport_description", "transport_host", "transport_host_label", "transport_user", "transport_user_label", NULL, NULL, NULL, + "transport_security_frame", "transport_ssl_hbox", "transport_use_ssl", "transport_ssl_disabled", + "transport_needs_auth", "transport_auth_frame", + "transport_auth_dropdown", "transport_check_supported", + "transport_remember_password", + emae_transport_host_info, + }, +}; + +static void +emae_uri_changed(EMAccountEditorService *service, CamelURL *url) +{ + gchar *uri; + + uri = camel_url_to_string(url, 0); + + e_account_set_string(service->emae->account, emae_service_info[service->type].account_uri_key, uri); + + /* small hack for providers which are store and transport - copy settings across */ + if (service->type == CAMEL_PROVIDER_STORE + && service->provider + && CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT(service->provider)) + e_account_set_string(service->emae->account, E_ACCOUNT_TRANSPORT_URL, uri); + + g_free(uri); +} + +static void +emae_service_url_changed(EMAccountEditorService *service, void (*setval)(CamelURL *, const gchar *), GtkEntry *entry) +{ + GtkComboBox *dropdown; + gint id; + GtkTreeModel *model; + GtkTreeIter iter; + CamelServiceAuthType *authtype; + + CamelURL *url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); + const gchar *text = gtk_entry_get_text(entry); + + setval(url, (text && text[0])?text:NULL); + + if (text && text[0] && setval == camel_url_set_user) { + dropdown = service->authtype; + if(dropdown) { + id = gtk_combo_box_get_active (dropdown); + if (id != -1) { + model = gtk_combo_box_get_model (dropdown); + if (gtk_tree_model_iter_nth_child (model, &iter, NULL, id)) { + gtk_tree_model_get (model, &iter, 1, &authtype, -1); + if (authtype) + camel_url_set_authmech (url, authtype->authproto); + } + } + } + } + + emae_uri_changed(service, url); + camel_url_free(url); +} + +static void +emae_service_url_path_changed(EMAccountEditorService *service, void (*setval)(CamelURL *, const gchar *), GtkWidget *widget) +{ + GtkComboBox *dropdown; + gint id; + GtkTreeModel *model; + GtkTreeIter iter; + CamelServiceAuthType *authtype; + + CamelURL *url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); + const gchar *text = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget)); + + setval(url, (text && text[0])?text:NULL); + + if (text && text[0] && setval == camel_url_set_user) { + dropdown = service->authtype; + if(dropdown) { + id = gtk_combo_box_get_active (dropdown); + if (id != -1) { + model = gtk_combo_box_get_model (dropdown); + if (gtk_tree_model_iter_nth_child (model, &iter, NULL, id)) { + gtk_tree_model_get (model, &iter, 1, &authtype, -1); + if (authtype) + camel_url_set_authmech (url, authtype->authproto); + } + } + } + } + + emae_uri_changed(service, url); + camel_url_free(url); +} + +static void +emae_hostname_changed(GtkEntry *entry, EMAccountEditorService *service) +{ + emae_service_url_changed(service, emae_url_set_hostport, entry); +} + +static void +emae_username_changed(GtkEntry *entry, EMAccountEditorService *service) +{ + emae_service_url_changed(service, camel_url_set_user, entry); +} + +static void +emae_path_changed(GtkWidget *widget, EMAccountEditorService *service) +{ + emae_service_url_path_changed(service, camel_url_set_path, widget); +} + +static gint +emae_ssl_update(EMAccountEditorService *service, CamelURL *url) +{ + gint id = gtk_combo_box_get_active(service->use_ssl); + GtkTreeModel *model; + GtkTreeIter iter; + gchar *ssl; + + if (id == -1) + return 0; + + model = gtk_combo_box_get_model(service->use_ssl); + if (gtk_tree_model_iter_nth_child(model, &iter, NULL, id)) { + gtk_tree_model_get(model, &iter, 1, &ssl, -1); + if (!strcmp(ssl, "none")) + ssl = NULL; + camel_url_set_param(url, "use_ssl", ssl); + return 1; + } + + return 0; +} + +static void +emae_ssl_changed(GtkComboBox *dropdown, EMAccountEditorService *service) +{ + CamelURL *url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); + + if (emae_ssl_update(service, url)) + emae_uri_changed(service, url); + camel_url_free(url); +} + +static void +emae_service_provider_changed(EMAccountEditorService *service) +{ + gint i, j; + void (*show)(GtkWidget *); + CamelURL *url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); + + if (service->provider) { + gint enable; + GtkWidget *dwidget = NULL; + + camel_url_set_protocol(url, service->provider->protocol); + gtk_label_set_text(service->description, service->provider->description); + if (!emae_check_license(service->emae, service->provider)) + gtk_widget_hide(service->frame); + else + gtk_widget_show(service->frame); + + enable = e_account_writable_option(service->emae->account, service->provider->protocol, "auth"); + gtk_widget_set_sensitive((GtkWidget *)service->authtype, enable); + gtk_widget_set_sensitive((GtkWidget *)service->check_supported, enable); + + enable = e_account_writable_option(service->emae->account, service->provider->protocol, "use_ssl"); + gtk_widget_set_sensitive((GtkWidget *)service->use_ssl, enable); + + enable = e_account_writable(service->emae->account, emae_service_info[service->type].save_passwd_key); + gtk_widget_set_sensitive((GtkWidget *)service->remember, enable); + + for (i=0;emae_service_info[service->type].host_info[i].flag;i++) { + GtkWidget *w; + gint hide; + struct _provider_host_info *info = &emae_service_info[service->type].host_info[i]; + + enable = CAMEL_PROVIDER_ALLOWS(service->provider, info->flag); + hide = CAMEL_PROVIDER_HIDDEN(service->provider, info->flag); + show = (enable && !hide)?gtk_widget_show:gtk_widget_hide; + + for (j=0; j < sizeof(info->widgets)/sizeof(info->widgets[0]); j++) { + if (info->widgets[j] && (w = G_STRUCT_MEMBER(GtkWidget *, service, info->widgets[j]))) { + show(w); + if (j == 0) { + if (dwidget == NULL && enable) + dwidget = w; + + if (info->setval && !hide) + info->setval(url, enable?gtk_entry_get_text((GtkEntry *)w):NULL); + } + } + } + } + + if (dwidget) + gtk_widget_grab_focus(dwidget); + + if (CAMEL_PROVIDER_ALLOWS(service->provider, CAMEL_URL_PART_AUTH)) { + GList *ll; + + /* try to keep the authmech from the current url, or clear it */ + if (url->authmech) { + if (service->provider->authtypes) { + for (ll = service->provider->authtypes;ll;ll = g_list_next(ll)) + if (!strcmp(url->authmech, ((CamelServiceAuthType *)ll->data)->authproto)) + break; + if (ll == NULL) + camel_url_set_authmech(url, NULL); + } else { + camel_url_set_authmech(url, NULL); + } + } + + emae_refresh_authtype(service->emae, service); + if (service->needs_auth && !CAMEL_PROVIDER_NEEDS(service->provider, CAMEL_URL_PART_AUTH)) + gtk_widget_show((GtkWidget *)service->needs_auth); + } else { + if (service->needs_auth) + gtk_widget_hide((GtkWidget *)service->needs_auth); + } +#ifdef HAVE_SSL + gtk_widget_hide(service->no_ssl); + if (service->provider->flags & CAMEL_PROVIDER_SUPPORTS_SSL) { + emae_ssl_update(service, url); + show = gtk_widget_show; + } else { + camel_url_set_param(url, "use_ssl", NULL); + show = gtk_widget_hide; + } + show(service->ssl_frame); + show(service->ssl_hbox); +#else + gtk_widget_hide(service->ssl_hbox); + gtk_widget_show(service->no_ssl); + camel_url_set_param(url, "use_ssl", NULL); +#endif + } else { + camel_url_set_protocol(url, NULL); + gtk_label_set_text(service->description, ""); + gtk_widget_hide(service->frame); + gtk_widget_hide(service->auth_frame); + gtk_widget_hide(service->ssl_frame); + } + + /* FIXME: linked services? */ + /* FIXME: permissions setup */ + + emae_uri_changed(service, url); + camel_url_free(url); +} + +static void +emae_provider_changed(GtkComboBox *dropdown, EMAccountEditorService *service) +{ + gint id = gtk_combo_box_get_active(dropdown); + GtkTreeModel *model; + GtkTreeIter iter; + + if (id == -1) + return; + + model = gtk_combo_box_get_model(dropdown); + if (!gtk_tree_model_iter_nth_child(model, &iter, NULL, id)) + return; + + gtk_tree_model_get(model, &iter, 1, &service->provider, -1); + + g_list_free(service->authtypes); + service->authtypes = NULL; + + emae_service_provider_changed(service); + + e_config_target_changed((EConfig *)service->emae->priv->config, E_CONFIG_TARGET_CHANGED_REBUILD); +} + +static void +emae_refresh_providers(EMAccountEditor *emae, EMAccountEditorService *service) +{ + EAccount *account = emae->account; + GtkListStore *store; + GtkTreeIter iter; + GList *l; + GtkCellRenderer *cell = gtk_cell_renderer_text_new(); + GtkComboBox *dropdown; + gint active = 0, i; + struct _service_info *info = &emae_service_info[service->type]; + const gchar *uri = e_account_get_string(account, info->account_uri_key); + gchar *current = NULL; + const gchar *tmp; + CamelURL *url; + + dropdown = service->providers; + gtk_widget_show((GtkWidget *)dropdown); + + if (uri) { + const gchar *colon = strchr(uri, ':'); + gint len; + + if (colon) { + len = colon-uri; + current = g_alloca(len+1); + memcpy(current, uri, len); + current[len] = 0; + } + } else { + current = (gchar *) "imap"; + } + + store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); + + i = 0; + + /* We just special case each type here, its just easier */ + if (service->type == CAMEL_PROVIDER_STORE) { + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, _("None"), 1, NULL, -1); + i++; + } + + for (l=emae->priv->providers; l; l=l->next) { + CamelProvider *provider = l->data; + + if (!((strcmp(provider->domain, "mail") == 0 + || strcmp (provider->domain, "news") == 0) + && provider->object_types[service->type] + && (service->type != CAMEL_PROVIDER_STORE || (provider->flags & CAMEL_PROVIDER_IS_SOURCE) != 0)) + /* hardcode not showing providers who's transport is done in the store */ + || (service->type == CAMEL_PROVIDER_TRANSPORT + && CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider))) + continue; + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, provider->name, 1, provider, -1); + + /* find the displayed and set default */ + if (i == 0 || (current && strcmp(provider->protocol, current) == 0)) { + service->provider = provider; + active = i; + + /* we need to set this value on the uri too */ + if (current == NULL) { + CamelURL *url = emae_account_url(emae, info->account_uri_key); + + camel_url_set_protocol(url, provider->protocol); + emae_uri_changed(service, url); + camel_url_free(url); + } + } + i++; + } + + + gtk_cell_layout_clear((GtkCellLayout *)dropdown); + gtk_combo_box_set_model(dropdown, (GtkTreeModel *)store); + gtk_cell_layout_pack_start((GtkCellLayout *)dropdown, cell, TRUE); + gtk_cell_layout_set_attributes((GtkCellLayout *)dropdown, cell, "text", 0, NULL); + + g_signal_handlers_disconnect_by_func(dropdown, emae_provider_changed, service); + gtk_combo_box_set_active(dropdown, -1); /* needed for gtkcombo bug(?) */ + gtk_combo_box_set_active(dropdown, active); + g_signal_connect(dropdown, "changed", G_CALLBACK(emae_provider_changed), service); + + if (!uri || (url = camel_url_new(uri, NULL)) == NULL) { + return; + } + + tmp = camel_url_get_param(url, "use_ssl"); + if (tmp == NULL) + tmp = "never"; + for (i=0;iuse_ssl, i); + break; + } + } +} + +static void +emae_authtype_changed(GtkComboBox *dropdown, EMAccountEditorService *service) +{ + gint id = gtk_combo_box_get_active(dropdown); + GtkTreeModel *model; + GtkTreeIter iter; + CamelServiceAuthType *authtype; + CamelURL *url; + + if (id == -1) + return; + + url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); + model = gtk_combo_box_get_model(dropdown); + if (gtk_tree_model_iter_nth_child(model, &iter, NULL, id)) { + gtk_tree_model_get(model, &iter, 1, &authtype, -1); + if (authtype) + camel_url_set_authmech(url, authtype->authproto); + else + camel_url_set_authmech(url, NULL); + emae_uri_changed(service, url); + } + camel_url_free(url); + + gtk_widget_set_sensitive((GtkWidget *)service->remember, + authtype + ?(authtype->need_password && e_account_writable(service->emae->account, emae_service_info[service->type].save_passwd_key)) + :FALSE); +} + +static void +emae_needs_auth(GtkToggleButton *toggle, EMAccountEditorService *service) +{ + gint need = gtk_toggle_button_get_active(toggle); + + gtk_widget_set_sensitive(service->auth_frame, need); + + if (need) + emae_authtype_changed(service->authtype, service); + else { + CamelURL *url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); + + camel_url_set_authmech(url, NULL); + emae_uri_changed(service, url); + camel_url_free(url); + } +} + +static void emae_check_authtype(GtkWidget *w, EMAccountEditorService *service); + +static void +emae_refresh_authtype (EMAccountEditor *emae, EMAccountEditorService *service) +{ + EAccount *account = emae->account; + GtkListStore *store; + GtkTreeIter iter; + GtkComboBox *dropdown; + gint active = 0; + gint i; + struct _service_info *info = &emae_service_info[service->type]; + const gchar *uri = e_account_get_string(account, info->account_uri_key); + GList *l, *ll; + CamelURL *url = NULL; + + dropdown = service->authtype; + gtk_widget_show((GtkWidget *)dropdown); + + store = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN); + + if (uri) + url = camel_url_new(uri, NULL); + + if (service->provider) { + for (i=0, l=service->provider->authtypes; l; l=l->next, i++) { + CamelServiceAuthType *authtype = l->data; + gint avail; + + /* if we have some already shown */ + if (service->authtypes) { + for (ll = service->authtypes;ll;ll = g_list_next(ll)) + if (!strcmp(authtype->authproto, ((CamelServiceAuthType *)ll->data)->authproto)) + break; + avail = ll != NULL; + } else { + avail = TRUE; + } + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, authtype->name, 1, authtype, 2, !avail, -1); + + if (url && url->authmech && !strcmp(url->authmech, authtype->authproto)) + active = i; + } + } + + gtk_combo_box_set_model(dropdown, (GtkTreeModel *)store); + gtk_combo_box_set_active(dropdown, -1); + + if (service->auth_changed_id == 0) { + GtkCellRenderer *cell = gtk_cell_renderer_text_new(); + + gtk_cell_layout_pack_start((GtkCellLayout *)dropdown, cell, TRUE); + gtk_cell_layout_set_attributes((GtkCellLayout *)dropdown, cell, "text", 0, "strikethrough", 2, NULL); + + service->auth_changed_id = g_signal_connect(dropdown, "changed", G_CALLBACK(emae_authtype_changed), service); + g_signal_connect(service->check_supported, "clicked", G_CALLBACK(emae_check_authtype), service); + } + + gtk_combo_box_set_active(dropdown, active); + + if (url) + camel_url_free(url); +} + +static void emae_check_authtype_done(const gchar *uri, CamelProviderType type, GList *types, gpointer data) +{ + EMAccountEditorService *service = data; + + if (service->check_dialog) { + if (service->authtypes) + g_list_free(service->authtypes); + + service->authtypes = g_list_copy(types); + emae_refresh_authtype(service->emae, service); + gtk_widget_destroy(service->check_dialog); + } + + if (service->emae->editor) + gtk_widget_set_sensitive(service->emae->editor, TRUE); + + service->check_id = -1; + g_object_unref(service->emae); +} + +static void emae_check_authtype_response(GtkWidget *d, gint button, EMAccountEditorService *service) +{ + mail_msg_cancel(service->check_id); + gtk_widget_destroy(service->check_dialog); + service->check_dialog = NULL; + + if (service->emae->editor) + gtk_widget_set_sensitive(service->emae->editor, TRUE); +} + +static void emae_check_authtype(GtkWidget *w, EMAccountEditorService *service) +{ + EMAccountEditor *emae = service->emae; + const gchar *uri; + + /* TODO: do we need to remove the auth mechanism from the uri? */ + uri = e_account_get_string(emae->account, emae_service_info[service->type].account_uri_key); + g_object_ref(emae); + + service->check_dialog = e_error_new(emae->editor ? (GtkWindow *)gtk_widget_get_toplevel(emae->editor) : NULL, + "mail:checking-service", NULL); + g_signal_connect(service->check_dialog, "response", G_CALLBACK(emae_check_authtype_response), service); + gtk_widget_show(service->check_dialog); + if (emae->editor) + gtk_widget_set_sensitive(emae->editor, FALSE); + service->check_id = mail_check_service(uri, service->type, emae_check_authtype_done, service); +} + +static void +emae_setup_service(EMAccountEditor *emae, EMAccountEditorService *service, GladeXML *xml) +{ + struct _service_info *info = &emae_service_info[service->type]; + CamelURL *url = emae_account_url(emae, info->account_uri_key); + const gchar *uri = e_account_get_string(emae->account, info->account_uri_key); + const gchar *tmp; + gint i; + + service->provider = uri?camel_provider_get(uri, NULL):NULL; + service->frame = glade_xml_get_widget(xml, info->frame); + service->container = glade_xml_get_widget(xml, info->container); + service->description = GTK_LABEL (glade_xml_get_widget (xml, info->description)); + service->hostname = GTK_ENTRY (glade_xml_get_widget (xml, info->hostname)); + service->hostlabel = (GtkLabel *)glade_xml_get_widget (xml, info->hostlabel); + service->username = GTK_ENTRY (glade_xml_get_widget (xml, info->username)); + service->userlabel = (GtkLabel *)glade_xml_get_widget (xml, info->userlabel); + if (info->pathentry) { + service->pathlabel = (GtkLabel *)glade_xml_get_widget(xml, info->pathlabel); + service->pathentry = glade_xml_get_widget(xml, info->pathentry); + } + + service->ssl_frame = glade_xml_get_widget (xml, info->security_frame); + gtk_widget_hide (service->ssl_frame); + service->ssl_hbox = glade_xml_get_widget (xml, info->ssl_hbox); + service->use_ssl = (GtkComboBox *)glade_xml_get_widget (xml, info->use_ssl); + service->no_ssl = glade_xml_get_widget (xml, info->ssl_disabled); + + /* configure ui for current settings */ + if (url->host) { + if (url->port) { + gchar *host = g_strdup_printf("%s:%d", url->host, url->port); + + gtk_entry_set_text(service->hostname, host); + g_free(host); + } else + gtk_entry_set_text(service->hostname, url->host); + } + if (url->user && *url->user) { + gtk_entry_set_text(service->username, url->user); + } + if (service->pathentry) { + GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; + + if (service->provider && (service->provider->url_flags & CAMEL_URL_NEED_PATH_DIR) == 0) + action = GTK_FILE_CHOOSER_ACTION_OPEN; + + if (action != gtk_file_chooser_get_action (GTK_FILE_CHOOSER (service->pathentry))) + gtk_file_chooser_set_action (GTK_FILE_CHOOSER (service->pathentry), action); + + if (url->path) + gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (service->pathentry), url->path); + } + + tmp = camel_url_get_param(url, "use_ssl"); + if (tmp == NULL) + tmp = "never"; + + for (i=0;iuse_ssl, i); + break; + } + } + + g_signal_connect (service->hostname, "changed", G_CALLBACK (emae_hostname_changed), service); + g_signal_connect (service->username, "changed", G_CALLBACK (emae_username_changed), service); + if (service->pathentry) + g_signal_connect (GTK_FILE_CHOOSER (service->pathentry), "selection-changed", G_CALLBACK (emae_path_changed), service); + + g_signal_connect(service->use_ssl, "changed", G_CALLBACK(emae_ssl_changed), service); + + service->auth_frame = glade_xml_get_widget(xml, info->auth_frame); + service->remember = emae_account_toggle(emae, info->remember_password, info->save_passwd_key, xml); + service->check_supported = (GtkButton *)glade_xml_get_widget(xml, info->authtype_check); + service->authtype = (GtkComboBox *)glade_xml_get_widget(xml, info->authtype); + /* old authtype will be destroyed when we exit */ + service->auth_changed_id = 0; + service->providers = (GtkComboBox *)glade_xml_get_widget(xml, info->type_dropdown); + emae_refresh_providers(emae, service); + emae_refresh_authtype(emae, service); + + if (info->needs_auth) { + service->needs_auth = (GtkToggleButton *)glade_xml_get_widget (xml, info->needs_auth); + gtk_toggle_button_set_active(service->needs_auth, url->authmech != NULL); + g_signal_connect(service->needs_auth, "toggled", G_CALLBACK(emae_needs_auth), service); + emae_needs_auth(service->needs_auth, service); + } else { + service->needs_auth = NULL; + } + + if (!e_account_writable (emae->account, info->account_uri_key)) + gtk_widget_set_sensitive(service->container, FALSE); + else + gtk_widget_set_sensitive(service->container, TRUE); + + emae_service_provider_changed(service); + + camel_url_free(url); +} + +/* do not re-order these, the order is used by various code to look up emae->priv->identity_entries[] */ +static struct { + const gchar *name; + gint item; +} emae_identity_entries[] = { + { "management_name", E_ACCOUNT_NAME }, + { "identity_full_name", E_ACCOUNT_ID_NAME }, + { "identity_address", E_ACCOUNT_ID_ADDRESS }, + { "identity_reply_to", E_ACCOUNT_ID_REPLY_TO }, + { "identity_organization", E_ACCOUNT_ID_ORGANIZATION }, +}; + +/* its a bit obtuse, but its simple */ +static void +emae_queue_widgets(EMAccountEditor *emae, GladeXML *xml, const gchar *first, ...) +{ + gint i = 0; + va_list ap; + + va_start(ap, first); + while (first) { + emae->priv->widgets_name[i] = first; + emae->priv->widgets[i++] = glade_xml_get_widget(xml, first); + first = va_arg(ap, const gchar *); + } + va_end(ap); + + g_return_if_fail(i < sizeof(emae->priv->widgets)/sizeof(emae->priv->widgets[0])); + + emae->priv->widgets[i] = NULL; + emae->priv->widgets_index = 0; +} + +static GtkWidget * +emae_identity_page(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + EMAccountEditor *emae = data; + EMAccountEditorPrivate *gui = emae->priv; + EAccount *account = emae->account; + gint i; + GtkWidget *w; + GladeXML *xml; + gchar *gladefile; + + /*if (old) + return old;*/ + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + "mail-config.glade", + NULL); + xml = glade_xml_new(gladefile, item->label, NULL); + g_free (gladefile); + + /* Management & Identity fields, in the druid the management frame is relocated to the last page later on */ + for (i=0;iidentity_entries[i] = emae_account_entry(emae, emae_identity_entries[i].name, emae_identity_entries[i].item, xml); + + gui->management_frame = glade_xml_get_widget(xml, "management_frame"); + + gui->default_account = GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "management_default")); + if (!e_get_default_account () + || (account == e_get_default_account ()) + || (GPOINTER_TO_INT(g_object_get_data (G_OBJECT (emae->account), "default_flagged"))) ) + gtk_toggle_button_set_active (gui->default_account, TRUE); + + if (emae->do_signature) { + emae_setup_signatures(emae, xml); + } else { + /* TODO: this could/should probably be neater */ + gtk_widget_hide(glade_xml_get_widget(xml, "sigLabel")); +#if 0 + gtk_widget_hide(glade_xml_get_widget(xml, "sigOption")); +#endif + gtk_widget_hide(glade_xml_get_widget(xml, "sigAddNew")); + } + + w = glade_xml_get_widget(xml, item->label); + if (emae->type == EMAE_PAGES) { + gtk_box_pack_start ((GtkBox *)emae->pages[0], w, TRUE, TRUE, 0); + } else if (((EConfig *)gui->config)->type == E_CONFIG_DRUID) { + GladeXML *druidxml; + GtkWidget *page; + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + "mail-config.glade", + NULL); + druidxml = glade_xml_new(gladefile, "identity_page", NULL); + g_free (gladefile); + + page = glade_xml_get_widget(druidxml, "identity_page"); + + gtk_box_pack_start((GtkBox*)((GnomeDruidPageStandard *)page)->vbox, w, TRUE, TRUE, 0); + w = page; + g_object_unref(druidxml); + gnome_druid_append_page((GnomeDruid *)parent, (GnomeDruidPage *)page); + } else { + gtk_notebook_append_page((GtkNotebook *)parent, w, gtk_label_new(_("Identity"))); + } + + emae_queue_widgets(emae, xml, "account_vbox", "identity_required_table", "identity_optional_table", NULL); + + g_object_unref(xml); + + return w; +} + +static GtkWidget * +emae_receive_page(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + EMAccountEditor *emae = data; + EMAccountEditorPrivate *gui = emae->priv; + GtkWidget *w; + GladeXML *xml; + gchar *gladefile; + + /*if (old) + return old;*/ + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + "mail-config.glade", + NULL); + xml = glade_xml_new(gladefile, item->label, NULL); + g_free (gladefile); + + gui->source.type = CAMEL_PROVIDER_STORE; + emae_setup_service(emae, &gui->source, xml); + + w = glade_xml_get_widget(xml, item->label); + if (emae->type == EMAE_PAGES) { + gtk_box_pack_start ((GtkBox *)emae->pages[1], w, TRUE, TRUE, 0); + } else if (((EConfig *)gui->config)->type == E_CONFIG_DRUID) { + GladeXML *druidxml; + GtkWidget *page; + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + "mail-config.glade", + NULL); + druidxml = glade_xml_new(gladefile, "source_page", NULL); + g_free (gladefile); + + page = glade_xml_get_widget(druidxml, "source_page"); + + gtk_box_pack_start((GtkBox*)((GnomeDruidPageStandard *)page)->vbox, w, TRUE, TRUE, 0); + w = page; + g_object_unref(druidxml); + gnome_druid_append_page((GnomeDruid *)parent, (GnomeDruidPage *)page); + } else { + gtk_notebook_append_page((GtkNotebook *)parent, w, gtk_label_new(_("Receiving Email"))); + } + + emae_queue_widgets(emae, xml, "source_type_table", "table4", "vbox181", "vbox179", NULL); + + g_object_unref(xml); + + return w; +} + +static void +emae_option_toggle_changed(GtkToggleButton *toggle, EMAccountEditorService *service) +{ + const gchar *name = g_object_get_data((GObject *)toggle, "option-name"); + GSList *depl = g_object_get_data((GObject *)toggle, "dependent-list"); + gint active = gtk_toggle_button_get_active(toggle); + CamelURL *url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); + + for (;depl;depl = g_slist_next(depl)) + gtk_widget_set_sensitive((GtkWidget *)depl->data, active); + + camel_url_set_param(url, name, active?"":NULL); + emae_uri_changed(service, url); + camel_url_free(url); +} + +static GtkWidget * +emae_option_toggle(EMAccountEditorService *service, CamelURL *url, const gchar *text, const gchar *name, gint def) +{ + GtkWidget *w; + + /* FIXME: how do we get the default value ever? */ + w = gtk_check_button_new_with_mnemonic(text); + g_object_set_data((GObject *)w, "option-name", (gpointer)name); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), camel_url_get_param (url, name) != NULL); + g_signal_connect(w, "toggled", G_CALLBACK(emae_option_toggle_changed), service); + gtk_widget_show(w); + + return w; +} + +static void +emae_option_entry_changed(GtkEntry *entry, EMAccountEditorService *service) +{ + const gchar *name = g_object_get_data((GObject *)entry, "option-name"); + const gchar *text = gtk_entry_get_text(entry); + CamelURL *url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); + + camel_url_set_param(url, name, text && text[0]?text:NULL); + emae_uri_changed(service, url); + camel_url_free(url); +} + +static GtkWidget * +emae_option_entry(EMAccountEditorService *service, CamelURL *url, const gchar *name, const gchar *def, GtkWidget *l) +{ + GtkWidget *w; + const gchar *val = camel_url_get_param(url, name); + + if (val == NULL) { + if (def) { + val = def; + camel_url_set_param(url, name, val); + emae_uri_changed(service, url); + } else + val = ""; + } + + w = g_object_new(gtk_entry_get_type(), + "text", val, + NULL); + gtk_label_set_mnemonic_widget ((GtkLabel*)l, w); + g_object_set_data((GObject *)w, "option-name", (gpointer)name); + g_signal_connect(w, "changed", G_CALLBACK(emae_option_entry_changed), service); + gtk_widget_show(w); + + return w; +} + +static void +emae_option_checkspin_changed(GtkSpinButton *spin, EMAccountEditorService *service) +{ + const gchar *name = g_object_get_data((GObject *)spin, "option-name"); + gchar value[16]; + CamelURL *url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); + + sprintf(value, "%d", gtk_spin_button_get_value_as_int(spin)); + camel_url_set_param(url, name, value); + emae_uri_changed(service, url); + camel_url_free(url); +} + +static void +emae_option_checkspin_check_changed(GtkToggleButton *toggle, EMAccountEditorService *service) +{ + const gchar *name = g_object_get_data((GObject *)toggle, "option-name"); + GtkSpinButton *spin = g_object_get_data((GObject *)toggle, "option-target"); + + if (gtk_toggle_button_get_active(toggle)) { + gtk_widget_set_sensitive((GtkWidget *)spin, TRUE); + emae_option_checkspin_changed(spin, service); + } else { + CamelURL *url = emae_account_url(service->emae, emae_service_info[service->type].account_uri_key); + + camel_url_set_param(url, name, NULL); + gtk_widget_set_sensitive((GtkWidget *)spin, FALSE); + emae_uri_changed(service, url); + camel_url_free(url); + } +} + +/* this is a fugly api */ +static GtkWidget * +emae_option_checkspin(EMAccountEditorService *service, CamelURL *url, const gchar *name, const gchar *fmt, const gchar *info) +{ + GtkWidget *hbox, *check, *spin, *label = NULL; + double min, def, max; + gchar *pre, *post; + const gchar *val; + gchar on; + gint enable; + + pre = g_alloca(strlen(fmt)+1); + strcpy(pre, fmt); + post = strstr(pre, "%s"); + if (post) { + *post = 0; + post+=2; + } + + if (sscanf(info, "%c:%lf:%lf:%lf", &on, &min, &def, &max) != 4) { + min = 0.0; + def = 0.0; + max = 1.0; + } + + if ((enable = (val = camel_url_get_param(url, name)) != NULL) ) + def = strtod(val, NULL); + else + enable = (on == 'y'); + + hbox = gtk_hbox_new(FALSE, 0); + check = g_object_new(gtk_check_button_get_type(), "label", pre, "use_underline", TRUE, "active", enable, NULL); + + spin = gtk_spin_button_new((GtkAdjustment *)gtk_adjustment_new(def, min, max, 1, 1, 0), 1, 0); + if (post) + label = gtk_label_new_with_mnemonic(post); + gtk_box_pack_start((GtkBox *)hbox, check, FALSE, TRUE, 0); + gtk_box_pack_start((GtkBox *)hbox, spin, FALSE, TRUE, 0); + if (label) + gtk_box_pack_start((GtkBox *)hbox, label, FALSE, TRUE, 4); + + g_object_set_data((GObject *)spin, "option-name", (gpointer)name); + g_object_set_data((GObject *)check, "option-name", (gpointer)name); + g_object_set_data((GObject *)check, "option-target", (gpointer)spin); + + g_signal_connect(spin, "value_changed", G_CALLBACK(emae_option_checkspin_changed), service); + g_signal_connect(check, "toggled", G_CALLBACK(emae_option_checkspin_check_changed), service); + + gtk_widget_show_all(hbox); + + return hbox; +} + +static void +emae_option_options_changed (GtkComboBox *options, EMAccountEditorService *service) +{ + const gchar *name = g_object_get_data (G_OBJECT (options), "option-name"); + gchar *value = NULL; + CamelURL *url = emae_account_url (service->emae, emae_service_info[service->type].account_uri_key); + gint id = gtk_combo_box_get_active (options); + + if (id != -1) { + GtkTreeModel *model; + GtkTreeIter iter; + + model = gtk_combo_box_get_model (options); + if (gtk_tree_model_iter_nth_child (model, &iter, NULL, id)) { + gtk_tree_model_get (model, &iter, 0, &value, -1); + } + } + + camel_url_set_param (url, name, value); + emae_uri_changed (service, url); + camel_url_free (url); + g_free (value); +} + +/* 'values' is in format "value0:caption0:value2:caption2:...valueN:captionN" */ +static GtkWidget * +emae_option_options (EMAccountEditorService *service, CamelURL *url, const gchar *name, const gchar *values, GtkWidget *l) +{ + GtkComboBox *w; + GtkListStore *store; + GtkTreeIter iter; + const gchar *p, *value, *caption; + GtkCellRenderer *cell; + gint active = 0; /* the first item entered is always a default item */ + gint i; + const gchar *val = camel_url_get_param (url, name); + + w = GTK_COMBO_BOX (gtk_combo_box_new ()); + + /* value and caption */ + store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); + + p = values; + for (p = values, i = 0; p; i++) { + gchar *vl, *cp; + + value = p; + caption = strchr (p, ':'); + if (caption) { + caption++; + } else { + g_warning (G_STRLOC ": expected ':' not found at '%s'", p); + break; + } + p = strchr (caption, ':'); + + vl = g_strndup (value, caption - value - 1); + if (p) { + p++; + cp = g_strndup (caption, p - caption - 1); + } else + cp = g_strdup (caption); + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 0, vl, 1, dgettext (service->provider->translation_domain, cp), -1); + + if (val && g_ascii_strcasecmp (val, vl) == 0) + active = i; + + g_free (vl); + g_free (cp); + } + + gtk_combo_box_set_model (w, (GtkTreeModel *)store); + gtk_combo_box_set_active (w, i > 0 ? active : -1); + + cell = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (w), cell, TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (w), cell, "text", 1, NULL); + + gtk_widget_show (GTK_WIDGET (w)); + + gtk_label_set_mnemonic_widget (GTK_LABEL (l), GTK_WIDGET (w)); + + g_object_set_data (G_OBJECT (w), "option-name", (gpointer)name); + g_signal_connect (w, "changed", G_CALLBACK (emae_option_options_changed), service); + + return GTK_WIDGET (w); +} + +static GtkWidget * +emae_receive_options_item(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + EMAccountEditor *emae = data; + GtkWidget *w, *box, *spin; + gint row; + + if (emae->priv->source.provider == NULL + || emae->priv->source.provider->extra_conf == NULL) + return NULL; + + if (old) + return old; + + /* We have to add the automatic mail check item with the rest of the receive options */ + row = ((GtkTable *)parent)->nrows; + + box = gtk_hbox_new(FALSE, 4); + w = gtk_check_button_new_with_mnemonic (_("Check for _new messages every")); + emae_account_toggle_widget(emae, (GtkToggleButton *)w, E_ACCOUNT_SOURCE_AUTO_CHECK); + gtk_box_pack_start((GtkBox *)box, w, FALSE, FALSE, 0); + + spin = gtk_spin_button_new_with_range(1.0, 1440.0, 1.0); + emae_account_spinint_widget(emae, (GtkSpinButton *)spin, E_ACCOUNT_SOURCE_AUTO_CHECK_TIME); + gtk_box_pack_start((GtkBox *)box, spin, FALSE, TRUE, 0); + + w = gtk_label_new_with_mnemonic (_("minu_tes")); + gtk_label_set_mnemonic_widget (GTK_LABEL (w), spin); + gtk_box_pack_start((GtkBox *)box, w, FALSE, FALSE, 0); + + gtk_widget_show_all(box); + + gtk_table_attach((GtkTable *)parent, box, 0, 2, row, row+1, GTK_EXPAND|GTK_FILL, 0, 0, 0); + + return box; +} + +static GtkWidget * +emae_receive_options_extra_item(EConfig *ec, EConfigItem *eitem, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + EMAccountEditor *emae = data; + struct _receive_options_item *item = (struct _receive_options_item *)eitem; + GtkWidget *w, *l, *h; + CamelProviderConfEntry *entries; + GtkWidget *depw; + GSList *depl = NULL, *n; + EMAccountEditorService *service = &emae->priv->source; + gint row, i; + GHashTable *extra; + CamelURL *url; + + if (emae->priv->source.provider == NULL + || emae->priv->source.provider->extra_conf == NULL) + return NULL; + + entries = emae->priv->source.provider->extra_conf; + for (i=0;entries && entries[i].type != CAMEL_PROVIDER_CONF_END;i++) + if (entries[i].type == CAMEL_PROVIDER_CONF_SECTION_START + && entries[i].name + && strcmp(entries[i].name, eitem->user_data) == 0) + goto section; + + return NULL; +section: + d(printf("Building extra section '%s'\n", eitem->path)); + + url = emae_account_url(emae, emae_service_info[service->type].account_uri_key); + item->extra_table = g_hash_table_new(g_str_hash, g_str_equal); + extra = g_hash_table_new(g_str_hash, g_str_equal); + row = ((GtkTable *)parent)->nrows; + + for (;entries[i].type != CAMEL_PROVIDER_CONF_END && entries[i].type != CAMEL_PROVIDER_CONF_SECTION_END;i++) { + if (entries[i].depname) { + depw = g_hash_table_lookup(extra, entries[i].depname); + if (depw) + depl = g_object_steal_data((GObject *)depw, "dependent-list"); + } else + depw = NULL; + + switch (entries[i].type) { + case CAMEL_PROVIDER_CONF_SECTION_START: + case CAMEL_PROVIDER_CONF_SECTION_END: + break; + case CAMEL_PROVIDER_CONF_LABEL: + /* FIXME: This is a hack for exchange connector, labels should be removed from confentry */ + if (!strcmp(entries[i].name, "hostname")) + l = (GtkWidget *)emae->priv->source.hostlabel; + else if (!strcmp(entries[i].name, "username")) + l = (GtkWidget *)emae->priv->source.userlabel; + else + l = NULL; + + if (l) { + gtk_label_set_text_with_mnemonic((GtkLabel *)l, entries[i].text); + if (depw) + depl = g_slist_prepend(depl, l); + } + break; + case CAMEL_PROVIDER_CONF_CHECKBOX: + w = emae_option_toggle(service, url, entries[i].text, entries[i].name, atoi(entries[i].value)); + gtk_table_attach((GtkTable *)parent, w, 0, 2, row, row+1, GTK_EXPAND|GTK_FILL, 0, 0, 0); + g_hash_table_insert(extra, (gpointer)entries[i].name, w); + if (depw) + depl = g_slist_prepend(depl, w); + row++; + /* HACK: keep_on_server is stored in the e-account, but is displayed as a properly on the uri, + make sure they track/match here */ + if (!strcmp(entries[i].name, "keep_on_server")) + emae_account_toggle_widget(emae, (GtkToggleButton *)w, E_ACCOUNT_SOURCE_KEEP_ON_SERVER); + break; + case CAMEL_PROVIDER_CONF_ENTRY: + l = g_object_new(gtk_label_get_type(), "label", entries[i].text, "xalign", 0.0, "use_underline", TRUE, NULL); + gtk_widget_show(l); + w = emae_option_entry(service, url, entries[i].name, entries[i].value, l); + gtk_table_attach((GtkTable *)parent, l, 0, 1, row, row+1, GTK_FILL, 0, 0, 0); + gtk_table_attach((GtkTable *)parent, w, 1, 2, row, row+1, GTK_EXPAND|GTK_FILL, 0, 0, 0); + if (depw) { + depl = g_slist_prepend(depl, w); + depl = g_slist_prepend(depl, l); + } + row++; + /* FIXME: this is another hack for exchange/groupwise connector */ + g_hash_table_insert(item->extra_table, (gpointer)entries[i].name, w); + break; + case CAMEL_PROVIDER_CONF_CHECKSPIN: + w = emae_option_checkspin(service, url, entries[i].name, entries[i].text, entries[i].value); + gtk_table_attach((GtkTable *)parent, w, 0, 2, row, row+1, GTK_EXPAND|GTK_FILL, 0, 0, 0); + if (depw) + depl = g_slist_prepend(depl, w); + row++; + break; + case CAMEL_PROVIDER_CONF_OPTIONS: + h = gtk_hbox_new (FALSE, 4); + gtk_widget_show (h); + l = g_object_new (gtk_label_get_type (), "label", entries[i].text, "xalign", 0.0, "use_underline", TRUE, NULL); + gtk_widget_show (l); + w = emae_option_options (service, url, entries[i].name, entries[i].value, l); + gtk_box_pack_start (GTK_BOX (h), l, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (h), w, FALSE, FALSE, 0); + gtk_table_attach ((GtkTable *)parent, h, 0, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); + if (depw) { + depl = g_slist_prepend (depl, h); + } + row++; + break; + default: + break; + } + + if (depw && depl) { + gint act = gtk_toggle_button_get_active((GtkToggleButton *)depw); + + g_object_set_data_full((GObject *)depw, "dependent-list", depl, (GDestroyNotify)g_slist_free); + for (n=depl;n;n=g_slist_next(n)) + gtk_widget_set_sensitive((GtkWidget *)n->data, act); + } + } + + camel_url_free(url); + + /* Since EConfig destroys the factory widget when it changes, we + * need to destroy our own ones as well, and add a dummy item + * so it knows this section isn't empty */ + + w = gtk_label_new(""); + gtk_widget_hide(w); + gtk_table_attach((GtkTable *)parent, w, 0, 2, row, row+1, 0, 0, 0, 0); + + return w; +} + +static GtkWidget * +emae_send_page(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + EMAccountEditor *emae = data; + EMAccountEditorPrivate *gui = emae->priv; + GtkWidget *w; + GladeXML *xml; + gchar *gladefile; + + /* no transport options page at all for these types of providers */ + if (gui->source.provider && CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT(gui->source.provider)) { + memset(&gui->transport.frame, 0, ((gchar *)&gui->transport.check_dialog)-((gchar *)&gui->transport.frame)); + return NULL; + } + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + "mail-config.glade", + NULL); + xml = glade_xml_new(gladefile, item->label, NULL); + g_free (gladefile); + + /* Transport */ + gui->transport.type = CAMEL_PROVIDER_TRANSPORT; + emae_setup_service(emae, &gui->transport, xml); + + w = glade_xml_get_widget(xml, item->label); + if (emae->type == EMAE_PAGES) { + gtk_box_pack_start ((GtkBox *)emae->pages[2], w, TRUE, TRUE, 0); + } else if (((EConfig *)gui->config)->type == E_CONFIG_DRUID) { + GladeXML *druidxml; + GtkWidget *page; + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + "mail-config.glade", + NULL); + druidxml = glade_xml_new(gladefile, "transport_page", NULL); + g_free (gladefile); + + page = glade_xml_get_widget(druidxml, "transport_page"); + + gtk_box_pack_start((GtkBox*)((GnomeDruidPageStandard *)page)->vbox, w, TRUE, TRUE, 0); + w = page; + g_object_unref(druidxml); + gnome_druid_append_page((GnomeDruid *)parent, (GnomeDruidPage *)page); + } else { + gtk_notebook_append_page((GtkNotebook *)parent, w, gtk_label_new(_("Sending Email"))); + } + + emae_queue_widgets(emae, xml, "transport_type_table", "vbox12", "vbox183", "vbox61", NULL); + + g_object_unref(xml); + + return w; +} + +static GtkWidget * +emae_defaults_page(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + EMAccountEditor *emae = data; + EMAccountEditorPrivate *gui = emae->priv; + GtkWidget *w; + GladeXML *xml; + gchar *gladefile; + + /*if (old) + return old;*/ + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + "mail-config.glade", + NULL); + xml = glade_xml_new(gladefile, item->label, NULL); + g_free (gladefile); + + /* Special folders */ + gui->drafts_folder_button = (GtkButton *)emae_account_folder(emae, "drafts_button", E_ACCOUNT_DRAFTS_FOLDER_URI, E_MAIL_FOLDER_DRAFTS, xml); + gui->sent_folder_button = (GtkButton *)emae_account_folder(emae, "sent_button", E_ACCOUNT_SENT_FOLDER_URI, E_MAIL_FOLDER_SENT, xml); + + /* Special Folders "Reset Defaults" button */ + gui->restore_folders_button = (GtkButton *)glade_xml_get_widget (xml, "default_folders_button"); + g_signal_connect (gui->restore_folders_button, "clicked", G_CALLBACK (default_folders_clicked), emae); + + /* Always Cc/Bcc */ + emae_account_toggle(emae, "always_cc", E_ACCOUNT_CC_ALWAYS, xml); + emae_account_entry(emae, "cc_addrs", E_ACCOUNT_CC_ADDRS, xml); + emae_account_toggle(emae, "always_bcc", E_ACCOUNT_BCC_ALWAYS, xml); + emae_account_entry(emae, "bcc_addrs", E_ACCOUNT_BCC_ADDRS, xml); + + gtk_widget_set_sensitive((GtkWidget *)gui->drafts_folder_button, e_account_writable(emae->account, E_ACCOUNT_DRAFTS_FOLDER_URI)); + + gtk_widget_set_sensitive( (GtkWidget *)gui->sent_folder_button, + e_account_writable(emae->account, E_ACCOUNT_SENT_FOLDER_URI) + && + (emae->priv->source.provider ? !(emae->priv->source.provider->flags & CAMEL_PROVIDER_DISABLE_SENT_FOLDER): TRUE) + ); + + gtk_widget_set_sensitive((GtkWidget *)gui->restore_folders_button, + (e_account_writable(emae->account, E_ACCOUNT_SENT_FOLDER_URI) + && ((emae->priv->source.provider && !( emae->priv->source.provider->flags & CAMEL_PROVIDER_DISABLE_SENT_FOLDER)) + || e_account_writable(emae->account, E_ACCOUNT_DRAFTS_FOLDER_URI)))); + + /* Receipt policy */ + emae_setup_receipt_policy (emae, xml); + + w = glade_xml_get_widget(xml, item->label); + gtk_notebook_append_page((GtkNotebook *)parent, w, gtk_label_new(_("Defaults"))); + + emae_queue_widgets(emae, xml, "vbox184", "table8", NULL); + + g_object_unref(xml); + + return w; +} + +static GtkWidget * +emae_security_page(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + EMAccountEditor *emae = data; +#if defined (HAVE_NSS) + EMAccountEditorPrivate *gui = emae->priv; +#endif + GtkWidget *w; + GladeXML *xml; + gchar *gladefile; + + /*if (old) + return old;*/ + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + "mail-config.glade", + NULL); + xml = glade_xml_new(gladefile, item->label, NULL); + g_free (gladefile); + + /* Security */ + emae_account_entry(emae, "pgp_key", E_ACCOUNT_PGP_KEY, xml); + emae_account_toggle(emae, "pgp_encrypt_to_self", E_ACCOUNT_PGP_ENCRYPT_TO_SELF, xml); + emae_account_toggle(emae, "pgp_always_sign", E_ACCOUNT_PGP_ALWAYS_SIGN, xml); + emae_account_toggle(emae, "pgp_no_imip_sign", E_ACCOUNT_PGP_NO_IMIP_SIGN, xml); + emae_account_toggle(emae, "pgp_always_trust", E_ACCOUNT_PGP_ALWAYS_TRUST, xml); + +#if defined (HAVE_NSS) + /* TODO: this should handle its entry separately? */ + gui->smime_sign_key = emae_account_entry(emae, "smime_sign_key", E_ACCOUNT_SMIME_SIGN_KEY, xml); + gui->smime_sign_key_select = (GtkButton *)glade_xml_get_widget (xml, "smime_sign_key_select"); + gui->smime_sign_key_clear = (GtkButton *)glade_xml_get_widget (xml, "smime_sign_key_clear"); + g_signal_connect(gui->smime_sign_key_select, "clicked", G_CALLBACK(smime_sign_key_select), emae); + g_signal_connect(gui->smime_sign_key_clear, "clicked", G_CALLBACK(smime_sign_key_clear), emae); + + gui->smime_sign_default = emae_account_toggle(emae, "smime_sign_default", E_ACCOUNT_SMIME_SIGN_DEFAULT, xml); + + gui->smime_encrypt_key = emae_account_entry(emae, "smime_encrypt_key", E_ACCOUNT_SMIME_ENCRYPT_KEY, xml); + gui->smime_encrypt_key_select = (GtkButton *)glade_xml_get_widget (xml, "smime_encrypt_key_select"); + gui->smime_encrypt_key_clear = (GtkButton *)glade_xml_get_widget (xml, "smime_encrypt_key_clear"); + g_signal_connect(gui->smime_encrypt_key_select, "clicked", G_CALLBACK(smime_encrypt_key_select), emae); + g_signal_connect(gui->smime_encrypt_key_clear, "clicked", G_CALLBACK(smime_encrypt_key_clear), emae); + + gui->smime_encrypt_default = emae_account_toggle(emae, "smime_encrypt_default", E_ACCOUNT_SMIME_ENCRYPT_DEFAULT, xml); + gui->smime_encrypt_to_self = emae_account_toggle(emae, "smime_encrypt_to_self", E_ACCOUNT_SMIME_ENCRYPT_TO_SELF, xml); + smime_changed(emae); +#else + { + /* Since we don't have NSS, hide the S/MIME config options */ + GtkWidget *frame; + + frame = glade_xml_get_widget(xml, "smime_vbox"); + gtk_widget_destroy(frame); + } +#endif /* HAVE_NSS */ + + w = glade_xml_get_widget(xml, item->label); + gtk_notebook_append_page((GtkNotebook *)parent, w, gtk_label_new(_("Security"))); + + g_object_unref(xml); + + return w; +} + +static GtkWidget * +emae_widget_glade(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + EMAccountEditor *emae = data; + gint i; + + for (i=0;emae->priv->widgets[i];i++) + if (!strcmp(emae->priv->widgets_name[i], item->label)) + return emae->priv->widgets[i]; + + g_warning("Mail account widget '%s' not found", item->label); + + return NULL; +} + +/* plugin meta-data for "org.gnome.evolution.mail.config.accountEditor" */ +static EMConfigItem emae_editor_items[] = { + { E_CONFIG_BOOK, (gchar *) "" }, + { E_CONFIG_PAGE, (gchar *) "00.identity", (gchar *) "vboxIdentityBorder", emae_identity_page }, + { E_CONFIG_SECTION, (gchar *) "00.identity/00.name", (gchar *) "account_vbox", emae_widget_glade }, + { E_CONFIG_SECTION_TABLE, (gchar *) "00.identity/10.required", (gchar *) "identity_required_table", emae_widget_glade }, + { E_CONFIG_SECTION_TABLE, (gchar *) "00.identity/20.info", (gchar *) "identity_optional_table", emae_widget_glade }, + + { E_CONFIG_PAGE, (gchar *) "10.receive", (gchar *) "vboxSourceBorder", emae_receive_page }, + { E_CONFIG_SECTION_TABLE, (gchar *) "10.receive/00.type", (gchar *) "source_type_table", emae_widget_glade }, + { E_CONFIG_SECTION_TABLE, (gchar *) "10.receive/10.config", (gchar *) "table4", emae_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "10.receive/20.security", (gchar *) "vbox181", emae_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "10.receive/30.auth", (gchar *) "vbox179", emae_widget_glade }, + + /* Most sections for this is auto-generated from the camel config */ + { E_CONFIG_PAGE, (gchar *) "20.receive_options", (gchar *) N_("Receiving Options"), }, + { E_CONFIG_SECTION_TABLE, (gchar *) "20.receive_options/10.mailcheck", (gchar *) N_("Checking for New Messages"), }, + { E_CONFIG_ITEM_TABLE, (gchar *) "20.receive_options/10.mailcheck/00.autocheck", NULL, emae_receive_options_item, }, + + { E_CONFIG_PAGE, (gchar *) "30.send", (gchar *) "vboxTransportBorder", emae_send_page }, + { E_CONFIG_SECTION_TABLE, (gchar *) "30.send/00.type", (gchar *) "transport_type_table", emae_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "30.send/10.config", (gchar *) "vbox12", emae_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "30.send/20.security", (gchar *) "vbox183", emae_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "30.send/30.auth", (gchar *) "vbox61", emae_widget_glade }, + + { E_CONFIG_PAGE, (gchar *) "40.defaults", (gchar *) "vboxFoldersBorder", emae_defaults_page }, + { E_CONFIG_SECTION, (gchar *) "40.defaults/00.folders", (gchar *) "vbox184", emae_widget_glade }, + { E_CONFIG_SECTION_TABLE, (gchar *) "40.defaults/10.composing", (gchar *) "table8", emae_widget_glade }, + + { E_CONFIG_PAGE, (gchar *) "50.security", (gchar *) "vboxSecurityBorder", emae_security_page }, + /* 1x1 table(!) not vbox: { E_CONFIG_SECTION, "50.security/00.gpg", "table19", emae_widget_glade }, */ + /* table not vbox: { E_CONFIG_SECTION, "50.security/10.smime", "smime_table", emae_widget_glade }, */ + { 0 }, +}; +static gboolean emae_editor_items_translated = FALSE; + +static GtkWidget * +emae_management_page(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + EMAccountEditor *emae = data; + EMAccountEditorPrivate *gui = emae->priv; + GtkWidget *w; + + w = gui->management_frame; + if (((EConfig *)gui->config)->type == E_CONFIG_DRUID) { + GladeXML *druidxml; + GtkWidget *page; + gchar *gladefile; + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + "mail-config.glade", + NULL); + druidxml = glade_xml_new(gladefile, "management_page", NULL); + g_free (gladefile); + + page = glade_xml_get_widget(druidxml, "management_page"); + + gtk_widget_reparent(w, ((GnomeDruidPageStandard *)page)->vbox); + w = page; + g_object_unref(druidxml); + gnome_druid_append_page((GnomeDruid *)parent, (GnomeDruidPage *)page); + } + + return w; +} + +static GtkWidget * +emae_widget_druid_glade(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + GladeXML *druidxml; + GtkWidget *w; + gchar *gladefile; + EMAccountEditor *emae = (EMAccountEditor *)data; + + if (emae->type == EMAE_PAGES) + return NULL; + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + "mail-config.glade", + NULL); + druidxml = glade_xml_new(gladefile, item->label, NULL); + g_free (gladefile); + + w = glade_xml_get_widget(druidxml, item->label); + /* i think the glade file has issues, we need to show all on at least the end page */ + gtk_widget_show_all(w); + g_object_unref(druidxml); + + gnome_druid_append_page((GnomeDruid *)parent, (GnomeDruidPage *)w); + + return w; +} + +/* plugin meta-data for "org.gnome.evolution.mail.config.accountDruid" */ +static EMConfigItem emae_druid_items[] = { + { E_CONFIG_DRUID, (gchar *) "" }, + { E_CONFIG_PAGE_START, (gchar *) "0.start", (gchar *) "start_page", emae_widget_druid_glade }, + + { E_CONFIG_PAGE, (gchar *) "00.identity", (gchar *) "vboxIdentityBorder", emae_identity_page }, + { E_CONFIG_SECTION, (gchar *) "00.identity/00.name", (gchar *) "account_vbox", emae_widget_glade }, + { E_CONFIG_SECTION_TABLE, (gchar *) "00.identity/10.required", (gchar *) "identity_required_table", emae_widget_glade }, + { E_CONFIG_SECTION_TABLE, (gchar *) "00.identity/20.info", (gchar *) "identity_optional_table", emae_widget_glade }, + + { E_CONFIG_PAGE, (gchar *) "10.receive", (gchar *) "vboxSourceBorder", emae_receive_page }, + { E_CONFIG_SECTION_TABLE, (gchar *) "10.receive/00.type", (gchar *) "source_type_table", emae_widget_glade }, + { E_CONFIG_SECTION_TABLE, (gchar *) "10.receive/10.config", (gchar *) "table4", emae_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "10.receive/20.security", (gchar *) "vbox181", emae_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "10.receive/30.auth", (gchar *) "vbox179", emae_widget_glade }, + + /* Most sections for this is auto-generated fromt the camel config */ + { E_CONFIG_PAGE, (gchar *) "20.receive_options", (gchar *) N_("Receiving Options"), }, + { E_CONFIG_SECTION_TABLE, (gchar *) "20.receive_options/10.mailcheck", (gchar *) N_("Checking for New Messages"), }, + { E_CONFIG_ITEM_TABLE, (gchar *) "20.receive_options/10.mailcheck/00.autocheck", NULL, emae_receive_options_item, }, + + { E_CONFIG_PAGE, (gchar *) "30.send", (gchar *) "vboxTransportBorder", emae_send_page }, + { E_CONFIG_SECTION_TABLE, (gchar *) "30.send/00.type", (gchar *) "transport_type_table", emae_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "30.send/10.config", (gchar *) "vbox12", emae_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "30.send/20.security", (gchar *) "vbox183", emae_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "30.send/30.auth", (gchar *) "vbox61", emae_widget_glade }, + + { E_CONFIG_PAGE, (gchar *) "40.management", (gchar *) "management_frame", emae_management_page }, + + { E_CONFIG_PAGE_FINISH, (gchar *) "999.end", (gchar *) "finish_page", emae_widget_druid_glade }, + { 0 }, +}; +static gboolean emae_druid_items_translated = FALSE; + +static void +emae_free(EConfig *ec, GSList *items, gpointer data) +{ + g_slist_free(items); +} + +static void +emae_free_auto(EConfig *ec, GSList *items, gpointer data) +{ + GSList *l, *n; + + for (l=items;l;) { + struct _receive_options_item *item = l->data; + + n = g_slist_next(l); + g_free(item->item.path); + if (item->extra_table) + g_hash_table_destroy(item->extra_table); + g_free(item); + g_slist_free_1(l); + l = n; + } +} + +static gboolean +emae_service_complete(EMAccountEditor *emae, EMAccountEditorService *service) +{ + CamelURL *url; + gint ok = TRUE; + const gchar *uri; + + if (service->provider == NULL) + return TRUE; + + uri = e_account_get_string(emae->account, emae_service_info[service->type].account_uri_key); + if (uri == NULL || (url = camel_url_new(uri, NULL)) == NULL) + return FALSE; + + if (CAMEL_PROVIDER_NEEDS(service->provider, CAMEL_URL_PART_HOST)) { + if (url->host == NULL || url->host[0] == 0) + ok = FALSE; + } + /* We only need the user if the service needs auth as well, i think */ + if (ok + && (service->needs_auth == NULL + || CAMEL_PROVIDER_NEEDS(service->provider, CAMEL_URL_PART_AUTH) + || gtk_toggle_button_get_active(service->needs_auth)) + && CAMEL_PROVIDER_NEEDS(service->provider, CAMEL_URL_PART_USER) + && (url->user == NULL || url->user[0] == 0)) + ok = FALSE; + + if (ok + && CAMEL_PROVIDER_NEEDS(service->provider, CAMEL_URL_PART_PATH) + && (url->path == NULL || url->path[0] == 0)) + ok = FALSE; + + camel_url_free(url); + + return ok; +} + +enum { + GMAIL = 0, + YAHOO, + AOL +}; +struct _server_prefill { + const gchar *key; + const gchar *recv; + const gchar *send; + const gchar *proto; + const gchar *ssl; +} mail_servers [] = { + {"gmail", "imap.gmail.com", "smtp.gmail.com", "imap", "always"}, + {"yahoo", "pop3.yahoo.com", "smtp.yahoo.com", "pop", "never"}, + {"aol", "imap.aol.com", "smtp.aol.com", "pop", "never"}, + {"msn", "pop3.email.msn.com", "smtp.email.msn.com", "pop", "never"} +}; + +static gint +check_servers (gchar *server) +{ + gint len = G_N_ELEMENTS(mail_servers), i; + + for (i=0; ipriv->config)->type == E_CONFIG_DRUID) { + if (!strcmp(pageid, "00.identity")) { + if (!emae->priv->identity_set) { + gchar *uname; + + emae->priv->identity_set = 1; +#ifndef G_OS_WIN32 + uname = g_locale_to_utf8(g_get_real_name(), -1, NULL, NULL, NULL); +#else + uname = g_strdup(g_get_real_name()); +#endif + if (uname) { + gtk_entry_set_text(emae->priv->identity_entries[1], uname); + g_free(uname); + } + } + } else if (!strcmp(pageid, "10.receive")) { + if (!emae->priv->receive_set) { + gchar *user, *at; + gint index; + gchar *uri = g_strdup(e_account_get_string(emae->account, E_ACCOUNT_SOURCE_URL)); + CamelURL *url; + + emae->priv->receive_set = 1; + tmp = (gchar *)e_account_get_string(emae->account, E_ACCOUNT_ID_ADDRESS); + at = strchr(tmp, '@'); + user = g_alloca(at-tmp+1); + memcpy(user, tmp, at-tmp); + user[at-tmp] = 0; + at++; + + index = check_servers(at); + gtk_entry_set_text(emae->priv->source.username, user); + gtk_entry_set_text(emae->priv->transport.username, user); + if (uri && (url = camel_url_new(uri, NULL)) != NULL) { + refresh = TRUE; + camel_url_set_protocol(url, mail_servers[index].proto); + camel_url_set_param(url, "use_ssl", mail_servers[index].ssl); + camel_url_set_host (url, mail_servers[index].recv); + camel_url_set_user (url, user); + gtk_entry_set_text(emae->priv->source.hostname, mail_servers[index].recv); + gtk_entry_set_text(emae->priv->transport.hostname, mail_servers[index].send); + uri = camel_url_to_string(url, 0); + e_account_set_string(emae->account, E_ACCOUNT_SOURCE_URL, uri); + + g_free(uri); + camel_url_free(url); + } + + } + } else if (!strcmp(pageid, "30.send")) { + CamelURL *url; + gchar *at, *user; + gint index; + gchar *uri = (gchar *)e_account_get_string(emae->account, E_ACCOUNT_TRANSPORT_URL); + + tmp = e_account_get_string(emae->account, E_ACCOUNT_ID_ADDRESS); + at = strchr(tmp, '@'); + user = g_alloca(at-tmp+1); + memcpy(user, tmp, at-tmp); + user[at-tmp] = 0; + at++; + + index = check_servers(at); + if (uri && (url = camel_url_new(uri, NULL)) != NULL) { + refresh = TRUE; + camel_url_set_protocol (url, "smtp"); + camel_url_set_param(url, "use_ssl", mail_servers[index].ssl); + camel_url_set_host (url, mail_servers[index].send); + camel_url_set_user (url, user); + uri = camel_url_to_string(url, 0); + e_account_set_string(emae->account, E_ACCOUNT_TRANSPORT_URL, uri); + g_free(uri); + camel_url_free(url); + } else { + g_warning("buz2\n"); + } + + } else if (!strcmp(pageid, "20.receive_options")) { + if (emae->priv->source.provider + && emae->priv->extra_provider != emae->priv->source.provider) { + emae->priv->extra_provider = emae->priv->source.provider; + emae_auto_detect(emae); + } + } else if (!strcmp(pageid, "40.management")) { + if (!emae->priv->management_set) { + gchar *template; + guint i = 0, len; + + emae->priv->management_set = 1; + tmp = e_account_get_string(emae->account, E_ACCOUNT_ID_ADDRESS); + len = strlen(tmp); + template = alloca(len + 14); + strcpy(template, tmp); + while (e_get_account_by_name (template)) + sprintf(template + len, " (%d)", i++); + + gtk_entry_set_text(emae->priv->identity_entries[0], template); + } + } + } + + /* + Setting a flag on the Account if it is marked as default. It is done in this way instead of + using a temporary variable so as to keep track of which account is marked as default in case of + editing multiple accounts at a time + */ + if (gtk_toggle_button_get_active(emae->priv->default_account)) + g_object_set_data (G_OBJECT (emae->account), "default_flagged", GINT_TO_POINTER(1)); + + if (pageid == NULL || !strcmp(pageid, "00.identity")) { + /* TODO: check the account name is set, and unique in the account list */ + ok = (tmp = e_account_get_string(emae->account, E_ACCOUNT_ID_NAME)) + && tmp[0] + && (tmp = e_account_get_string(emae->account, E_ACCOUNT_ID_ADDRESS)) + && is_email(tmp) + && ((tmp = e_account_get_string(emae->account, E_ACCOUNT_ID_REPLY_TO)) == NULL + || tmp[0] == 0 + || is_email(tmp)); + if (!ok) { + d(printf("identity incomplete\n")); + } + } + + if (ok && (pageid == NULL || !strcmp(pageid, "10.receive"))) { + if (emae->type == EMAE_PAGES && refresh) { + emae_refresh_providers(emae, &emae->priv->source); + } + ok = emae_service_complete(emae, &emae->priv->source); + if (!ok) { + d(printf("receive page incomplete\n")); + } + } + + if (ok && (pageid == NULL || !strcmp(pageid, "30.send"))) { + if (emae->type == EMAE_PAGES && refresh) { + emae_refresh_providers(emae, &emae->priv->transport); + } + ok = emae_service_complete(emae, &emae->priv->transport); + if (!ok) { + d(printf("send page incomplete\n")); + } + } + + if (ok && (pageid == NULL || !strcmp(pageid, "40.management"))) { + ok = (tmp = e_account_get_string(emae->account, E_ACCOUNT_NAME)) + && tmp[0] + && ((ea = e_get_account_by_name (tmp)) == NULL + || ea == emae->original); + if (!ok) { + d(printf("management page incomplete\n")); + } + } + + return ok; +} + +void +em_account_editor_check (EMAccountEditor *emae, const gchar *page) +{ + emae_check_complete((EConfig *)emae->config, page, emae); +} + +/* HACK: FIXME: the component should listen to the account object directly */ +static void +add_new_store (gchar *uri, CamelStore *store, gpointer user_data) +{ +#if 0 /* KILL-BONOBO: Try to actually fix this? */ + MailComponent *component = mail_component_peek (); + EAccount *account = user_data; + + if (store == NULL) + return; + + mail_component_add_store (component, store, account->name); +#endif +} + +static void +emae_commit(EConfig *ec, GSList *items, gpointer data) +{ + EMAccountEditor *emae = data; + EAccountList *accounts = e_get_account_list (); + EAccount *account; + + /* the mail-config*acconts* api needs a lot of work */ + + if (emae->original) { + d(printf("Committing account '%s'\n", e_account_get_string(emae->account, E_ACCOUNT_NAME))); + e_account_import(emae->original, emae->account); + account = emae->original; + e_account_list_change(accounts, account); + } else { + d(printf("Adding new account '%s'\n", e_account_get_string(emae->account, E_ACCOUNT_NAME))); + e_account_list_add(accounts, emae->account); + account = emae->account; + + /* HACK: this will add the account to the folder tree. + We should just be listening to the account list directly for changed events */ + if (account->enabled + && emae->priv->source.provider + && (emae->priv->source.provider->flags & CAMEL_PROVIDER_IS_STORAGE)) + mail_get_store(e_account_get_string(emae->account, E_ACCOUNT_SOURCE_URL), NULL, add_new_store, account); + } + + if (gtk_toggle_button_get_active(emae->priv->default_account)) + e_account_list_set_default(accounts, account); + + e_account_list_save(accounts); +} + +void +em_account_editor_commit (EMAccountEditor *emae) +{ + emae_commit ((EConfig *)emae->config, NULL, emae); +} + +static void +emae_editor_destroyed(GtkWidget *dialog, EMAccountEditor *emae) +{ + emae->editor = NULL; + g_object_unref(emae); +} + +static void +em_account_editor_construct(EMAccountEditor *emae, EAccount *account, em_account_editor_t type, const gchar *id) +{ + EMAccountEditorPrivate *gui = emae->priv; + gint i, index; + GSList *l; + GList *prov; + EMConfig *ec; + EMConfigTargetAccount *target; + GHashTable *have; + EConfigItem *items; + + emae->type = type; + emae->original = account; + if (emae->original) { + gchar *xml; + + g_object_ref(emae->original); + xml = e_account_to_xml(emae->original); + emae->account = e_account_new_from_xml(xml); + g_free(xml); + + emae->do_signature = TRUE; + } else { + /* TODO: have a get_default_account thing?? */ + emae->account = e_account_new(); + emae->account->enabled = TRUE; + + e_account_set_string ( + emae->account, E_ACCOUNT_DRAFTS_FOLDER_URI, + e_mail_local_get_folder_uri (E_MAIL_FOLDER_DRAFTS)); + + e_account_set_string ( + emae->account, E_ACCOUNT_SENT_FOLDER_URI, + e_mail_local_get_folder_uri (E_MAIL_FOLDER_SENT)); + } + + /* sort the providers, remote first */ + gui->providers = g_list_sort(camel_provider_list(TRUE), (GCompareFunc)provider_compare); + + if (type == EMAE_NOTEBOOK) { + ec = em_config_new(E_CONFIG_BOOK, id); + items = emae_editor_items; + if (!emae_editor_items_translated) { + for (i=0;items[i].path;i++) { + if (items[i].label) + items[i].label = gettext(items[i].label); + } + emae_editor_items_translated = TRUE; + } + } else { + ec = em_config_new(E_CONFIG_DRUID, id); + items = emae_druid_items; + if (!emae_druid_items_translated) { + for (i=0;items[i].path;i++) { + if (items[i].label) + items[i].label = _(items[i].label); + } + emae_druid_items_translated = TRUE; + } + } + + emae->config = gui->config = ec; + l = NULL; + for (i=0;items[i].path;i++) + l = g_slist_prepend(l, &items[i]); + e_config_add_items((EConfig *)ec, l, emae_commit, NULL, emae_free, emae); + + /* This is kinda yuck, we're dynamically mapping from the 'old style' extensibility api to the new one */ + l = NULL; + have = g_hash_table_new(g_str_hash, g_str_equal); + index = 20; + for (prov=gui->providers;prov;prov=g_list_next(prov)) { + CamelProviderConfEntry *entries = ((CamelProvider *)prov->data)->extra_conf; + + for (i=0;entries && entries[i].type != CAMEL_PROVIDER_CONF_END;i++) { + struct _receive_options_item *item; + const gchar *name = entries[i].name; + gint myindex = index; + + if (entries[i].type != CAMEL_PROVIDER_CONF_SECTION_START + || name == NULL + || g_hash_table_lookup(have, name)) + continue; + + /* override mailcheck since we also insert our own mailcheck item at this index */ + if (name && !strcmp(name, "mailcheck")) + myindex = 10; + + item = g_malloc0(sizeof(*item)); + item->item.type = E_CONFIG_SECTION_TABLE; + item->item.path = g_strdup_printf("20.receive_options/%02d.%s", myindex, name?name:"unnamed"); + item->item.label = g_strdup (entries[i].text); + + l = g_slist_prepend(l, item); + + item = g_malloc0(sizeof(*item)); + item->item.type = E_CONFIG_ITEM_TABLE; + item->item.path = g_strdup_printf("20.receive_options/%02d.%s/80.camelitem", myindex, name?name:"unnamed"); + item->item.factory = emae_receive_options_extra_item; + item->item.user_data = g_strdup (entries[i].name); + + l = g_slist_prepend(l, item); + + index += 10; + g_hash_table_insert(have, (gpointer)entries[i].name, have); + } + } + g_hash_table_destroy(have); + e_config_add_items((EConfig *)ec, l, NULL, NULL, emae_free_auto, emae); + gui->extra_items = l; + + e_config_add_page_check((EConfig *)ec, NULL, emae_check_complete, emae); + + target = em_config_target_new_account(ec, emae->account); + e_config_set_target((EConfig *)ec, (EConfigTarget *)target); + + if (type != EMAE_PAGES) { + emae->editor = e_config_create_window((EConfig *)ec, NULL, type==EMAE_NOTEBOOK?_("Account Editor"):_("Evolution Account Assistant")); + g_signal_connect(emae->editor, "destroy", G_CALLBACK(emae_editor_destroyed), emae); + } else { + e_config_create_widget((EConfig *)ec); + } +} diff --git a/modules/mail/em-account-editor.h b/modules/mail/em-account-editor.h new file mode 100644 index 0000000000..d8d96f58f0 --- /dev/null +++ b/modules/mail/em-account-editor.h @@ -0,0 +1,86 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Jeffrey Stedfast + * Dan Winship + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef EM_ACCOUNT_EDITOR_H +#define EM_ACCOUNT_EDITOR_H + +#include + +#include + +G_BEGIN_DECLS + +typedef struct _EMAccountEditor EMAccountEditor; +typedef struct _EMAccountEditorClass EMAccountEditorClass; +typedef struct _EMAccountEditorPrivate EMAccountEditorPrivate; + +typedef enum { + EMAE_NOTEBOOK, + EMAE_DRUID, + EMAE_PAGES +} em_account_editor_t; + +struct _EMAccountEditor { + GObject gobject; + + EMAccountEditorPrivate *priv; + + em_account_editor_t type; + GtkWidget *editor; /* gtknotebook or druid, depending on type */ + + EMConfig *config; /* driver object */ + + EAccount *account; /* working account, must instant apply to this */ + EAccount *original; /* original account, not changed unless commit is invoked */ + + GtkWidget **pages; /* Pages for Anjal's page type editor */ + + guint do_signature:1; /* allow editing signature */ +}; + +struct _EMAccountEditorClass { + GObjectClass gobject_class; +}; + +GType em_account_editor_get_type(void); + +EMAccountEditor *em_account_editor_new(EAccount *account, em_account_editor_t type, const gchar *id); +EMAccountEditor *em_account_editor_new_for_pages(EAccount *account, em_account_editor_t type, gchar *id, GtkWidget **pages); +void em_account_editor_commit (EMAccountEditor *emae); +void em_account_editor_check (EMAccountEditor *emae, const gchar *page); + +gboolean em_account_editor_save (EMAccountEditor *gui); +void em_account_editor_destroy (EMAccountEditor *gui); + +gboolean em_account_editor_identity_complete (EMAccountEditor *gui, GtkWidget **incomplete); +gboolean em_account_editor_source_complete (EMAccountEditor *gui, GtkWidget **incomplete); +gboolean em_account_editor_transport_complete (EMAccountEditor *gui, GtkWidget **incomplete); +gboolean em_account_editor_management_complete (EMAccountEditor *gui, GtkWidget **incomplete); + +void em_account_editor_build_extra_conf (EMAccountEditor *gui, const gchar *url); + +void em_account_editor_auto_detect_extra_conf (EMAccountEditor *gui); + +G_END_DECLS + +#endif /* EM_ACCOUNT_EDITOR_H */ diff --git a/modules/mail/em-account-prefs.c b/modules/mail/em-account-prefs.c new file mode 100644 index 0000000000..f2c646d5ed --- /dev/null +++ b/modules/mail/em-account-prefs.c @@ -0,0 +1,323 @@ +/* + * em-account-prefs.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/* XXX EAccountManager handles all the user interface stuff. This subclass + * applies policies using mailer resources that EAccountManager does not + * have access to. The desire is to someday move account management + * completely out of the mailer, perhaps to evolution-data-server. */ + +#include "em-account-prefs.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include + +#include "e-util/e-error.h" + +#include "e-mail-store.h" +#include "em-config.h" +#include "em-account-editor.h" + +#define EM_ACCOUNT_PREFS_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EM_TYPE_ACCOUNT_PREFS, EMAccountPrefsPrivate)) + +struct _EMAccountPrefsPrivate { + gpointer druid; /* weak pointer */ + gpointer editor; /* weak pointer */ +}; + +static gpointer parent_class; + +static void +account_prefs_enable_account_cb (EAccountTreeView *tree_view) +{ + EAccount *account; + + account = e_account_tree_view_get_selected (tree_view); + g_return_if_fail (account != NULL); + + e_mail_store_add_by_uri (account->source->url, account->name); +} + +static void +account_prefs_disable_account_cb (EAccountTreeView *tree_view) +{ + EAccountList *account_list; + EAccount *account; + gpointer parent; + gint response; + + account = e_account_tree_view_get_selected (tree_view); + g_return_if_fail (account != NULL); + + account_list = e_account_tree_view_get_account_list (tree_view); + g_return_if_fail (account_list != NULL); + + if (!e_account_list_account_has_proxies (account_list, account)) + return; + + parent = gtk_widget_get_toplevel (GTK_WIDGET (tree_view)); + parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; + + response = e_error_run ( + parent, "mail:ask-delete-proxy-accounts", NULL); + + if (response != GTK_RESPONSE_YES) { + g_signal_stop_emission_by_name (tree_view, "disable-account"); + return; + } + + e_account_list_remove_account_proxies (account_list, account); + + e_mail_store_remove_by_uri (account->source->url); +} + +static void +account_prefs_add_account (EAccountManager *manager) +{ + EMAccountPrefsPrivate *priv; + EMAccountEditor *emae; + gpointer parent; + + priv = EM_ACCOUNT_PREFS_GET_PRIVATE (manager); + + if (priv->druid != NULL) { + gtk_window_present (GTK_WINDOW (priv->druid)); + return; + } + + parent = gtk_widget_get_toplevel (GTK_WIDGET (manager)); + parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; + + /** @HookPoint-EMConfig: New Mail Account Druid + * @Id: org.gnome.evolution.mail.config.accountDruid + * @Type: E_CONFIG_DRUID + * @Class: org.gnome.evolution.mail.config:1.0 + * @Target: EMConfigTargetAccount + * + * The new mail account druid. + */ + emae = em_account_editor_new ( + NULL, EMAE_DRUID, + "org.gnome.evolution.mail.config.accountDruid"); + priv->druid = emae->editor; + + g_object_add_weak_pointer (G_OBJECT (priv->druid), &priv->druid); + gtk_window_set_transient_for (GTK_WINDOW (priv->druid), parent); + gtk_widget_show (priv->druid); +} + +static void +account_prefs_edit_account (EAccountManager *manager) +{ + EMAccountPrefsPrivate *priv; + EMAccountEditor *emae; + EAccountTreeView *tree_view; + EAccountList *account_list; + EAccount *account; + gpointer parent; + + priv = EM_ACCOUNT_PREFS_GET_PRIVATE (manager); + + if (priv->editor != NULL) { + gtk_window_present (GTK_WINDOW (priv->editor)); + return; + } + + account_list = e_account_manager_get_account_list (manager); + tree_view = e_account_manager_get_tree_view (manager); + account = e_account_tree_view_get_selected (tree_view); + g_return_if_fail (account != NULL); + + parent = gtk_widget_get_toplevel (GTK_WIDGET (manager)); + parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; + + /** @HookPoint-EMConfig: Mail Account Editor + * @Id: org.gnome.evolution.mail.config.accountEditor + * @Type: E_CONFIG_BOOK + * @Class: org.gnome.evolution.mail.config:1.0 + * @Target: EMConfigTargetAccount + * + * The account editor window. + */ + emae = em_account_editor_new ( + account, EMAE_NOTEBOOK, + "org.gnome.evolution.mail.config.accountEditor"); + priv->editor = emae->editor; + + g_object_add_weak_pointer (G_OBJECT (priv->editor), &priv->editor); + gtk_window_set_transient_for (GTK_WINDOW (priv->editor), parent); + gtk_widget_show (priv->editor); +} + +static void +account_prefs_delete_account (EAccountManager *manager) +{ + EMAccountPrefsPrivate *priv; + EAccountTreeView *tree_view; + EAccountList *account_list; + EAccount *account; + gboolean has_proxies; + gpointer parent; + gint response; + + priv = EM_ACCOUNT_PREFS_GET_PRIVATE (manager); + + account_list = e_account_manager_get_account_list (manager); + tree_view = e_account_manager_get_tree_view (manager); + account = e_account_tree_view_get_selected (tree_view); + g_return_if_fail (account != NULL); + + /* Make sure we aren't editing anything... */ + if (priv->editor != NULL) + return; + + parent = gtk_widget_get_toplevel (GTK_WIDGET (manager)); + parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; + + has_proxies = + e_account_list_account_has_proxies (account_list, account); + + response = e_error_run ( + parent, has_proxies ? + "mail:ask-delete-account-with-proxies" : + "mail:ask-delete-account", NULL); + + if (response != GTK_RESPONSE_YES) { + g_signal_stop_emission_by_name (manager, "delete-account"); + return; + } + + /* Remove the account from the folder tree. */ + if (account->enabled && account->source && account->source->url) + e_mail_store_remove_by_uri (account->source->url); + + /* Remove all the proxies the account has created. */ + if (has_proxies) + e_account_list_remove_account_proxies (account_list, account); + + /* Remove it from the config file. */ + e_account_list_remove (account_list, account); + + e_account_list_save (account_list); +} + +static void +account_prefs_dispose (GObject *object) +{ + EMAccountPrefsPrivate *priv; + + priv = EM_ACCOUNT_PREFS_GET_PRIVATE (object); + + if (priv->druid != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->druid), &priv->druid); + priv->druid = NULL; + } + + if (priv->editor != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->editor), &priv->editor); + priv->editor = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +account_prefs_class_init (EMAccountPrefsClass *class) +{ + GObjectClass *object_class; + EAccountManagerClass *account_manager_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMAccountPrefsPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->dispose = account_prefs_dispose; + + account_manager_class = E_ACCOUNT_MANAGER_CLASS (class); + account_manager_class->add_account = account_prefs_add_account; + account_manager_class->edit_account = account_prefs_edit_account; + account_manager_class->delete_account = account_prefs_delete_account; +} + +static void +account_prefs_init (EMAccountPrefs *prefs) +{ + EAccountManager *manager; + EAccountTreeView *tree_view; + + prefs->priv = EM_ACCOUNT_PREFS_GET_PRIVATE (prefs); + + manager = E_ACCOUNT_MANAGER (prefs); + tree_view = e_account_manager_get_tree_view (manager); + + g_signal_connect ( + tree_view, "enable-account", + G_CALLBACK (account_prefs_enable_account_cb), NULL); + + g_signal_connect ( + tree_view, "disable-account", + G_CALLBACK (account_prefs_disable_account_cb), NULL); +} + +GType +em_account_prefs_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMAccountPrefsClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) account_prefs_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMAccountPrefs), + 0, /* n_preallocs */ + (GInstanceInitFunc) account_prefs_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + E_TYPE_ACCOUNT_MANAGER, "EMAccountPrefs", + &type_info, 0); + } + + return type; +} + +GtkWidget * +em_account_prefs_new (EAccountList *account_list) +{ + g_return_val_if_fail (E_IS_ACCOUNT_LIST (account_list), NULL); + + return g_object_new ( + EM_TYPE_ACCOUNT_PREFS, "account-list", account_list, NULL); +} diff --git a/modules/mail/em-account-prefs.h b/modules/mail/em-account-prefs.h new file mode 100644 index 0000000000..82df8fa941 --- /dev/null +++ b/modules/mail/em-account-prefs.h @@ -0,0 +1,69 @@ +/* + * em-account-prefs.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef EM_ACCOUNT_PREFS_H +#define EM_ACCOUNT_PREFS_H + +#include +#include
+#include +#include + +/* Standard GObject macros */ +#define EM_TYPE_ACCOUNT_PREFS \ + (em_account_prefs_get_type ()) +#define EM_ACCOUNT_PREFS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EM_TYPE_ACCOUNT_PREFS, EMAccountPrefs)) +#define EM_ACCOUNT_PREFS_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EM_TYPE_ACCOUNT_PREFS, EMAccountPrefsClass)) +#define EM_IS_ACCOUNT_PREFS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EM_TYPE_ACCOUNT_PREFS)) +#define EM_IS_ACCOUNT_PREFS_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EM_TYPE_ACCOUNT_PREFS)) +#define EM_ACCOUNT_PREFS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), EM_TYPE_ACCOUNT_PREFS, EMAccountPrefsClass)) + +G_BEGIN_DECLS + +typedef struct _EMAccountPrefs EMAccountPrefs; +typedef struct _EMAccountPrefsClass EMAccountPrefsClass; +typedef struct _EMAccountPrefsPrivate EMAccountPrefsPrivate; + +struct _EMAccountPrefs { + EAccountManager parent; + EMAccountPrefsPrivate *priv; +}; + +struct _EMAccountPrefsClass { + EAccountManagerClass parent_class; +}; + +GType em_account_prefs_get_type (void); +GtkWidget * em_account_prefs_new (EAccountList *account_list); + +G_END_DECLS + +#endif /* EM_ACCOUNT_PREFS_H */ diff --git a/modules/mail/em-composer-prefs.c b/modules/mail/em-composer-prefs.c new file mode 100644 index 0000000000..18dae567ca --- /dev/null +++ b/modules/mail/em-composer-prefs.c @@ -0,0 +1,621 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Jeffrey Stedfast + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "e-util/e-binding.h" +#include "e-util/e-signature-utils.h" +#include "e-util/gconf-bridge.h" + +#include "em-composer-prefs.h" +#include "composer/e-msg-composer.h" + +#include + +#include + +#include +#include + +#include +#include + +#include "misc/e-charset-picker.h" +#include "misc/e-signature-editor.h" +#include "misc/e-signature-manager.h" +#include "misc/e-signature-preview.h" +#include "e-util/e-error.h" +#include "e-util/e-util-private.h" + +#include "mail-config.h" +#include "em-config.h" + +static gpointer parent_class; + +static gboolean +transform_color_to_string (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + const GdkColor *color; + gchar *string; + + color = g_value_get_boxed (src_value); + string = gdk_color_to_string (color); + g_value_set_string (dst_value, string); + g_free (string); + + return TRUE; +} + +static gboolean +transform_string_to_color (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + GdkColor color; + const gchar *string; + gboolean success = FALSE; + + string = g_value_get_string (src_value); + if (gdk_color_parse (string, &color)) { + g_value_set_boxed (dst_value, &color); + success = TRUE; + } + + return success; +} + +static gboolean +transform_old_to_new_reply_style (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + gboolean success = TRUE; + + /* XXX This is the kind of legacy crap we wind up + * with when we don't migrate things properly. */ + + switch (g_value_get_int (src_value)) { + case 0: /* Quoted: 0 -> 2 */ + g_value_set_int (dst_value, 2); + break; + + case 1: /* Do Not Quote: 1 -> 3 */ + g_value_set_int (dst_value, 3); + break; + + case 2: /* Attach: 2 -> 0 */ + g_value_set_int (dst_value, 0); + break; + + case 3: /* Outlook: 3 -> 1 */ + g_value_set_int (dst_value, 1); + break; + + default: + success = FALSE; + break; + } + + return success; +} + +static gboolean +transform_new_to_old_reply_style (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + gboolean success = TRUE; + + /* XXX This is the kind of legacy crap we wind up + * with when we don't migrate things properly. */ + + switch (g_value_get_int (src_value)) { + case 0: /* Attach: 0 -> 2 */ + g_value_set_int (dst_value, 2); + break; + + case 1: /* Outlook: 1 -> 3 */ + g_value_set_int (dst_value, 3); + break; + + case 2: /* Quoted: 2 -> 0 */ + g_value_set_int (dst_value, 0); + break; + + case 3: /* Do Not Quote: 3 -> 1 */ + g_value_set_int (dst_value, 1); + break; + + default: + success = FALSE; + break; + } + + return success; +} + +static void +composer_prefs_finalize (GObject *object) +{ + EMComposerPrefs *prefs = (EMComposerPrefs *) object; + + g_object_unref (prefs->gui); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +composer_prefs_class_init (EMComposerPrefsClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + + object_class = G_OBJECT_CLASS (class); + object_class->finalize = composer_prefs_finalize; +} + +static void +composer_prefs_init (EMComposerPrefs *prefs) +{ +} + +GType +em_composer_prefs_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMComposerPrefsClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) composer_prefs_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMComposerPrefs), + 0, /* n_allocs */ + (GInstanceInitFunc) composer_prefs_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_VBOX, "EMComposerPrefs", &type_info, 0); + } + + return type; +} + +void +em_composer_prefs_new_signature (GtkWindow *parent, + gboolean html_mode) +{ + GtkWidget *editor; + + editor = e_signature_editor_new (); + gtkhtml_editor_set_html_mode (GTKHTML_EDITOR (editor), html_mode); + gtk_window_set_transient_for (GTK_WINDOW (editor), parent); + gtk_widget_show (editor); +} + +static void +spell_language_toggled_cb (GtkCellRendererToggle *renderer, + const gchar *path_string, + EMComposerPrefs *prefs) +{ + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; + gboolean active; + gboolean valid; + + model = prefs->language_model; + + /* Convert the path string to a tree iterator. */ + path = gtk_tree_path_new_from_string (path_string); + valid = gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_path_free (path); + g_return_if_fail (valid); + + /* Toggle the active state. */ + gtk_tree_model_get (model, &iter, 0, &active, -1); + gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, !active, -1); +} + +static void +spell_language_save (EMComposerPrefs *prefs) +{ + GList *spell_languages = NULL; + GtkTreeModel *model; + GtkTreeIter iter; + gboolean valid; + + model = prefs->language_model; + + /* Build a list of active spell languages. */ + valid = gtk_tree_model_get_iter_first (model, &iter); + while (valid) { + const GtkhtmlSpellLanguage *language; + gboolean active; + + gtk_tree_model_get ( + model, &iter, 0, &active, 2, &language, -1); + + if (active) + spell_languages = g_list_prepend ( + spell_languages, (gpointer) language); + + valid = gtk_tree_model_iter_next (model, &iter); + } + spell_languages = g_list_reverse (spell_languages); + + /* Update the GConf value. */ + e_save_spell_languages (spell_languages); + + g_list_free (spell_languages); +} + +static void +spell_setup (EMComposerPrefs *prefs) +{ + const GList *available_languages; + GList *active_languages; + GtkListStore *store; + + store = GTK_LIST_STORE (prefs->language_model); + available_languages = gtkhtml_spell_language_get_available (); + + active_languages = e_load_spell_languages (); + + /* Populate the GtkListStore. */ + while (available_languages != NULL) { + const GtkhtmlSpellLanguage *language; + GtkTreeIter tree_iter; + const gchar *name; + gboolean active; + + language = available_languages->data; + name = gtkhtml_spell_language_get_name (language); + active = (g_list_find (active_languages, language) != NULL); + + gtk_list_store_append (store, &tree_iter); + + gtk_list_store_set ( + store, &tree_iter, + 0, active, 1, name, 2, language, -1); + + available_languages = available_languages->next; + } + + g_list_free (active_languages); +} + +static void +charset_activate (GtkWidget *item, + EMComposerPrefs *prefs) +{ + GConfClient *client; + GtkWidget *menu; + gchar *string; + + client = mail_config_get_gconf_client (); + menu = gtk_option_menu_get_menu (prefs->charset); + string = e_charset_picker_get_charset (menu); + + if (string == NULL) + string = g_strdup (camel_iconv_locale_charset ()); + + gconf_client_set_string ( + client, "/apps/evolution/mail/composer/charset", + string, NULL); + + g_free (string); +} + +static void +option_menu_connect (EMComposerPrefs *prefs, + GtkOptionMenu *omenu, + GCallback callback, + const gchar *key) +{ + GConfClient *client; + GtkWidget *menu; + GList *list; + + client = mail_config_get_gconf_client (); + menu = gtk_option_menu_get_menu (omenu); + list = GTK_MENU_SHELL (menu)->children; + + while (list != NULL) { + GtkWidget *widget = list->data; + + g_object_set_data (G_OBJECT (widget), "key", (gpointer) key); + g_signal_connect (widget, "activate", callback, prefs); + list = list->next; + } + + if (!gconf_client_key_is_writable (client, key, NULL)) + gtk_widget_set_sensitive (GTK_WIDGET (omenu), FALSE); +} + +static GtkWidget * +emcp_widget_glade (EConfig *ec, + EConfigItem *item, + GtkWidget *parent, + GtkWidget *old, + gpointer data) +{ + EMComposerPrefs *prefs = data; + + return glade_xml_get_widget (prefs->gui, item->label); +} + +/* plugin meta-data */ +static EMConfigItem emcp_items[] = { + { E_CONFIG_BOOK, (gchar *) "", (gchar *) "composer_toplevel", emcp_widget_glade }, + { E_CONFIG_PAGE, (gchar *) "00.general", (gchar *) "vboxGeneral", emcp_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "00.general/00.behavior", (gchar *) "vboxBehavior", emcp_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "00.general/10.alerts", (gchar *) "vboxAlerts", emcp_widget_glade }, + { E_CONFIG_PAGE, (gchar *) "10.signatures", (gchar *) "vboxSignatures", emcp_widget_glade }, + /* signature/signatures and signature/preview parts not usable */ + + { E_CONFIG_PAGE, (gchar *) "20.spellcheck", (gchar *) "vboxSpellChecking", emcp_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "20.spellcheck/00.languages", (gchar *) "vbox178", emcp_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "20.spellcheck/00.options", (gchar *) "vboxOptions", emcp_widget_glade }, +}; + +static void +emcp_free (EConfig *ec, GSList *items, gpointer data) +{ + /* the prefs data is freed automagically */ + g_slist_free (items); +} + +static void +em_composer_prefs_construct (EMComposerPrefs *prefs, + EShell *shell) +{ + GtkWidget *toplevel, *widget, *menu, *info_pixmap; + GtkWidget *container; + EShellSettings *shell_settings; + ESignatureList *signature_list; + ESignatureTreeView *signature_tree_view; + GladeXML *gui; + GtkTreeView *view; + GtkListStore *store; + GtkTreeSelection *selection; + GtkCellRenderer *renderer; + GConfBridge *bridge; + GConfClient *client; + gchar *buf; + EMConfig *ec; + EMConfigTargetPrefs *target; + GSList *l; + gint i; + gchar *gladefile; + + bridge = gconf_bridge_get (); + client = mail_config_get_gconf_client (); + shell_settings = e_shell_get_shell_settings (shell); + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + "mail-config.glade", + NULL); + gui = glade_xml_new (gladefile, "composer_toplevel", NULL); + prefs->gui = gui; + g_free (gladefile); + + /** @HookPoint-EMConfig: Mail Composer Preferences + * @Id: org.gnome.evolution.mail.composerPrefs + * @Type: E_CONFIG_BOOK + * @Class: org.gnome.evolution.mail.config:1.0 + * @Target: EMConfigTargetPrefs + * + * The mail composer preferences settings page. + */ + ec = em_config_new(E_CONFIG_BOOK, "org.gnome.evolution.mail.composerPrefs"); + l = NULL; + for (i = 0; i < G_N_ELEMENTS (emcp_items); i++) + l = g_slist_prepend(l, &emcp_items[i]); + e_config_add_items((EConfig *)ec, l, NULL, NULL, emcp_free, prefs); + + /* General tab */ + + /* Default Behavior */ + widget = glade_xml_get_widget (gui, "chkSendHTML"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "composer-format-html", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "chkPromptEmptySubject"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "composer-prompt-empty-subject", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "chkPromptBccOnly"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "composer-prompt-only-bcc", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "chkAutoSmileys"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "composer-magic-smileys", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "chkRequestReceipt"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "composer-request-receipt", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "chkReplyStartBottom"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "composer-reply-start-bottom", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "chkOutlookFilenames"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "composer-outlook-filenames", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "chkTopSignature"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "composer-top-signature", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "chkEnableSpellChecking"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "composer-inline-spelling", + G_OBJECT (widget), "active"); + + prefs->charset = GTK_OPTION_MENU ( + glade_xml_get_widget (gui, "omenuCharset1")); + buf = gconf_client_get_string ( + client, "/apps/evolution/mail/composer/charset", NULL); + menu = e_charset_picker_new ( + buf && *buf ? buf : camel_iconv_locale_charset ()); + gtk_option_menu_set_menu (prefs->charset, GTK_WIDGET (menu)); + option_menu_connect ( + prefs, prefs->charset, + G_CALLBACK (charset_activate), + "/apps/evolution/mail/composer/charset"); + g_free (buf); + + /* Spell Checking */ + widget = glade_xml_get_widget (gui, "listSpellCheckLanguage"); + view = GTK_TREE_VIEW (widget); + store = gtk_list_store_new ( + 3, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_POINTER); + g_signal_connect_swapped ( + store, "row-changed", + G_CALLBACK (spell_language_save), prefs); + prefs->language_model = GTK_TREE_MODEL (store); + gtk_tree_view_set_model (view, prefs->language_model); + renderer = gtk_cell_renderer_toggle_new (); + g_signal_connect ( + renderer, "toggled", + G_CALLBACK (spell_language_toggled_cb), prefs); + gtk_tree_view_insert_column_with_attributes ( + view, -1, _("Enabled"), + renderer, "active", 0, NULL); + + gtk_tree_view_insert_column_with_attributes ( + view, -1, _("Language(s)"), + gtk_cell_renderer_text_new (), + "text", 1, NULL); + selection = gtk_tree_view_get_selection (view); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE); + info_pixmap = glade_xml_get_widget (gui, "pixmapSpellInfo"); + gtk_image_set_from_stock ( + GTK_IMAGE (info_pixmap), + GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_BUTTON); + + widget = glade_xml_get_widget (gui, "colorButtonSpellCheckColor"); + e_mutual_binding_new_full ( + G_OBJECT (shell_settings), "composer-spell-color", + G_OBJECT (widget), "color", + transform_string_to_color, + transform_color_to_string, + NULL, NULL); + + spell_setup (prefs); + + /* Forwards and Replies */ + widget = glade_xml_get_widget (gui, "comboboxForwardStyle"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-forward-style", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "comboboxReplyStyle"); + e_mutual_binding_new_full ( + G_OBJECT (shell_settings), "mail-reply-style", + G_OBJECT (widget), "active", + transform_old_to_new_reply_style, + transform_new_to_old_reply_style, + NULL, NULL); + + /* Signatures */ + signature_list = e_get_signature_list (); + container = glade_xml_get_widget (gui, "alignSignatures"); + widget = e_signature_manager_new (signature_list); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + /* The mail shell backend responds to the "window-created" signal + * that this triggers and configures it with composer preferences. */ + g_signal_connect_swapped ( + widget, "editor-created", + G_CALLBACK (e_shell_watch_window), shell); + + e_binding_new ( + G_OBJECT (shell_settings), "composer-format-html", + G_OBJECT (widget), "prefer-html"); + + e_binding_new_with_negation ( + G_OBJECT (shell_settings), "disable-command-line", + G_OBJECT (widget), "allow-scripts"); + + signature_tree_view = e_signature_manager_get_tree_view ( + E_SIGNATURE_MANAGER (widget)); + + container = glade_xml_get_widget (gui, "scrolled-sig"); + widget = e_signature_preview_new (); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + e_binding_new_with_negation ( + G_OBJECT (shell_settings), "disable-command-line", + G_OBJECT (widget), "allow-scripts"); + + e_binding_new ( + G_OBJECT (signature_tree_view), "selected", + G_OBJECT (widget), "signature"); + + /* get our toplevel widget */ + target = em_config_target_new_prefs (ec, client); + e_config_set_target ((EConfig *)ec, (EConfigTarget *)target); + toplevel = e_config_create_widget ((EConfig *)ec); + gtk_container_add (GTK_CONTAINER (prefs), toplevel); +} + +GtkWidget * +em_composer_prefs_new (EShell *shell) +{ + EMComposerPrefs *prefs; + + g_return_val_if_fail (E_IS_SHELL (shell), NULL); + + prefs = g_object_new (EM_TYPE_COMPOSER_PREFS, NULL); + em_composer_prefs_construct (prefs, shell); + + return GTK_WIDGET (prefs); +} diff --git a/modules/mail/em-composer-prefs.h b/modules/mail/em-composer-prefs.h new file mode 100644 index 0000000000..3b848f1a2f --- /dev/null +++ b/modules/mail/em-composer-prefs.h @@ -0,0 +1,93 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Jeffrey Stedfast + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef EM_COMPOSER_PREFS_H +#define EM_COMPOSER_PREFS_H + +#include +#include +#include + +#include + +/* Standard GObject macros */ +#define EM_TYPE_COMPOSER_PREFS \ + (em_composer_prefs_get_type ()) +#define EM_COMPOSER_PREFS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EM_TYPE_COMPOSER_PREFS, EMComposerPrefs)) +#define EM_COMPOSER_PREFS_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EM_TYPE_COMPOSER_PREFS, EMComposerPrefsClass)) +#define EM_IS_COMPOSER_PREFS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EM_TYPE_COMPOSER_PREFS)) +#define EM_IS_COMPOSER_PREFS_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EM_TYPE_COMPOSER_PREFS)) +#define EM_COMPOSER_PREFS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), EM_TYPE_COMPOSER_PREFS, EMComposerPrefsClass)) + +G_BEGIN_DECLS + +typedef struct _EMComposerPrefs EMComposerPrefs; +typedef struct _EMComposerPrefsClass EMComposerPrefsClass; + +struct _ESignature; + +struct _EMComposerPrefs { + GtkVBox parent; + + GladeXML *gui; + + /* General tab */ + + /* Default Behavior */ + GtkOptionMenu *charset; + + GtkTreeModel *language_model; + + /* Forwards and Replies */ + GtkComboBox *forward_style; + GtkComboBox *reply_style; + + /* Signatures */ + GtkHTML *sig_preview; +}; + +struct _EMComposerPrefsClass { + GtkVBoxClass parent_class; +}; + +GType em_composer_prefs_get_type (void); +GtkWidget * em_composer_prefs_new (EShell *shell); +void em_composer_prefs_new_signature (GtkWindow *parent, + gboolean html_mode); + +/* needed by global config */ +#define EM_COMPOSER_PREFS_CONTROL_ID \ + "OAFIID:GNOME_Evolution_Mail_ComposerPrefs_ConfigControl:" BASE_VERSION + +G_END_DECLS + +#endif /* EM_COMPOSER_PREFS_H */ diff --git a/modules/mail/em-mailer-prefs.c b/modules/mail/em-mailer-prefs.c new file mode 100644 index 0000000000..fa450dc2ee --- /dev/null +++ b/modules/mail/em-mailer-prefs.c @@ -0,0 +1,1332 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Jeffrey Stedfast + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "em-mailer-prefs.h" +#include "em-format/em-format.h" + +#include +#include +#include +#include "misc/e-charset-picker.h" + +#include + +#include + +#include "libedataserverui/e-cell-renderer-color.h" + +#include "e-util/e-binding.h" +#include "e-util/e-util-private.h" + +#include "e-mail-label-manager.h" +#include "mail-config.h" +#include "em-junk-hook.h" +#include "em-config.h" +#include "mail-session.h" + +static void em_mailer_prefs_class_init (EMMailerPrefsClass *class); +static void em_mailer_prefs_init (EMMailerPrefs *dialog); +static void em_mailer_prefs_finalize (GObject *object); + +static GtkVBoxClass *parent_class = NULL; + +enum { + HEADER_LIST_NAME_COLUMN, /* displayable name of the header (may be a translation) */ + HEADER_LIST_ENABLED_COLUMN, /* is the header enabled? */ + HEADER_LIST_IS_DEFAULT_COLUMN, /* is this header a default header, eg From: */ + HEADER_LIST_HEADER_COLUMN, /* the real name of this header */ + HEADER_LIST_N_COLUMNS +}; + +static GType col_types[] = { + G_TYPE_STRING, + G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN, + G_TYPE_STRING +}; + +/* temporarily copied from em-format.c */ +static const gchar *default_headers[] = { + N_("From"), + N_("Reply-To"), + N_("To"), + N_("Cc"), + N_("Bcc"), + N_("Subject"), + N_("Date"), + N_("Newsgroups"), + N_("Face"), + "x-evolution-mailer", /* DO NOT translate */ +}; + +#define EM_FORMAT_HEADER_XMAILER "x-evolution-mailer" + +/* for empty trash on exit frequency */ +static const struct { + const gchar *label; + gint days; +} empty_trash_frequency[] = { + { N_("Every time"), 0 }, + { N_("Once per day"), 1 }, + { N_("Once per week"), 7 }, + { N_("Once per month"), 30 }, +}; + +GType +em_mailer_prefs_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo type_info = { + sizeof (EMMailerPrefsClass), + NULL, NULL, + (GClassInitFunc) em_mailer_prefs_class_init, + NULL, NULL, + sizeof (EMMailerPrefs), + 0, + (GInstanceInitFunc) em_mailer_prefs_init, + }; + + type = g_type_register_static (gtk_vbox_get_type (), "EMMailerPrefs", &type_info, 0); + } + + return type; +} + +static void +em_mailer_prefs_class_init (EMMailerPrefsClass *klass) +{ + GObjectClass *object_class; + + object_class = (GObjectClass *) klass; + parent_class = g_type_class_ref (gtk_vbox_get_type ()); + + object_class->finalize = em_mailer_prefs_finalize; +} + +static void +em_mailer_prefs_init (EMMailerPrefs *preferences) +{ + preferences->gconf = mail_config_get_gconf_client (); +} + +static void +em_mailer_prefs_finalize (GObject *obj) +{ + EMMailerPrefs *prefs = (EMMailerPrefs *) obj; + + g_object_unref (prefs->gui); + + if (prefs->labels_change_notify_id) { + gconf_client_notify_remove (prefs->gconf, prefs->labels_change_notify_id); + + prefs->labels_change_notify_id = 0; + } + + ((GObjectClass *)(parent_class))->finalize (obj); +} + +static gboolean +mark_seen_timeout_transform (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + gdouble v_double; + + /* Shell Settings (gint) -> Spin Button (double) */ + v_double = (gdouble) g_value_get_int (src_value); + g_value_set_double (dst_value, v_double / 1000.0); + + return TRUE; +} + +static gboolean +mark_seen_timeout_reverse_transform (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + gdouble v_double; + + /* Spin Button (double) -> Shell Settings (gint) */ + v_double = g_value_get_double (src_value); + g_value_set_int (dst_value, v_double * 1000); + + return TRUE; +} + +enum { + JH_LIST_COLUMN_NAME, + JH_LIST_COLUMN_VALUE +}; + +static void +jh_tree_refill (EMMailerPrefs *prefs) +{ + GtkListStore *store = prefs->junk_header_list_store; + GSList *l, *cjh = gconf_client_get_list (prefs->gconf, "/apps/evolution/mail/junk/custom_header", GCONF_VALUE_STRING, NULL); + + gtk_list_store_clear (store); + + for (l = cjh; l; l = l->next) { + GtkTreeIter iter; + gchar **tokens = g_strsplit (l->data, "=", 2); + + gtk_list_store_append (store, &iter); + gtk_list_store_set ( + store, &iter, + JH_LIST_COLUMN_NAME , tokens[0] ? tokens[0] : "", + JH_LIST_COLUMN_VALUE, tokens[1] ? tokens[1] : "" , + -1); + g_strfreev (tokens); + } + + g_slist_foreach (cjh, (GFunc) g_free, NULL); + g_slist_free (cjh); +} + +static void +jh_add_cb (GtkWidget *widget, gpointer user_data) +{ + EMMailerPrefs *prefs = (EMMailerPrefs *) user_data; + GtkWidget *dialog, *l1, *l2, *entry1, *entry2, *vbox, *hbox; + gint response; + dialog = gtk_dialog_new_with_buttons (_("Add Custom Junk Header"), (GtkWindow *)gtk_widget_get_toplevel (widget), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); + + vbox = gtk_vbox_new (FALSE, 6); + hbox = gtk_hbox_new (FALSE, 0); + l1 = gtk_label_new_with_mnemonic (_("Header Name:")); + l2 = gtk_label_new_with_mnemonic (_("Header Value Contains:")); + entry1 = gtk_entry_new (); + entry2 = gtk_entry_new (); + gtk_box_pack_start ((GtkBox *) hbox, l1, FALSE, FALSE, 6); + gtk_box_pack_start ((GtkBox *)hbox, entry1, FALSE, FALSE, 6); + gtk_box_pack_start ((GtkBox *)vbox, hbox, FALSE, FALSE, 6); + + hbox = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start ((GtkBox *)hbox, l2, FALSE, FALSE, 6); + gtk_box_pack_start ((GtkBox *)hbox, entry2, FALSE, FALSE, 6); + gtk_box_pack_start ((GtkBox *)vbox, hbox, FALSE, FALSE, 6); + + gtk_widget_show_all (vbox); + gtk_container_add ((GtkContainer *)((GtkDialog *)dialog)->vbox, vbox); + response = gtk_dialog_run ((GtkDialog *)dialog); + if (response == GTK_RESPONSE_ACCEPT) { + const gchar *name = gtk_entry_get_text ((GtkEntry *)entry1); + const gchar *value = gtk_entry_get_text ((GtkEntry *)entry2); + gchar *tok; + GSList *list = gconf_client_get_list (prefs->gconf, "/apps/evolution/mail/junk/custom_header", GCONF_VALUE_STRING, NULL); + + /* FIXME: Validate the values */ + + tok = g_strdup_printf ("%s=%s", name, value); + list = g_slist_append (list, tok); + gconf_client_set_list (prefs->gconf, "/apps/evolution/mail/junk/custom_header", GCONF_VALUE_STRING, list, NULL); + g_slist_foreach (list, (GFunc)g_free, NULL); + + g_slist_free (list); + } + gtk_widget_destroy (dialog); + jh_tree_refill (prefs); +} + +static void +jh_remove_cb (GtkWidget *widget, gpointer user_data) +{ + EMMailerPrefs *prefs = user_data; + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + + g_return_if_fail (prefs != NULL); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->junk_header_tree)); + if (gtk_tree_selection_get_selected (selection, &model, &iter)) { + gchar *name=NULL, *value=NULL; + GSList *prev = NULL, *node, *list = gconf_client_get_list (prefs->gconf, "/apps/evolution/mail/junk/custom_header", GCONF_VALUE_STRING, NULL); + gtk_tree_model_get (model, &iter, JH_LIST_COLUMN_NAME, &name, JH_LIST_COLUMN_VALUE, &value, -1); + node = list; + while (node) { + gchar *test; + gint len = strlen (name); + test = strncmp (node->data, name, len) == 0 ? (gchar *) node->data+len:NULL; + + if (test) { + test++; + if (strcmp (test, value) == 0) + break; + } + + prev = node; + node = node->next; + } + + if (prev && !node) { + /* Not found. So what? */ + } else if (prev && node) { + prev->next = node->next; + g_free (node->data); + } else if (!prev && node) { + list = list->next; + g_free (node->data); + } + + gconf_client_set_list (prefs->gconf, "/apps/evolution/mail/junk/custom_header", GCONF_VALUE_STRING, list, NULL); + + g_slist_foreach (list, (GFunc)g_free, NULL); + g_slist_free (list); + g_free (name); + g_free (value); + + jh_tree_refill (prefs); + } +} + + +static GtkListStore * +init_junk_tree (GtkWidget *label_tree, EMMailerPrefs *prefs) +{ + GtkListStore *store; + GtkCellRenderer *renderer; + gint col; + + g_return_val_if_fail (label_tree != NULL, NULL); + g_return_val_if_fail (prefs != NULL, NULL); + + store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); + gtk_tree_view_set_model (GTK_TREE_VIEW (label_tree), GTK_TREE_MODEL (store)); + + renderer = gtk_cell_renderer_text_new (); + col = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (label_tree), -1, _("Header"), renderer, "text", JH_LIST_COLUMN_NAME, NULL); + g_object_set (G_OBJECT (renderer), "editable", TRUE, NULL); + + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (label_tree), -1, _("Contains Value"), renderer, "text", JH_LIST_COLUMN_VALUE, NULL); + g_object_set (G_OBJECT (renderer), "editable", TRUE, NULL); + + return store; +} + +static void +emmp_header_remove_sensitivity (EMMailerPrefs *prefs) +{ + GtkTreeIter iter; + GtkTreeSelection *selection = gtk_tree_view_get_selection (prefs->header_list); + gboolean is_default; + + /* remove button should be sensitive if the currenlty selected entry in the list view + is not a default header. if there are no entries, or none is selected, it should be + disabled + */ + if (gtk_tree_selection_get_selected (selection, NULL, &iter)) { + gtk_tree_model_get (GTK_TREE_MODEL (prefs->header_list_store), &iter, + HEADER_LIST_IS_DEFAULT_COLUMN, &is_default, + -1); + if (is_default) + gtk_widget_set_sensitive (GTK_WIDGET (prefs->remove_header), FALSE); + else + gtk_widget_set_sensitive (GTK_WIDGET (prefs->remove_header), TRUE); + } else { + gtk_widget_set_sensitive (GTK_WIDGET (prefs->remove_header), FALSE); + } +} + +static gboolean +emmp_header_is_valid (const gchar *header) +{ + gint len = g_utf8_strlen (header, -1); + + if (header[0] == 0 + || g_utf8_strchr (header, len, ':') != NULL + || g_utf8_strchr (header, len, ' ') != NULL) + return FALSE; + + return TRUE; +} + +static void +emmp_header_add_sensitivity (EMMailerPrefs *prefs) +{ + const gchar *entry_contents; + GtkTreeIter iter; + gboolean valid; + + /* the add header button should be sensitive if the text box contains + a valid header string, that is not a duplicate with something already + in the list view + */ + entry_contents = gtk_entry_get_text (GTK_ENTRY (prefs->entry_header)); + if (!emmp_header_is_valid (entry_contents)) { + gtk_widget_set_sensitive (GTK_WIDGET (prefs->add_header), FALSE); + return; + } + + /* check if this is a duplicate */ + valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (prefs->header_list_store), &iter); + while (valid) { + gchar *header_name; + + gtk_tree_model_get (GTK_TREE_MODEL (prefs->header_list_store), &iter, + HEADER_LIST_HEADER_COLUMN, &header_name, + -1); + if (g_ascii_strcasecmp (header_name, entry_contents) == 0) { + gtk_widget_set_sensitive (GTK_WIDGET (prefs->add_header), FALSE); + return; + } + + valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (prefs->header_list_store), &iter); + } + + gtk_widget_set_sensitive (GTK_WIDGET (prefs->add_header), TRUE); +} + +static void +emmp_save_headers (EMMailerPrefs *prefs) +{ + GSList *header_list; + GtkTreeIter iter; + gboolean valid; + + /* Headers */ + header_list = NULL; + valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (prefs->header_list_store), &iter); + while (valid) { + struct _EMMailerPrefsHeader h; + gboolean enabled; + gchar *xml; + + gtk_tree_model_get (GTK_TREE_MODEL (prefs->header_list_store), &iter, + HEADER_LIST_HEADER_COLUMN, &h.name, + HEADER_LIST_ENABLED_COLUMN, &enabled, + -1); + h.enabled = enabled; + + if ((xml = em_mailer_prefs_header_to_xml (&h))) + header_list = g_slist_append (header_list, xml); + + valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (prefs->header_list_store), &iter); + } + + gconf_client_set_list (prefs->gconf, "/apps/evolution/mail/display/headers", GCONF_VALUE_STRING, header_list, NULL); + g_slist_foreach (header_list, (GFunc) g_free, NULL); + g_slist_free (header_list); +} + +static void +emmp_header_list_enabled_toggled (GtkCellRendererToggle *cell, const gchar *path_string, EMMailerPrefs *prefs) +{ + GtkTreeModel *model = GTK_TREE_MODEL (prefs->header_list_store); + GtkTreePath *path = gtk_tree_path_new_from_string (path_string); + GtkTreeIter iter; + gint enabled; + + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, HEADER_LIST_ENABLED_COLUMN, &enabled, -1); + enabled = !enabled; + gtk_list_store_set (GTK_LIST_STORE (model), &iter, HEADER_LIST_ENABLED_COLUMN, + enabled, -1); + gtk_tree_path_free (path); + + emmp_save_headers (prefs); +} + +static void +emmp_header_add_header (GtkWidget *widget, EMMailerPrefs *prefs) +{ + GtkTreeModel *model = GTK_TREE_MODEL (prefs->header_list_store); + GtkTreeIter iter; + const gchar *text = gtk_entry_get_text (prefs->entry_header); + + g_strstrip ((gchar *)text); + + if (text && (strlen (text)>0)) { + gtk_list_store_append (GTK_LIST_STORE (model), &iter); + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + HEADER_LIST_NAME_COLUMN, text, + HEADER_LIST_ENABLED_COLUMN, TRUE, + HEADER_LIST_HEADER_COLUMN, text, + HEADER_LIST_IS_DEFAULT_COLUMN, FALSE, + -1); + gtk_entry_set_text (prefs->entry_header, ""); + emmp_header_remove_sensitivity (prefs); + emmp_header_add_sensitivity (prefs); + + emmp_save_headers (prefs); + } +} + +static void +emmp_header_remove_header (GtkWidget *button, gpointer user_data) +{ + EMMailerPrefs *prefs = (EMMailerPrefs *) user_data; + GtkTreeModel *model = GTK_TREE_MODEL (prefs->header_list_store); + GtkTreeSelection *selection = gtk_tree_view_get_selection (prefs->header_list); + GtkTreeIter iter; + + if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) + return; + + gtk_list_store_remove (GTK_LIST_STORE (model), &iter); + emmp_header_remove_sensitivity (prefs); + + emmp_save_headers (prefs); +} + +static void +emmp_header_list_row_selected (GtkTreeSelection *selection, gpointer user_data) +{ + EMMailerPrefs *prefs = (EMMailerPrefs *) user_data; + + emmp_header_remove_sensitivity (prefs); +} + +static void +emmp_header_entry_changed (GtkWidget *entry, gpointer user_data) +{ + EMMailerPrefs *prefs = (EMMailerPrefs *) user_data; + + emmp_header_add_sensitivity (prefs); +} + +static void +toggle_button_toggled (GtkToggleButton *toggle, EMMailerPrefs *prefs) +{ + const gchar *key; + + key = g_object_get_data ((GObject *) toggle, "key"); + gconf_client_set_bool (prefs->gconf, key, gtk_toggle_button_get_active (toggle), NULL); +} + +static void +junk_book_lookup_button_toggled (GtkToggleButton *toggle, EMMailerPrefs *prefs) +{ + toggle_button_toggled (toggle, prefs); + gtk_widget_set_sensitive (GTK_WIDGET (prefs->junk_lookup_local_only), gtk_toggle_button_get_active (toggle)); +} + +static void +custom_junk_button_toggled (GtkToggleButton *toggle, EMMailerPrefs *prefs) +{ + toggle_button_toggled (toggle, prefs); + if (gtk_toggle_button_get_active (toggle)) { + gtk_widget_set_sensitive ((GtkWidget *) prefs->junk_header_remove, TRUE); + gtk_widget_set_sensitive ((GtkWidget *) prefs->junk_header_add, TRUE); + gtk_widget_set_sensitive ((GtkWidget *) prefs->junk_header_tree, TRUE); + } else { + gtk_widget_set_sensitive ((GtkWidget *) prefs->junk_header_tree, FALSE); + gtk_widget_set_sensitive ((GtkWidget *) prefs->junk_header_add, FALSE); + gtk_widget_set_sensitive ((GtkWidget *) prefs->junk_header_remove, FALSE); + } + + +} + +static void +toggle_button_init (EMMailerPrefs *prefs, GtkToggleButton *toggle, gint not, const gchar *key, GCallback toggled) +{ + gboolean bool; + + bool = gconf_client_get_bool (prefs->gconf, key, NULL); + gtk_toggle_button_set_active (toggle, not ? !bool : bool); + + if (toggled) { + g_object_set_data ((GObject *) toggle, "key", (gpointer) key); + g_signal_connect (toggle, "toggled", toggled, prefs); + } + + if (!gconf_client_key_is_writable (prefs->gconf, key, NULL)) + gtk_widget_set_sensitive ((GtkWidget *) toggle, FALSE); +} + +static void +charset_activate (GtkWidget *item, EMMailerPrefs *prefs) +{ + GtkWidget *menu; + gchar *string; + + menu = gtk_option_menu_get_menu (prefs->charset); + if (!(string = e_charset_picker_get_charset (menu))) + string = g_strdup (camel_iconv_locale_charset ()); + + gconf_client_set_string (prefs->gconf, "/apps/evolution/mail/display/charset", string, NULL); + g_free (string); +} + +static void +charset_menu_init (EMMailerPrefs *prefs) +{ + GtkWidget *menu, *item; + GList *items; + gchar *buf; + + buf = gconf_client_get_string (prefs->gconf, "/apps/evolution/mail/display/charset", NULL); + menu = e_charset_picker_new (buf && *buf ? buf : camel_iconv_locale_charset ()); + gtk_option_menu_set_menu (prefs->charset, GTK_WIDGET (menu)); + g_free (buf); + + items = GTK_MENU_SHELL (menu)->children; + while (items) { + item = items->data; + g_signal_connect (item, "activate", G_CALLBACK (charset_activate), prefs); + items = items->next; + } + + if (!gconf_client_key_is_writable (prefs->gconf, "/apps/evolution/mail/display/charset", NULL)) + gtk_widget_set_sensitive ((GtkWidget *) prefs->charset, FALSE); +} + +static void +trash_days_activate (GtkWidget *item, EMMailerPrefs *prefs) +{ + gint days; + + days = GPOINTER_TO_INT (g_object_get_data ((GObject *) item, "days")); + gconf_client_set_int (prefs->gconf, "/apps/evolution/mail/trash/empty_on_exit_days", days, NULL); +} + +static void +emmp_empty_trash_init (EMMailerPrefs *prefs) +{ + gint locked, days, hist = 0, i; + GtkWidget *menu, *item; + + days = gconf_client_get_int(prefs->gconf, "/apps/evolution/mail/trash/empty_on_exit_days", NULL); + menu = gtk_menu_new(); + for (i = 0; i < G_N_ELEMENTS (empty_trash_frequency); i++) { + if (days >= empty_trash_frequency[i].days) + hist = i; + + item = gtk_menu_item_new_with_label (_(empty_trash_frequency[i].label)); + g_object_set_data ((GObject *) item, "days", GINT_TO_POINTER (empty_trash_frequency[i].days)); + g_signal_connect (item, "activate", G_CALLBACK (trash_days_activate), prefs); + + gtk_widget_show (item); + gtk_menu_shell_append((GtkMenuShell *)menu, item); + } + + gtk_widget_show(menu); + gtk_option_menu_set_menu((GtkOptionMenu *)prefs->empty_trash_days, menu); + gtk_option_menu_set_history((GtkOptionMenu *)prefs->empty_trash_days, hist); + + locked = !gconf_client_key_is_writable (prefs->gconf, "/apps/evolution/mail/trash/empty_on_exit_days", NULL); + gtk_widget_set_sensitive ((GtkWidget *) prefs->empty_trash_days, !locked); +} + +static void +junk_days_activate (GtkWidget *item, EMMailerPrefs *prefs) +{ + gint days; + + days = GPOINTER_TO_INT (g_object_get_data ((GObject *) item, "days")); + gconf_client_set_int (prefs->gconf, "/apps/evolution/mail/junk/empty_on_exit_days", days, NULL); +} + +static void +emmp_empty_junk_init (EMMailerPrefs *prefs) +{ + gint locked, days, hist = 0, i; + GtkWidget *menu, *item; + + toggle_button_init (prefs, prefs->empty_junk, FALSE, + "/apps/evolution/mail/junk/empty_on_exit", + G_CALLBACK (toggle_button_toggled)); + + days = gconf_client_get_int(prefs->gconf, "/apps/evolution/mail/junk/empty_on_exit_days", NULL); + menu = gtk_menu_new(); + for (i = 0; i < G_N_ELEMENTS (empty_trash_frequency); i++) { + if (days >= empty_trash_frequency[i].days) + hist = i; + + item = gtk_menu_item_new_with_label (_(empty_trash_frequency[i].label)); + g_object_set_data ((GObject *) item, "days", GINT_TO_POINTER (empty_trash_frequency[i].days)); + g_signal_connect (item, "activate", G_CALLBACK (junk_days_activate), prefs); + + gtk_widget_show (item); + gtk_menu_shell_append((GtkMenuShell *)menu, item); + } + + gtk_widget_show(menu); + gtk_option_menu_set_menu((GtkOptionMenu *)prefs->empty_junk_days, menu); + gtk_option_menu_set_history((GtkOptionMenu *)prefs->empty_junk_days, hist); + + locked = !gconf_client_key_is_writable (prefs->gconf, "/apps/evolution/mail/junk/empty_on_exit_days", NULL); + gtk_widget_set_sensitive ((GtkWidget *) prefs->empty_junk_days, !locked); +} + +static void +http_images_changed (GtkWidget *widget, EMMailerPrefs *prefs) +{ + gint when; + + if (gtk_toggle_button_get_active (prefs->images_always)) + when = MAIL_CONFIG_HTTP_ALWAYS; + else if (gtk_toggle_button_get_active (prefs->images_sometimes)) + when = MAIL_CONFIG_HTTP_SOMETIMES; + else + when = MAIL_CONFIG_HTTP_NEVER; + + gconf_client_set_int (prefs->gconf, "/apps/evolution/mail/display/load_http_images", when, NULL); +} + + +static GtkWidget * +emmp_widget_glade(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + EMMailerPrefs *prefs = data; + + return glade_xml_get_widget(prefs->gui, item->label); +} + +/* plugin meta-data */ +static EMConfigItem emmp_items[] = { + { E_CONFIG_BOOK, (gchar *) "", (gchar *) "preferences_toplevel", emmp_widget_glade }, + { E_CONFIG_PAGE, (gchar *) "00.general", (gchar *) "vboxGeneral", emmp_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "00.general/00.fonts", (gchar *) "vboxMessageFonts", emmp_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "00.general/10.display", (gchar *) "vboxMessageDisplay", emmp_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "00.general/20.delete", (gchar *) "vboxDeletingMail", emmp_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "00.general/30.newmail", (gchar *) "vboxNewMailNotify", emmp_widget_glade }, + { E_CONFIG_PAGE, (gchar *) "10.html", (gchar *) "vboxHtmlMail", emmp_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "10.html/00.general", (gchar *) "vbox173", emmp_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "10.html/10.images", (gchar *) "vbox190", emmp_widget_glade }, + { E_CONFIG_PAGE, (gchar *) "20.labels", (gchar *) "frameColours", emmp_widget_glade }, + /* this is a table, so we can't use it { E_CONFIG_SECTION, "20.labels/00.labels", "tableColours", emmp_widget_glade }, */ + { E_CONFIG_PAGE, (gchar *) "30.headers", (gchar *) "vboxHeaderTab", emmp_widget_glade }, + /* no subvbox for section { E_CONFIG_PAGE, "30.headers/00.headers", "vbox199", emmp_widget_glade }, */ + { E_CONFIG_PAGE, (gchar *) "40.junk", (gchar *) "vbox161", emmp_widget_glade }, + /* no subvbox for section { E_CONFIG_SECTION, "40.junk/00.general", xxx, emmp_widget_glade } */ + { E_CONFIG_SECTION, (gchar *) "40.junk/10.options", (gchar *) "vbox204", emmp_widget_glade }, +}; + +static void +emmp_free(EConfig *ec, GSList *items, gpointer data) +{ + /* the prefs data is freed automagically */ + + g_slist_free(items); +} + +static void +junk_plugin_changed (GtkWidget *combo, EMMailerPrefs *prefs) +{ + gchar *def_plugin = gtk_combo_box_get_active_text(GTK_COMBO_BOX (combo)); + const GList *plugins = mail_session_get_junk_plugins(); + + gconf_client_set_string (prefs->gconf, "/apps/evolution/mail/junk/default_plugin", def_plugin, NULL); + while (plugins) { + struct _EMJunkHookItem *item = plugins->data;; + + if (item->plugin_name && def_plugin && !strcmp (item->plugin_name, def_plugin)) { + gboolean status; + + session->junk_plugin = CAMEL_JUNK_PLUGIN (&(item->csp)); + status = e_plugin_invoke (item->hook->hook.plugin, item->validate_binary, NULL) != NULL; + if ((gboolean)status == TRUE) { + gchar *text, *html; + gtk_image_set_from_stock (prefs->plugin_image, "gtk-dialog-info", GTK_ICON_SIZE_MENU); + text = g_strdup_printf (_("%s plugin is available and the binary is installed."), item->plugin_name); + html = g_strdup_printf ("%s", text); + gtk_label_set_markup (prefs->plugin_status, html); + g_free (html); + g_free (text); + } else { + gchar *text, *html; + gtk_image_set_from_stock (prefs->plugin_image, "gtk-dialog-warning", GTK_ICON_SIZE_MENU); + text = g_strdup_printf (_("%s plugin is not available. Please check whether the package is installed."), item->plugin_name); + html = g_strdup_printf ("%s", text); + gtk_label_set_markup (prefs->plugin_status, html); + g_free (html); + g_free (text); + } + break; + } + plugins = plugins->next; + } +} + +static void +junk_plugin_setup (GtkWidget *combo, EMMailerPrefs *prefs) +{ + gint index = 0; + gboolean def_set = FALSE; + const GList *plugins = mail_session_get_junk_plugins(); + gchar *pdefault = gconf_client_get_string (prefs->gconf, "/apps/evolution/mail/junk/default_plugin", NULL); + + if (!plugins || !g_list_length ((GList *)plugins)) { + gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("No Junk plugin available")); + gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0); + gtk_widget_set_sensitive (GTK_WIDGET (combo), FALSE); + gtk_widget_hide (GTK_WIDGET (prefs->plugin_image)); + gtk_widget_hide (GTK_WIDGET (prefs->plugin_status)); + gtk_image_set_from_stock (prefs->plugin_image, NULL, 0); + g_free (pdefault); + + return; + } + + while (plugins) { + struct _EMJunkHookItem *item = plugins->data;; + + gtk_combo_box_append_text (GTK_COMBO_BOX (combo), item->plugin_name); + if (!def_set && pdefault && item->plugin_name && !strcmp(pdefault, item->plugin_name)) { + gboolean status; + + def_set = TRUE; + gtk_combo_box_set_active (GTK_COMBO_BOX (combo), index); + status = e_plugin_invoke (item->hook->hook.plugin, item->validate_binary, NULL) != NULL; + if (status) { + gchar *text, *html; + gtk_image_set_from_stock (prefs->plugin_image, "gtk-dialog-info", GTK_ICON_SIZE_MENU); + /* May be a better text */ + text = g_strdup_printf (_("%s plugin is available and the binary is installed."), item->plugin_name); + html = g_strdup_printf ("%s", text); + gtk_label_set_markup (prefs->plugin_status, html); + g_free (html); + g_free (text); + } else { + gchar *text, *html; + gtk_image_set_from_stock (prefs->plugin_image, "gtk-dialog-warning", GTK_ICON_SIZE_MENU); + /* May be a better text */ + text = g_strdup_printf (_("%s plugin is not available. Please check whether the package is installed."), item->plugin_name); + html = g_strdup_printf ("%s", text); + gtk_label_set_markup (prefs->plugin_status, html); + g_free (html); + g_free (text); + } + } + plugins = plugins->next; + index++; + } + + g_signal_connect (combo, "changed", G_CALLBACK(junk_plugin_changed), prefs); + g_free (pdefault); +} + +GtkWidget * +create_combo_text_widget (void) { + return gtk_combo_box_new_text (); +} + +static void +em_mailer_prefs_construct (EMMailerPrefs *prefs, + EShell *shell) +{ + GSList *header_config_list, *header_add_list, *p; + EShellSettings *shell_settings; + GHashTable *default_header_hash; + GtkWidget *toplevel; + GtkWidget *container; + GtkWidget *widget; + GtkTreeSelection *selection; + GtkCellRenderer *renderer; + GtkTreeIter iter; + GladeXML *gui; + gboolean locked; + gint val, i; + EMConfig *ec; + EMConfigTargetPrefs *target; + GSList *l; + gchar *gladefile; + + shell_settings = e_shell_get_shell_settings (shell); + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + "mail-config.glade", + NULL); + gui = glade_xml_new (gladefile, "preferences_toplevel", NULL); + g_free (gladefile); + + prefs->gui = gui; + + /** @HookPoint-EMConfig: Mail Preferences Page + * @Id: org.gnome.evolution.mail.prefs + * @Type: E_CONFIG_BOOK + * @Class: org.gnome.evolution.mail.config:1.0 + * @Target: EMConfigTargetPrefs + * + * The main mail preferences page. + */ + ec = em_config_new(E_CONFIG_BOOK, "org.gnome.evolution.mail.prefs"); + l = NULL; + for (i=0;itimeout = GTK_SPIN_BUTTON (widget); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-mark-seen", + G_OBJECT (widget), "sensitive"); + e_mutual_binding_new_full ( + G_OBJECT (shell_settings), "mail-mark-seen-timeout", + G_OBJECT (widget), "value", + mark_seen_timeout_transform, + mark_seen_timeout_reverse_transform, + NULL, NULL); + + widget = glade_xml_get_widget (gui, "mlimit_checkbutton"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-force-message-limit", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "mlimit_spin"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-force-message-limit", + G_OBJECT (widget), "sensitive"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-message-text-part-limit", + G_OBJECT (widget), "value"); + + widget = glade_xml_get_widget (gui, "address_checkbox"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-address-compress", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "address_spin"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-address-compress", + G_OBJECT (widget), "sensitive"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-address-count", + G_OBJECT (widget), "value"); + + widget = glade_xml_get_widget (gui, "magic_spacebar_checkbox"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-magic-spacebar", + G_OBJECT (widget), "active"); + + prefs->charset = GTK_OPTION_MENU (glade_xml_get_widget (gui, "omenuCharset")); + charset_menu_init (prefs); + + widget = glade_xml_get_widget (gui, "chkHighlightCitations"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-mark-citations", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "colorButtonHighlightCitations"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-mark-citations", + G_OBJECT (widget), "sensitive"); + e_mutual_binding_new_full ( + G_OBJECT (shell_settings), "mail-citation-color", + G_OBJECT (widget), "color", + e_binding_transform_string_to_color, + e_binding_transform_color_to_string, + NULL, NULL); + + widget = glade_xml_get_widget (gui, "chkEnableSearchFolders"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-enable-search-folders", + G_OBJECT (widget), "active"); + + /* Deleting Mail */ + widget = glade_xml_get_widget (gui, "chkEmptyTrashOnExit"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-empty-trash-on-exit", + G_OBJECT (widget), "active"); + + prefs->empty_trash_days = GTK_OPTION_MENU (glade_xml_get_widget (gui, "omenuEmptyTrashDays")); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-empty-trash-on-exit", + G_OBJECT (prefs->empty_trash_days), "sensitive"); + emmp_empty_trash_init (prefs); + + widget = glade_xml_get_widget (gui, "chkConfirmExpunge"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-confirm-expunge", + G_OBJECT (widget), "active"); + + /* Mail Fonts */ + widget = glade_xml_get_widget (gui, "radFontUseSame"); + e_mutual_binding_new_with_negation ( + G_OBJECT (shell_settings), "mail-use-custom-fonts", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "FontFixed"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-font-monospace", + G_OBJECT (widget), "font-name"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-use-custom-fonts", + G_OBJECT (widget), "sensitive"); + + widget = glade_xml_get_widget (gui, "FontVariable"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-font-variable", + G_OBJECT (widget), "font-name"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-use-custom-fonts", + G_OBJECT (widget), "sensitive"); + + /* HTML Mail tab */ + + /* Loading Images */ + locked = !gconf_client_key_is_writable (prefs->gconf, "/apps/evolution/mail/display/load_http_images", NULL); + + val = gconf_client_get_int (prefs->gconf, "/apps/evolution/mail/display/load_http_images", NULL); + prefs->images_never = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "radImagesNever")); + gtk_toggle_button_set_active (prefs->images_never, val == MAIL_CONFIG_HTTP_NEVER); + if (locked) + gtk_widget_set_sensitive ((GtkWidget *) prefs->images_never, FALSE); + + prefs->images_sometimes = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "radImagesSometimes")); + gtk_toggle_button_set_active (prefs->images_sometimes, val == MAIL_CONFIG_HTTP_SOMETIMES); + if (locked) + gtk_widget_set_sensitive ((GtkWidget *) prefs->images_sometimes, FALSE); + + prefs->images_always = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "radImagesAlways")); + gtk_toggle_button_set_active (prefs->images_always, val == MAIL_CONFIG_HTTP_ALWAYS); + if (locked) + gtk_widget_set_sensitive ((GtkWidget *) prefs->images_always, FALSE); + + g_signal_connect (prefs->images_never, "toggled", G_CALLBACK (http_images_changed), prefs); + g_signal_connect (prefs->images_sometimes, "toggled", G_CALLBACK (http_images_changed), prefs); + g_signal_connect (prefs->images_always, "toggled", G_CALLBACK (http_images_changed), prefs); + + widget = glade_xml_get_widget (gui, "chkShowAnimatedImages"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-show-animated-images", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "chkPromptWantHTML"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-confirm-unwanted-html", + G_OBJECT (widget), "active"); + + container = glade_xml_get_widget (gui, "labels-alignment"); + widget = e_mail_label_manager_new (); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + e_binding_new ( + G_OBJECT (shell_settings), "mail-label-list-store", + G_OBJECT (widget), "list-store"); + + /* headers */ + locked = !gconf_client_key_is_writable (prefs->gconf, "/apps/evolution/mail/display/headers", NULL); + + widget = glade_xml_get_widget (gui, "photo_show"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-show-sender-photo", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "photo_local"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-show-sender-photo", + G_OBJECT (widget), "sensitive"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-only-local-photos", + G_OBJECT (widget), "active"); + + /* always de-sensitised until the user types something in the entry */ + prefs->add_header = GTK_BUTTON (glade_xml_get_widget (gui, "cmdHeadersAdd")); + gtk_widget_set_sensitive ((GtkWidget *) prefs->add_header, FALSE); + + /* always de-sensitised until the user selects a header in the list */ + prefs->remove_header = GTK_BUTTON (glade_xml_get_widget (gui, "cmdHeadersRemove")); + gtk_widget_set_sensitive ((GtkWidget *) prefs->remove_header, FALSE); + + prefs->entry_header = GTK_ENTRY (glade_xml_get_widget (gui, "txtHeaders")); + gtk_widget_set_sensitive ((GtkWidget *) prefs->entry_header, !locked); + + prefs->header_list = GTK_TREE_VIEW (glade_xml_get_widget (gui, "treeHeaders")); + gtk_widget_set_sensitive ((GtkWidget *) prefs->header_list, !locked); + + selection = gtk_tree_view_get_selection (prefs->header_list); + g_signal_connect (selection, "changed", G_CALLBACK (emmp_header_list_row_selected), prefs); + g_signal_connect (prefs->entry_header, "changed", G_CALLBACK (emmp_header_entry_changed), prefs); + g_signal_connect (prefs->entry_header, "activate", G_CALLBACK (emmp_header_add_header), prefs); + /* initialise the tree with appropriate headings */ + prefs->header_list_store = gtk_list_store_newv (HEADER_LIST_N_COLUMNS, col_types); + g_signal_connect (prefs->add_header, "clicked", G_CALLBACK (emmp_header_add_header), prefs); + g_signal_connect (prefs->remove_header, "clicked", G_CALLBACK (emmp_header_remove_header), prefs); + gtk_tree_view_set_model (prefs->header_list, GTK_TREE_MODEL (prefs->header_list_store)); + + renderer = gtk_cell_renderer_toggle_new (); + g_object_set (renderer, "activatable", TRUE, NULL); + g_signal_connect (renderer, "toggled", G_CALLBACK (emmp_header_list_enabled_toggled), prefs); + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (prefs->header_list), -1, + "Enabled", renderer, + "active", HEADER_LIST_ENABLED_COLUMN, + NULL); + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (prefs->header_list), -1, + "Name", renderer, + "text", HEADER_LIST_NAME_COLUMN, + NULL); + + /* populated the listview with entries; firstly we add all the default headers, and then + we add read header configuration out of gconf. If a header in gconf is a default header, + we update the enabled flag accordingly + */ + header_add_list = NULL; + default_header_hash = g_hash_table_new (g_str_hash, g_str_equal); + for (i = 0; i < G_N_ELEMENTS (default_headers); i++) { + struct _EMMailerPrefsHeader *h; + + h = g_malloc (sizeof (struct _EMMailerPrefsHeader)); + h->is_default = TRUE; + h->name = g_strdup (default_headers[i]); + h->enabled = strcmp ((gchar *)default_headers[i], "x-evolution-mailer") != 0; + g_hash_table_insert (default_header_hash, (gpointer) default_headers[i], h); + header_add_list = g_slist_append (header_add_list, h); + } + + /* read stored headers from gconf */ + header_config_list = gconf_client_get_list (prefs->gconf, "/apps/evolution/mail/display/headers", GCONF_VALUE_STRING, NULL); + p = header_config_list; + while (p) { + struct _EMMailerPrefsHeader *h, *def; + gchar *xml = (gchar *) p->data; + + h = em_mailer_prefs_header_from_xml (xml); + if (h) { + def = g_hash_table_lookup (default_header_hash, h->name); + if (def) { + def->enabled = h->enabled; + em_mailer_prefs_header_free (h); + } else { + h->is_default = FALSE; + header_add_list = g_slist_append (header_add_list, h); + } + } + + p = p->next; + } + + g_hash_table_destroy (default_header_hash); + g_slist_foreach (header_config_list, (GFunc) g_free, NULL); + g_slist_free (header_config_list); + + p = header_add_list; + while (p) { + struct _EMMailerPrefsHeader *h = (struct _EMMailerPrefsHeader *) p->data; + const gchar *name; + + if (g_ascii_strcasecmp (h->name, EM_FORMAT_HEADER_XMAILER) == 0) + name = _("Mailer"); + else + name = _(h->name); + + gtk_list_store_append (prefs->header_list_store, &iter); + gtk_list_store_set (prefs->header_list_store, &iter, + HEADER_LIST_NAME_COLUMN, name, + HEADER_LIST_ENABLED_COLUMN, h->enabled, + HEADER_LIST_IS_DEFAULT_COLUMN, h->is_default, + HEADER_LIST_HEADER_COLUMN, h->name, + -1); + + em_mailer_prefs_header_free (h); + p = p->next; + } + + g_slist_free (header_add_list); + + /* Junk prefs */ + widget = glade_xml_get_widget (gui, "chkCheckIncomingMail"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-check-for-junk", + G_OBJECT (widget), "active"); + + prefs->empty_junk = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "junk_empty_check")); + prefs->empty_junk_days = GTK_OPTION_MENU (glade_xml_get_widget (gui, "junk_empty_combo")); + emmp_empty_junk_init (prefs); + + prefs->default_junk_plugin = GTK_COMBO_BOX (glade_xml_get_widget (gui, "default_junk_plugin")); + prefs->plugin_status = GTK_LABEL (glade_xml_get_widget (gui, "plugin_status")); + prefs->plugin_image = GTK_IMAGE (glade_xml_get_widget (gui, "plugin_image")); + junk_plugin_setup (GTK_WIDGET (prefs->default_junk_plugin), prefs); + + prefs->junk_header_check = (GtkToggleButton *)glade_xml_get_widget (gui, "junk_header_check"); + prefs->junk_header_tree = (GtkTreeView *)glade_xml_get_widget (gui, "junk_header_tree"); + prefs->junk_header_add = (GtkButton *)glade_xml_get_widget (gui, "junk_header_add"); + prefs->junk_header_remove = (GtkButton *)glade_xml_get_widget (gui, "junk_header_remove"); + prefs->junk_book_lookup = (GtkToggleButton *)glade_xml_get_widget (gui, "lookup_book"); + prefs->junk_lookup_local_only = (GtkToggleButton *)glade_xml_get_widget (gui, "junk_lookup_local_only"); + toggle_button_init (prefs, prefs->junk_book_lookup, FALSE, + "/apps/evolution/mail/junk/lookup_addressbook", + G_CALLBACK (junk_book_lookup_button_toggled)); + + toggle_button_init (prefs, prefs->junk_lookup_local_only, FALSE, + "/apps/evolution/mail/junk/lookup_addressbook_local_only", + G_CALLBACK (toggle_button_toggled)); + + junk_book_lookup_button_toggled (prefs->junk_book_lookup, prefs); + + prefs->junk_header_list_store = init_junk_tree ((GtkWidget *)prefs->junk_header_tree, prefs); + toggle_button_init (prefs, prefs->junk_header_check, FALSE, + "/apps/evolution/mail/junk/check_custom_header", + G_CALLBACK (custom_junk_button_toggled)); + + custom_junk_button_toggled (prefs->junk_header_check, prefs); + jh_tree_refill (prefs); + g_signal_connect (G_OBJECT (prefs->junk_header_add), "clicked", G_CALLBACK (jh_add_cb), prefs); + g_signal_connect (G_OBJECT (prefs->junk_header_remove), "clicked", G_CALLBACK (jh_remove_cb), prefs); + + /* get our toplevel widget */ + target = em_config_target_new_prefs(ec, prefs->gconf); + e_config_set_target((EConfig *)ec, (EConfigTarget *)target); + toplevel = e_config_create_widget((EConfig *)ec); + gtk_container_add (GTK_CONTAINER (prefs), toplevel); +} + +GtkWidget * +em_mailer_prefs_new (EShell *shell) +{ + EMMailerPrefs *new; + + g_return_val_if_fail (E_IS_SHELL (shell), NULL); + + new = g_object_new (EM_TYPE_MAILER_PREFS, NULL); + + /* FIXME Kill this function. */ + em_mailer_prefs_construct (new, shell); + + return GTK_WIDGET (new); +} + + +static struct _EMMailerPrefsHeader * +emmp_header_from_xmldoc (xmlDocPtr doc) +{ + struct _EMMailerPrefsHeader *h; + xmlNodePtr root; + xmlChar *name; + + if (doc == NULL) + return NULL; + + root = doc->children; + if (strcmp ((gchar *)root->name, "header") != 0) + return NULL; + + name = xmlGetProp (root, (const guchar *)"name"); + if (name == NULL) + return NULL; + + h = g_malloc0 (sizeof (struct _EMMailerPrefsHeader)); + h->name = g_strdup ((gchar *)name); + xmlFree (name); + + if (xmlHasProp (root, (const guchar *)"enabled")) + h->enabled = 1; + else + h->enabled = 0; + + return h; +} + +/** + * em_mailer_prefs_header_from_xml + * @xml: XML configuration data + * + * Parses passed XML data, which should be of + * the format
, and + * returns a EMMailerPrefs structure, or NULL if there + * is an error. + **/ +struct _EMMailerPrefsHeader * +em_mailer_prefs_header_from_xml (const gchar *xml) +{ + struct _EMMailerPrefsHeader *header; + xmlDocPtr doc; + + if (!(doc = xmlParseDoc ((guchar *) xml))) + return NULL; + + header = emmp_header_from_xmldoc (doc); + xmlFreeDoc (doc); + + return header; +} + +/** + * em_mailer_prefs_header_free + * @header: header to free + * + * Frees the memory associated with the passed header + * structure. + */ +void +em_mailer_prefs_header_free (struct _EMMailerPrefsHeader *header) +{ + if (header == NULL) + return; + + g_free (header->name); + g_free (header); +} + +/** + * em_mailer_prefs_header_to_xml + * @header: header from which to generate XML + * + * Returns the passed header as a XML structure, + * or NULL on error + */ +gchar * +em_mailer_prefs_header_to_xml (struct _EMMailerPrefsHeader *header) +{ + xmlDocPtr doc; + xmlNodePtr root; + xmlChar *xml; + gchar *out; + gint size; + + g_return_val_if_fail (header != NULL, NULL); + g_return_val_if_fail (header->name != NULL, NULL); + + doc = xmlNewDoc ((const guchar *)"1.0"); + + root = xmlNewDocNode (doc, NULL, (const guchar *)"header", NULL); + xmlSetProp (root, (const guchar *)"name", (guchar *)header->name); + if (header->enabled) + xmlSetProp (root, (const guchar *)"enabled", NULL); + + xmlDocSetRootElement (doc, root); + xmlDocDumpMemory (doc, &xml, &size); + xmlFreeDoc (doc); + + out = g_malloc (size + 1); + memcpy (out, xml, size); + out[size] = '\0'; + xmlFree (xml); + + return out; +} diff --git a/modules/mail/em-mailer-prefs.h b/modules/mail/em-mailer-prefs.h new file mode 100644 index 0000000000..b33e620392 --- /dev/null +++ b/modules/mail/em-mailer-prefs.h @@ -0,0 +1,141 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Jeffrey Stedfast + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef EM_MAILER_PREFS_H +#define EM_MAILER_PREFS_H + +#include +#include +#include +#include + +/* Standard GObject macros */ +#define EM_TYPE_MAILER_PREFS \ + (em_mailer_prefs_get_type ()) +#define EM_MAILER_PREFS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EM_TYPE_MAILER_PREFS, EMMailerPrefs)) +#define EM_MAILER_PREFS_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EM_TYPE_MAILER_PREFS, EMMailerPrefsClass)) +#define EM_IS_MAILER_PREFS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EM_TYPE_MAILER_PREFS)) +#define EM_IS_MAILER_PREFS_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EM_TYPE_MAILER_PREFS)) +#define EM_MAILER_PREFS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), EM_TYPE_MAILER_PREFS)) + +G_BEGIN_DECLS + +typedef struct _EMMailerPrefs EMMailerPrefs; +typedef struct _EMMailerPrefsClass EMMailerPrefsClass; +typedef struct _EMMailerPrefsHeader EMMailerPrefsHeader; + +struct _EMMailerPrefsHeader { + gchar *name; + guint enabled:1; + guint is_default:1; +}; + +struct _EMMailerPrefs { + GtkVBox parent_object; + + GladeXML *gui; + GConfClient *gconf; + + /* General tab */ + + /* Message Display */ + GtkSpinButton *timeout; + GtkOptionMenu *charset; + + /* Deleting Mail */ + GtkToggleButton *empty_trash; + GtkComboBox *empty_trash_days; + GtkToggleButton *confirm_expunge; + + /* HTML Mail tab */ + GtkFontButton *font_variable; + GtkFontButton *font_fixed; + GtkToggleButton *font_share; + + /* Loading Images */ + GtkToggleButton *images_always; + GtkToggleButton *images_sometimes; + GtkToggleButton *images_never; + + GtkToggleButton *autodetect_links; + + /* Labels and Colours tab */ + GtkWidget *label_add; + GtkWidget *label_edit; + GtkWidget *label_remove; + GtkWidget *label_tree; + GtkListStore *label_list_store; + guint labels_change_notify_id; /* mail_config's notify id */ + + /* Headers tab */ + GtkButton *add_header; + GtkButton *remove_header; + GtkEntry *entry_header; + GtkTreeView *header_list; + GtkListStore *header_list_store; + + /* Junk prefs */ + GtkToggleButton *empty_junk; + GtkComboBox *empty_junk_days; + + GtkToggleButton *sa_local_tests_only; + GtkToggleButton *sa_use_daemon; + GtkComboBox *default_junk_plugin; + GtkLabel *plugin_status; + GtkImage *plugin_image; + + GtkToggleButton *junk_header_check; + GtkTreeView *junk_header_tree; + GtkListStore *junk_header_list_store; + GtkButton *junk_header_add; + GtkButton *junk_header_remove; + GtkToggleButton *junk_book_lookup; + GtkToggleButton *junk_lookup_local_only; +}; + +struct _EMMailerPrefsClass { + GtkVBoxClass parent_class; +}; + +GType em_mailer_prefs_get_type (void); +GtkWidget * create_combo_text_widget (void); + +GtkWidget * em_mailer_prefs_new (EShell *shell); + +EMMailerPrefsHeader * + em_mailer_prefs_header_from_xml (const gchar *xml); +gchar * em_mailer_prefs_header_to_xml (EMMailerPrefsHeader *header); +void em_mailer_prefs_header_free (EMMailerPrefsHeader *header); + +G_END_DECLS + +#endif /* EM_MAILER_PREFS_H */ diff --git a/modules/mail/em-network-prefs.c b/modules/mail/em-network-prefs.c new file mode 100644 index 0000000000..e530d4d076 --- /dev/null +++ b/modules/mail/em-network-prefs.c @@ -0,0 +1,499 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Veerapuram Varadhan + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "em-network-prefs.h" + +#include +#include +#include + +#include + +#include "e-util/e-error.h" +#include "e-util/e-util-private.h" + +#include "mail-config.h" +#include "em-config.h" + +#define d(x) + +#define GCONF_E_SHELL_NETWORK_CONFIG_PATH "/apps/evolution/shell/network_config/" +#define GCONF_E_HTTP_HOST_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "http_host" +#define GCONF_E_HTTP_PORT_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "http_port" +#define GCONF_E_HTTPS_HOST_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "secure_host" +#define GCONF_E_HTTPS_PORT_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "secure_port" +#define GCONF_E_SOCKS_HOST_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "socks_host" +#define GCONF_E_SOCKS_PORT_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "socks_port" +#define GCONF_E_IGNORE_HOSTS_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "ignore_hosts" +#define GCONF_E_USE_AUTH_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "use_authentication" +#define GCONF_E_PROXY_TYPE_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "proxy_type" +#define GCONF_E_AUTH_USER_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "authentication_user" +#define GCONF_E_AUTH_PWD_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "authentication_password" +#define GCONF_E_USE_PROXY_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "use_http_proxy" +#define GCONF_E_AUTOCONFIG_URL_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "autoconfig_url" + +static void em_network_prefs_class_init (EMNetworkPrefsClass *class); +static void em_network_prefs_init (EMNetworkPrefs *dialog); +static void em_network_prefs_destroy (GtkObject *obj); +static void em_network_prefs_finalise (GObject *obj); + + +static GtkVBoxClass *parent_class = NULL; + + +GType +em_network_prefs_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo info = { + sizeof (EMNetworkPrefsClass), + NULL, NULL, + (GClassInitFunc) em_network_prefs_class_init, + NULL, NULL, + sizeof (EMNetworkPrefs), + 0, + (GInstanceInitFunc) em_network_prefs_init, + }; + + type = g_type_register_static (gtk_vbox_get_type (), "EMNetworkPrefs", &info, 0); + } + + return type; +} + +static void +em_network_prefs_class_init (EMNetworkPrefsClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); + + parent_class = g_type_class_ref (gtk_vbox_get_type ()); + + object_class->destroy = em_network_prefs_destroy; + gobject_class->finalize = em_network_prefs_finalise; +} + +static void +em_network_prefs_init (EMNetworkPrefs *prefs) +{ + /* do something here */ +} + +static void +em_network_prefs_finalise (GObject *obj) +{ + d(g_print ("Network preferences finalize is called\n")); + + /* do something here */ + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +em_network_prefs_destroy (GtkObject *obj) +{ + d(g_print ("Network preferences destroy is called\n")); + + GTK_OBJECT_CLASS (parent_class)->destroy (obj); +} + +static void +toggle_button_toggled (GtkToggleButton *toggle, EMNetworkPrefs *prefs) +{ + const gchar *key; + + key = g_object_get_data ((GObject *) toggle, "key"); + gconf_client_set_bool (prefs->gconf, key, gtk_toggle_button_get_active (toggle), NULL); + if (toggle == prefs->use_auth) { + gboolean sensitivity = gtk_toggle_button_get_active (prefs->use_auth); + gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_auth_user, sensitivity); + gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_auth_pwd, sensitivity); + gtk_widget_set_sensitive ((GtkWidget *) prefs->auth_user, sensitivity); + gtk_widget_set_sensitive ((GtkWidget *) prefs->auth_pwd, sensitivity); + } +} + +static void +toggle_button_init (EMNetworkPrefs *prefs, GtkToggleButton *toggle, const gchar *key) +{ + gboolean bool; + + bool = gconf_client_get_bool (prefs->gconf, key, NULL); + gtk_toggle_button_set_active (toggle, bool); + + g_object_set_data ((GObject *) toggle, "key", (gpointer) key); + g_signal_connect (toggle, "toggled", G_CALLBACK (toggle_button_toggled), prefs); + + if (!gconf_client_key_is_writable (prefs->gconf, key, NULL)) + gtk_widget_set_sensitive ((GtkWidget *) toggle, FALSE); +} + +static GtkWidget * +emnp_widget_glade(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) +{ + EMNetworkPrefs *prefs = data; + + return glade_xml_get_widget(prefs->gui, item->label); +} + +static void +emnp_set_sensitiveness (EMNetworkPrefs *prefs, NetworkConfigProxyType type, gboolean sensitivity) +{ +#if 0 + if (type == NETWORK_PROXY_AUTOCONFIG) { + gtk_widget_set_sensitive ((GtkWidget *) prefs->auto_proxy_url, sensitivity); + d(g_print ("Setting sensitivity of autoconfig to: %d\n", sensitivity)); + } else +#endif + if (type == NETWORK_PROXY_MANUAL) { + gboolean state; + + gtk_widget_set_sensitive ((GtkWidget *) prefs->http_host, sensitivity); + gtk_widget_set_sensitive ((GtkWidget *) prefs->https_host, sensitivity); + gtk_widget_set_sensitive ((GtkWidget *) prefs->ignore_hosts, sensitivity); + gtk_widget_set_sensitive ((GtkWidget *) prefs->use_auth, sensitivity); + gtk_widget_set_sensitive ((GtkWidget *) prefs->http_port, sensitivity); + gtk_widget_set_sensitive ((GtkWidget *) prefs->https_port, sensitivity); + gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_ignore_hosts, sensitivity); + gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_http_host, sensitivity); + gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_http_port, sensitivity); + gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_https_host, sensitivity); + gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_https_port, sensitivity); +#if 0 + gtk_widget_set_sensitive ((GtkWidget *) prefs->socks_host, sensitivity); + gtk_widget_set_sensitive ((GtkWidget *) prefs->socks_port, sensitivity); + gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_socks_host, sensitivity); + gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_socks_port, sensitivity); +#endif + state = sensitivity && gtk_toggle_button_get_active (prefs->use_auth); + gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_auth_user, state); + gtk_widget_set_sensitive ((GtkWidget *) prefs->lbl_auth_pwd, state); + gtk_widget_set_sensitive ((GtkWidget *) prefs->auth_user, state); + gtk_widget_set_sensitive ((GtkWidget *) prefs->auth_pwd, state); + + d(g_print ("Setting sensitivity of manual proxy to: %d\n", sensitivity)); + } +} + +static void +notify_proxy_type_changed (GtkWidget *widget, EMNetworkPrefs *prefs) +{ + gint type; + + if (gtk_toggle_button_get_active (prefs->sys_proxy)) + type = NETWORK_PROXY_SYS_SETTINGS; + else if (gtk_toggle_button_get_active (prefs->no_proxy)) + type = NETWORK_PROXY_DIRECT_CONNECTION; + else if (gtk_toggle_button_get_active (prefs->manual_proxy)) + type = NETWORK_PROXY_MANUAL; + else +#if 0 + type = NETWORK_PROXY_AUTOCONFIG; +#else + type = NETWORK_PROXY_SYS_SETTINGS; +#endif + + gconf_client_set_int (prefs->gconf, "/apps/evolution/shell/network_config/proxy_type", type, NULL); + + if (type == NETWORK_PROXY_DIRECT_CONNECTION || + type == NETWORK_PROXY_SYS_SETTINGS) { + emnp_set_sensitiveness (prefs, NETWORK_PROXY_MANUAL, FALSE); + emnp_set_sensitiveness (prefs, NETWORK_PROXY_AUTOCONFIG, FALSE); + } else if (type == NETWORK_PROXY_AUTOCONFIG) { + emnp_set_sensitiveness (prefs, NETWORK_PROXY_MANUAL, FALSE); + emnp_set_sensitiveness (prefs, NETWORK_PROXY_AUTOCONFIG, TRUE); + } else if (type == NETWORK_PROXY_MANUAL) { + emnp_set_sensitiveness (prefs, NETWORK_PROXY_AUTOCONFIG, FALSE); + emnp_set_sensitiveness (prefs, NETWORK_PROXY_MANUAL, TRUE); + } + + if (type != NETWORK_PROXY_DIRECT_CONNECTION) + gconf_client_set_bool (prefs->gconf, GCONF_E_USE_PROXY_KEY, TRUE, NULL); + else if (type != NETWORK_PROXY_SYS_SETTINGS) + gconf_client_set_bool (prefs->gconf, GCONF_E_USE_PROXY_KEY, FALSE, NULL); + +} + +static void +widget_entry_changed_cb (GtkWidget *widget, gpointer data) +{ + const gchar *value; + gint port = -1; + GConfClient *gconf = mail_config_get_gconf_client (); + + /* + Do not change the order of comparison - + GtkSpinButton is an extended form of GtkEntry + */ + if (GTK_IS_SPIN_BUTTON (widget)) { + port = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget)); + gconf_client_set_int (gconf, (const gchar *)data, port, NULL); + d(g_print ("%s:%s: %s is SpinButton: value = [%d]\n", G_STRLOC, G_STRFUNC, (const gchar *)data, port)); + } else if (GTK_IS_ENTRY (widget)) { + value = gtk_entry_get_text (GTK_ENTRY (widget)); + gconf_client_set_string (gconf, (const gchar *)data, value, NULL); + d(g_print ("%s:%s: %s is Entry: value = [%s]\n", G_STRLOC, G_STRFUNC, (const gchar *)data, value)); + } + +} + +/* plugin meta-data */ +static EMConfigItem emnp_items[] = { + { E_CONFIG_BOOK, (gchar *) "", (gchar *) "network_preferences_toplevel", emnp_widget_glade }, + { E_CONFIG_PAGE, (gchar *) "00.general", (gchar *) "vboxGeneral", emnp_widget_glade }, + { E_CONFIG_SECTION, (gchar *) "00.general/00.proxy", (gchar *) "frameProxy", emnp_widget_glade }, +}; + +static void +emnp_free(EConfig *ec, GSList *items, gpointer data) +{ + /* the prefs data is freed automagically */ + + g_slist_free(items); +} + +static void +emnp_set_markups (EMNetworkPrefs *prefs) +{ + gtk_label_set_use_markup (GTK_LABEL (GTK_BIN(prefs->sys_proxy)->child), TRUE); + gtk_label_set_use_markup (GTK_LABEL (GTK_BIN(prefs->no_proxy)->child), TRUE); + gtk_label_set_use_markup (GTK_LABEL (GTK_BIN(prefs->manual_proxy)->child), TRUE); +#if 0 + gtk_label_set_use_markup (GTK_LABEL (GTK_BIN(prefs->auto_proxy)->child), TRUE); +#endif +} + +static void +em_network_prefs_construct (EMNetworkPrefs *prefs) +{ + GtkWidget *toplevel; + GladeXML *gui; + GSList* l; + gchar *buf; + EMConfig *ec; + EMConfigTargetPrefs *target; + gboolean locked; + gint i, val, port; + gchar *gladefile; + + prefs->gconf = mail_config_get_gconf_client (); + + gladefile = g_build_filename (EVOLUTION_GLADEDIR, + "mail-config.glade", + NULL); + gui = glade_xml_new (gladefile, "network_preferences_toplevel", NULL); + prefs->gui = gui; + g_free (gladefile); + + /** @HookPoint-EMConfig: Network Preferences + * @Id: org.gnome.evolution.mail.networkPrefs + * @Type: E_CONFIG_BOOK + * @Class: org.gnome.evolution.mail.config:1.0 + * @Target: EMConfigTargetPrefs + * + * The network preferences settings page. + */ + ec = em_config_new(E_CONFIG_BOOK, "org.gnome.evolution.mail.networkPrefs"); + l = NULL; + for (i=0;igconf, GCONF_E_PROXY_TYPE_KEY, NULL); + + val = gconf_client_get_int (prefs->gconf, GCONF_E_PROXY_TYPE_KEY, NULL); + + /* no auto-proxy at the moment */ + if (val == NETWORK_PROXY_AUTOCONFIG) + val = NETWORK_PROXY_SYS_SETTINGS; + + prefs->sys_proxy = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "rdoSysSettings")); + gtk_toggle_button_set_active (prefs->sys_proxy, val == NETWORK_PROXY_SYS_SETTINGS); + if (locked) + gtk_widget_set_sensitive ((GtkWidget *) prefs->sys_proxy, FALSE); + + d(g_print ("Sys settings ----!!! \n")); + + prefs->no_proxy = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "rdoNoProxy")); + gtk_toggle_button_set_active (prefs->no_proxy, val == NETWORK_PROXY_DIRECT_CONNECTION); + if (locked) + gtk_widget_set_sensitive ((GtkWidget *) prefs->no_proxy, FALSE); + + d(g_print ("No proxy settings ----!!! \n")); + + /* no auto-proxy at the moment */ +#if 0 + prefs->auto_proxy = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "rdoAutoConfig")); + prefs->auto_proxy_url = GTK_ENTRY (glade_xml_get_widget (gui, "txtAutoConfigUrl")); + + gtk_toggle_button_set_active (prefs->auto_proxy, val == NETWORK_PROXY_AUTOCONFIG); + + g_signal_connect(prefs->auto_proxy_url, "changed", G_CALLBACK(widget_entry_changed_cb), GCONF_E_AUTOCONFIG_URL_KEY); + if (locked) + gtk_widget_set_sensitive ((GtkWidget *) prefs->auto_proxy, FALSE); +#endif + + d(g_print ("Auto config settings ----!!! \n")); + + prefs->manual_proxy = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "rdoManualProxy")); + prefs->http_host = GTK_ENTRY (glade_xml_get_widget (gui, "txtHttpHost")); + prefs->https_host = GTK_ENTRY (glade_xml_get_widget (gui, "txtHttpsHost")); + prefs->ignore_hosts = GTK_ENTRY (glade_xml_get_widget (gui, "txtIgnoreHosts")); + prefs->http_port = GTK_SPIN_BUTTON (glade_xml_get_widget (gui, "spnHttpPort")); + prefs->https_port = GTK_SPIN_BUTTON (glade_xml_get_widget (gui, "spnHttpsPort")); + prefs->lbl_http_host = GTK_LABEL (glade_xml_get_widget (gui, "lblHttpHost")); + prefs->lbl_http_port = GTK_LABEL (glade_xml_get_widget (gui, "lblHttpPort")); + prefs->lbl_https_host = GTK_LABEL (glade_xml_get_widget (gui, "lblHttpsHost")); + prefs->lbl_https_port = GTK_LABEL (glade_xml_get_widget (gui, "lblHttpsPort")); + prefs->lbl_ignore_hosts = GTK_LABEL (glade_xml_get_widget (gui, "lblIgnoreHosts")); + prefs->use_auth = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "chkUseAuth")); + toggle_button_init (prefs, prefs->use_auth, GCONF_E_USE_AUTH_KEY); + prefs->lbl_auth_user = GTK_LABEL (glade_xml_get_widget (gui, "lblAuthUser")); + prefs->lbl_auth_pwd = GTK_LABEL (glade_xml_get_widget (gui, "lblAuthPwd")); + prefs->auth_user = GTK_ENTRY (glade_xml_get_widget (gui, "txtAuthUser")); + prefs->auth_pwd = GTK_ENTRY (glade_xml_get_widget (gui, "txtAuthPwd")); + +#if 0 + prefs->socks_host = GTK_ENTRY (glade_xml_get_widget (gui, "txtSocksHost")); + prefs->socks_port = GTK_SPIN_BUTTON (glade_xml_get_widget (gui, "spnSocksPort")); + prefs->lbl_socks_host = GTK_LABEL (glade_xml_get_widget (gui, "lblSocksHost")); + prefs->lbl_socks_port = GTK_LABEL (glade_xml_get_widget (gui, "lblSocksPort")); + g_signal_connect (prefs->socks_host, "changed", + G_CALLBACK(widget_entry_changed_cb), GCONF_E_SOCKS_HOST_KEY); + g_signal_connect (prefs->socks_port, "value_changed", + G_CALLBACK(widget_entry_changed_cb), GCONF_E_SOCKS_PORT_KEY); +#endif + + /* Manual proxy options */ + g_signal_connect (prefs->http_host, "changed", + G_CALLBACK(widget_entry_changed_cb), + (gpointer) GCONF_E_HTTP_HOST_KEY); + g_signal_connect (prefs->https_host, "changed", + G_CALLBACK(widget_entry_changed_cb), + (gpointer) GCONF_E_HTTPS_HOST_KEY); + g_signal_connect (prefs->ignore_hosts, "changed", + G_CALLBACK(widget_entry_changed_cb), + (gpointer) GCONF_E_IGNORE_HOSTS_KEY); + g_signal_connect (prefs->http_port, "value_changed", + G_CALLBACK(widget_entry_changed_cb), + (gpointer) GCONF_E_HTTP_PORT_KEY); + g_signal_connect (prefs->https_port, "value_changed", + G_CALLBACK(widget_entry_changed_cb), + (gpointer) GCONF_E_HTTPS_PORT_KEY); + g_signal_connect (prefs->auth_user, "changed", + G_CALLBACK(widget_entry_changed_cb), + (gpointer) GCONF_E_AUTH_USER_KEY); + g_signal_connect (prefs->auth_pwd, "changed", + G_CALLBACK(widget_entry_changed_cb), + (gpointer) GCONF_E_AUTH_PWD_KEY); + + gtk_toggle_button_set_active (prefs->manual_proxy, val == NETWORK_PROXY_MANUAL); + g_signal_connect (prefs->sys_proxy, "toggled", G_CALLBACK (notify_proxy_type_changed), prefs); + g_signal_connect (prefs->no_proxy, "toggled", G_CALLBACK (notify_proxy_type_changed), prefs); +#if 0 + g_signal_connect (prefs->auto_proxy, "toggled", G_CALLBACK (notify_proxy_type_changed), prefs); +#endif + g_signal_connect (prefs->manual_proxy, "toggled", G_CALLBACK (notify_proxy_type_changed), prefs); + + if (locked) + gtk_widget_set_sensitive ((GtkWidget *) prefs->manual_proxy, FALSE); + d(g_print ("Manual settings ----!!! \n")); + + buf = gconf_client_get_string (prefs->gconf, GCONF_E_HTTP_HOST_KEY, NULL); + gtk_entry_set_text (prefs->http_host, buf ? buf : ""); + g_free (buf); + + buf = gconf_client_get_string (prefs->gconf, GCONF_E_HTTPS_HOST_KEY, NULL); + gtk_entry_set_text (prefs->https_host, buf ? buf : ""); + g_free (buf); + + buf = gconf_client_get_string (prefs->gconf, GCONF_E_IGNORE_HOSTS_KEY, NULL); + gtk_entry_set_text (prefs->ignore_hosts, buf ? buf : ""); + g_free (buf); + + buf = gconf_client_get_string (prefs->gconf, GCONF_E_AUTH_USER_KEY, NULL); + gtk_entry_set_text (prefs->auth_user, buf ? buf : ""); + g_free (buf); + + buf = gconf_client_get_string (prefs->gconf, GCONF_E_AUTH_PWD_KEY, NULL); + gtk_entry_set_text (prefs->auth_pwd, buf ? buf : ""); + g_free (buf); + + port = gconf_client_get_int (prefs->gconf, GCONF_E_HTTP_PORT_KEY, NULL); + gtk_spin_button_set_value (prefs->http_port, (gdouble)port); + + port = gconf_client_get_int (prefs->gconf, GCONF_E_HTTPS_PORT_KEY, NULL); + gtk_spin_button_set_value (prefs->https_port, (gdouble)port); + +#if 0 + buf = gconf_client_get_string (prefs->gconf, GCONF_E_SOCKS_HOST_KEY, NULL); + gtk_entry_set_text (prefs->socks_host, buf ? buf : ""); + g_free (buf); + + port = gconf_client_get_int (prefs->gconf, GCONF_E_SOCKS_PORT_KEY, NULL); + gtk_spin_button_set_value (prefs->socks_port, (gdouble)port); +#endif + emnp_set_markups (prefs); + + if (val == NETWORK_PROXY_DIRECT_CONNECTION || + val == NETWORK_PROXY_SYS_SETTINGS) { + emnp_set_sensitiveness (prefs, NETWORK_PROXY_MANUAL, FALSE); + emnp_set_sensitiveness (prefs, NETWORK_PROXY_AUTOCONFIG, FALSE); + } else if (val == NETWORK_PROXY_AUTOCONFIG) { + emnp_set_sensitiveness (prefs, NETWORK_PROXY_MANUAL, FALSE); + emnp_set_sensitiveness (prefs, NETWORK_PROXY_AUTOCONFIG, TRUE); + } else if (val == NETWORK_PROXY_MANUAL) { + emnp_set_sensitiveness (prefs, NETWORK_PROXY_AUTOCONFIG, FALSE); + emnp_set_sensitiveness (prefs, NETWORK_PROXY_MANUAL, TRUE); + } + + /* get our toplevel widget */ + target = em_config_target_new_prefs(ec, prefs->gconf); + e_config_set_target((EConfig *)ec, (EConfigTarget *)target); + toplevel = e_config_create_widget((EConfig *)ec); + gtk_container_add (GTK_CONTAINER (prefs), toplevel); +} + +GtkWidget * +em_network_prefs_new (void) +{ + EMNetworkPrefs *new; + + new = (EMNetworkPrefs *) g_object_new (em_network_prefs_get_type (), NULL); + em_network_prefs_construct (new); + + return (GtkWidget *) new; +} diff --git a/modules/mail/em-network-prefs.h b/modules/mail/em-network-prefs.h new file mode 100644 index 0000000000..057247b750 --- /dev/null +++ b/modules/mail/em-network-prefs.h @@ -0,0 +1,102 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Veerapuram Varadhan + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef EM_NETWORK_PREFS_H +#define EM_NETWORK_PREFS_H + +#include +#include +#include + +/* Standard GObject macros */ +#define EM_TYPE_NETWORK_PREFS \ + (em_network_prefs_get_type ()) +#define EM_NETWORK_PREFS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EM_TYPE_NETWORK_PREFS, EMNetworkPrefs)) +#define EM_NETWORK_PREFS_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EM_TYPE_NETWORK_PREFS, EMNetworkPrefsClass)) +#define EM_IS_NETWORK_PREFS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EM_TYPE_NETWORK_PREFS)) +#define EM_IS_NETWORK_PREFS_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EM_TYPE_NETWORK_PREFS)) +#define EM_NETWORK_PREFS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), EM_TYPE_NETWORK_PREFS, EMNetworkPrefsClass)) + +G_BEGIN_DECLS + +typedef struct _EMNetworkPrefs EMNetworkPrefs; +typedef struct _EMNetworkPrefsClass EMNetworkPrefsClass; + +typedef enum { + NETWORK_PROXY_SYS_SETTINGS, + NETWORK_PROXY_DIRECT_CONNECTION, + NETWORK_PROXY_MANUAL, + NETWORK_PROXY_AUTOCONFIG +} NetworkConfigProxyType; + +struct _EMNetworkPrefs { + GtkVBox parent_object; + + GConfClient *gconf; + + GladeXML *gui; + + /* Default Behavior */ + GtkToggleButton *sys_proxy; + GtkToggleButton *no_proxy; + GtkToggleButton *manual_proxy; + GtkToggleButton *use_auth; + + GtkEntry *http_host; + GtkEntry *https_host; + GtkEntry *socks_host; + GtkEntry *ignore_hosts; + GtkEntry *auth_user; + GtkEntry *auth_pwd; + + GtkLabel *lbl_http_host; + GtkLabel *lbl_http_port; + GtkLabel *lbl_https_host; + GtkLabel *lbl_https_port; + GtkLabel *lbl_ignore_hosts; + GtkLabel *lbl_auth_user; + GtkLabel *lbl_auth_pwd; + + GtkSpinButton *http_port; + GtkSpinButton *https_port; +}; + +struct _EMNetworkPrefsClass { + GtkVBoxClass parent_class; +}; + +GType em_network_prefs_get_type (void); +GtkWidget * em_network_prefs_new (void); + +G_END_DECLS + +#endif /* EM_NETWORK_PREFS_H */ diff --git a/modules/mail/evolution-module-mail.c b/modules/mail/evolution-module-mail.c new file mode 100644 index 0000000000..97bc953c41 --- /dev/null +++ b/modules/mail/evolution-module-mail.c @@ -0,0 +1,59 @@ +/* + * evolution-module-mail.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-shell-backend.h" +#include "e-mail-shell-content.h" +#include "e-mail-shell-sidebar.h" +#include "e-mail-shell-view.h" + +/* Module Entry Points */ +void e_module_load (GTypeModule *type_module); +void e_module_unload (GTypeModule *type_module); +const gchar * g_module_check_init (GModule *module); + +G_MODULE_EXPORT void +e_module_load (GTypeModule *type_module) +{ + /* Register dynamically loaded types. */ + + e_mail_shell_backend_register_type (type_module); + e_mail_shell_content_register_type (type_module); + e_mail_shell_sidebar_register_type (type_module); + e_mail_shell_view_register_type (type_module); +} + +G_MODULE_EXPORT void +e_module_unload (GTypeModule *type_module) +{ +} + +G_MODULE_EXPORT const gchar * +g_module_check_init (GModule *module) +{ + /* FIXME Until mail is split into a module library and a + * reusable shared library, prevent the module from + * being unloaded. Unloading the module resets all + * static variables, which screws up foo_get_type() + * functions among other things. */ + g_module_make_resident (module); + + return NULL; +} diff --git a/plugins/attachment-reminder/Makefile.am b/plugins/attachment-reminder/Makefile.am index edfe538d3a..b3c1799455 100644 --- a/plugins/attachment-reminder/Makefile.am +++ b/plugins/attachment-reminder/Makefile.am @@ -28,7 +28,7 @@ liborg_gnome_evolution_attachment_reminder_la_LIBADD = \ $(top_builddir)/addressbook/gui/contact-list-editor/libecontactlisteditor.la \ $(top_builddir)/e-util/libeutil.la \ $(top_builddir)/widgets/misc/libemiscwidgets.la \ - $(top_builddir)/mail/libevolution-module-mail.la \ + $(top_builddir)/mail/libevolution-mail.la \ $(EVOLUTION_MAIL_LIBS) schemadir = $(GCONF_SCHEMA_FILE_DIR) diff --git a/plugins/audio-inline/Makefile.am b/plugins/audio-inline/Makefile.am index c17876d622..a8f591ec1f 100644 --- a/plugins/audio-inline/Makefile.am +++ b/plugins/audio-inline/Makefile.am @@ -10,9 +10,9 @@ plugin_LTLIBRARIES = liborg-gnome-audio-inline.la liborg_gnome_audio_inline_la_SOURCES = audio-inline.c liborg_gnome_audio_inline_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED) -liborg_gnome_audio_inline_la_LIBADD = \ - $(top_builddir)/mail/libevolution-module-mail.la \ - $(GSTREAMER_LIBS) \ +liborg_gnome_audio_inline_la_LIBADD = \ + $(top_builddir)/mail/libevolution-mail.la \ + $(GSTREAMER_LIBS) \ $(EVOLUTION_MAIL_LIBS) EXTRA_DIST = org-gnome-audio-inline.eplug.xml diff --git a/plugins/bogo-junk-plugin/Makefile.am b/plugins/bogo-junk-plugin/Makefile.am index afa24a0d71..9d51b4d89d 100644 --- a/plugins/bogo-junk-plugin/Makefile.am +++ b/plugins/bogo-junk-plugin/Makefile.am @@ -11,9 +11,9 @@ plugin_LTLIBRARIES = liborg-gnome-bogo-junk-plugin.la liborg_gnome_bogo_junk_plugin_la_SOURCES = bf-junk-filter.c liborg_gnome_bogo_junk_plugin_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED) liborg_gnome_bogo_junk_plugin_la_LIBADD = \ - $(top_builddir)/mail/libevolution-module-mail.la \ - $(top_builddir)/e-util/libeutil.la \ - $(EVOLUTION_MAIL_LIBS) \ + $(top_builddir)/mail/libevolution-mail.la \ + $(top_builddir)/e-util/libeutil.la \ + $(EVOLUTION_MAIL_LIBS) \ $(GNOME_PLATFORM_LIBS) schemadir = $(GCONF_SCHEMA_FILE_DIR) diff --git a/plugins/external-editor/Makefile.am b/plugins/external-editor/Makefile.am index 76234e3533..b5ec612403 100644 --- a/plugins/external-editor/Makefile.am +++ b/plugins/external-editor/Makefile.am @@ -33,7 +33,7 @@ liborg_gnome_external_editor_la_LIBADD = \ $(top_builddir)/shell/libeshell.la \ $(top_builddir)/addressbook/gui/contact-editor/libecontacteditor.la \ $(top_builddir)/addressbook/gui/contact-list-editor/libecontactlisteditor.la \ - $(top_builddir)/mail/libevolution-module-mail.la \ + $(top_builddir)/mail/libevolution-mail.la \ $(EVOLUTION_MAIL_LIBS) \ $(GNOME_PLATFORM_LIBS) diff --git a/plugins/imap-features/Makefile.am b/plugins/imap-features/Makefile.am index cf7dbd79c9..e6b6559c63 100644 --- a/plugins/imap-features/Makefile.am +++ b/plugins/imap-features/Makefile.am @@ -14,10 +14,10 @@ plugin_LTLIBRARIES = liborg-gnome-imap-features.la liborg_gnome_imap_features_la_SOURCES = \ imap-headers.c -liborg_gnome_imap_features_la_LIBADD= \ - $(top_builddir)/e-util/libeutil.la \ - $(top_builddir)/mail/libevolution-module-mail.la \ - $(EVOLUTION_MAIL_LIBS) +liborg_gnome_imap_features_la_LIBADD= \ + $(top_builddir)/e-util/libeutil.la \ + $(top_builddir)/mail/libevolution-mail.la \ + $(EVOLUTION_MAIL_LIBS) liborg_gnome_imap_features_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED) diff --git a/plugins/mail-notification/Makefile.am b/plugins/mail-notification/Makefile.am index 629697f7d1..2055cce572 100644 --- a/plugins/mail-notification/Makefile.am +++ b/plugins/mail-notification/Makefile.am @@ -18,10 +18,10 @@ plugin_LTLIBRARIES = liborg-gnome-mail-notification.la liborg_gnome_mail_notification_la_SOURCES = mail-notification.c liborg_gnome_mail_notification_la_LDFLAGS = \ -module -avoid-version $(NO_UNDEFINED) -liborg_gnome_mail_notification_la_LIBADD = \ - $(LIBNOTIFY_LIBS) \ - $(top_builddir)/e-util/libeutil.la \ - $(top_builddir)/mail/libevolution-module-mail.la \ +liborg_gnome_mail_notification_la_LIBADD = \ + $(LIBNOTIFY_LIBS) \ + $(top_builddir)/e-util/libeutil.la \ + $(top_builddir)/mail/libevolution-mail.la \ $(GNOME_PLATFORM_LIBS) if ENABLE_DBUS diff --git a/plugins/mark-all-read/Makefile.am b/plugins/mark-all-read/Makefile.am index f3db1bdc6c..f1bbbcbb18 100644 --- a/plugins/mark-all-read/Makefile.am +++ b/plugins/mark-all-read/Makefile.am @@ -11,8 +11,8 @@ liborg_gnome_mark_all_read_la_SOURCES = mark-all-read.c liborg_gnome_mark_all_read_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED) liborg_gnome_mark_all_read_la_LIBADD = \ $(top_builddir)/e-util/libeutil.la \ - $(top_builddir)/mail/libevolution-module-mail.la \ - $(top_builddir)/shell/libeshell.la \ + $(top_builddir)/mail/libevolution-mail.la \ + $(top_builddir)/shell/libeshell.la \ $(EVOLUTION_MAIL_LIBS) EXTRA_DIST = org-gnome-mark-all-read.eplug.xml diff --git a/plugins/sa-junk-plugin/Makefile.am b/plugins/sa-junk-plugin/Makefile.am index 7d82ad396d..d7ba3e7d51 100644 --- a/plugins/sa-junk-plugin/Makefile.am +++ b/plugins/sa-junk-plugin/Makefile.am @@ -12,9 +12,9 @@ liborg_gnome_sa_junk_plugin_la_SOURCES = em-junk-filter.c liborg_gnome_sa_junk_plugin_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED) liborg_gnome_sa_junk_plugin_la_LIBADD = \ - $(top_builddir)/mail/libevolution-module-mail.la \ - $(top_builddir)/e-util/libeutil.la \ - $(EVOLUTION_MAIL_LIBS) \ + $(top_builddir)/mail/libevolution-mail.la \ + $(top_builddir)/e-util/libeutil.la \ + $(EVOLUTION_MAIL_LIBS) \ $(GNOME_PLATFORM_LIBS) BUILT_SOURCES = $(plugin_DATA) $(error_DATA) diff --git a/plugins/vcard-inline/Makefile.am b/plugins/vcard-inline/Makefile.am index f3c20d1c59..df143ce9d4 100644 --- a/plugins/vcard-inline/Makefile.am +++ b/plugins/vcard-inline/Makefile.am @@ -11,7 +11,7 @@ plugin_LTLIBRARIES = liborg-gnome-vcard-inline.la liborg_gnome_vcard_inline_la_SOURCES = vcard-inline.c liborg_gnome_vcard_inline_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED) liborg_gnome_vcard_inline_la_LIBADD = \ - $(top_builddir)/mail/libevolution-module-mail.la \ + $(top_builddir)/mail/libevolution-mail.la \ $(top_builddir)/addressbook/util/libeabutil.la \ $(top_builddir)/addressbook/gui/widgets/libeabwidgets.la \ $(top_builddir)/addressbook/gui/merging/libeabbookmerging.la \ diff --git a/po/POTFILES.in b/po/POTFILES.in index 6cc1741ac3..b5d94bc34c 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -2,17 +2,6 @@ # Please keep this list in alphabetic order. addressbook/addressbook.error.xml addressbook/conduit/address-conduit.c -addressbook/gui/component/addressbook-config.c -addressbook/gui/component/apps_evolution_addressbook.schemas.in -addressbook/gui/component/autocompletion-config.c -addressbook/gui/component/e-book-shell-backend.c -addressbook/gui/component/e-book-shell-content.c -addressbook/gui/component/e-book-shell-migrate.c -addressbook/gui/component/e-book-shell-sidebar.c -addressbook/gui/component/e-book-shell-view-actions.c -addressbook/gui/component/e-book-shell-view.c -addressbook/gui/component/eab-composer-util.c -addressbook/gui/component/ldap-config.glade addressbook/gui/contact-editor/contact-editor.glade addressbook/gui/contact-editor/e-contact-editor-fullname.c addressbook/gui/contact-editor/e-contact-editor.c @@ -24,9 +13,6 @@ addressbook/gui/contact-list-editor/e-contact-list-editor.c addressbook/gui/merging/eab-contact-commit-duplicate-detected.glade addressbook/gui/merging/eab-contact-duplicate-detected.glade addressbook/gui/merging/eab-contact-merging.c -addressbook/gui/widgets/a11y/ea-addressbook-view.c -addressbook/gui/widgets/a11y/ea-minicard-view.c -addressbook/gui/widgets/a11y/ea-minicard.c addressbook/gui/widgets/addresstypes.xml addressbook/gui/widgets/e-addressbook-model.c addressbook/gui/widgets/e-addressbook-reflow-adapter.c @@ -37,6 +23,9 @@ addressbook/gui/widgets/e-minicard-label.c addressbook/gui/widgets/e-minicard-view-widget.c addressbook/gui/widgets/e-minicard-view.c addressbook/gui/widgets/e-minicard.c +addressbook/gui/widgets/ea-addressbook-view.c +addressbook/gui/widgets/ea-minicard-view.c +addressbook/gui/widgets/ea-minicard.c addressbook/gui/widgets/eab-contact-display.c addressbook/gui/widgets/eab-gui-util.c addressbook/gui/widgets/gal-view-factory-minicard.c @@ -136,29 +125,6 @@ calendar/gui/print.c calendar/gui/tasktypes.xml calendar/gui/weekday-picker.c calendar/importers/icalendar-importer.c -calendar/module/e-cal-shell-backend.c -calendar/module/e-cal-shell-content.c -calendar/module/e-cal-shell-migrate.c -calendar/module/e-cal-shell-sidebar.c -calendar/module/e-cal-shell-view-actions.c -calendar/module/e-cal-shell-view-memopad.c -calendar/module/e-cal-shell-view-private.c -calendar/module/e-cal-shell-view-taskpad.c -calendar/module/e-cal-shell-view.c -calendar/module/e-memo-shell-backend.c -calendar/module/e-memo-shell-content.c -calendar/module/e-memo-shell-migrate.c -calendar/module/e-memo-shell-sidebar.c -calendar/module/e-memo-shell-view-actions.c -calendar/module/e-memo-shell-view-private.c -calendar/module/e-memo-shell-view.c -calendar/module/e-task-shell-backend.c -calendar/module/e-task-shell-content.c -calendar/module/e-task-shell-migrate.c -calendar/module/e-task-shell-sidebar.c -calendar/module/e-task-shell-view-actions.c -calendar/module/e-task-shell-view-private.c -calendar/module/e-task-shell-view.c calendar/zones.h composer/e-composer-actions.c composer/e-composer-autosave.c @@ -194,7 +160,6 @@ filter/filter.error.xml filter/filter.glade filter/rule-context.c filter/rule-editor.c -mail/e-attachment-handler-mail.c mail/e-mail-attachment-bar.c mail/e-mail-browser.c mail/e-mail-display.c @@ -202,18 +167,11 @@ mail/e-mail-label-dialog.c mail/e-mail-label-list-store.c mail/e-mail-label-manager.c mail/e-mail-label-tree-view.c +mail/e-mail-local.c mail/e-mail-reader-utils.c mail/e-mail-reader.c mail/e-mail-search-bar.c -mail/e-mail-shell-backend.c -mail/e-mail-shell-content.c -mail/e-mail-shell-migrate.c -mail/e-mail-shell-view-actions.c -mail/e-mail-shell-view-private.c -mail/e-mail-shell-view.c -mail/em-account-editor.c -mail/em-account-prefs.c -mail/em-composer-prefs.c +mail/e-mail-store.c mail/em-composer-utils.c mail/em-filter-editor.c mail/em-filter-folder-element.c @@ -229,7 +187,6 @@ mail/em-format-html-display.c mail/em-format-html-print.c mail/em-format-html.c mail/em-junk-hook.c -mail/em-mailer-prefs.c mail/em-popup.c mail/em-subscribe-editor.c mail/em-utils.c @@ -257,6 +214,51 @@ mail/message-list.etspec mail/message-tag-editor.c mail/message-tag-followup.c mail/searchtypes.xml +modules/addressbook/addressbook-config.c +modules/addressbook/apps_evolution_addressbook.schemas.in +modules/addressbook/autocompletion-config.c +modules/addressbook/e-book-shell-backend.c +modules/addressbook/e-book-shell-content.c +modules/addressbook/e-book-shell-migrate.c +modules/addressbook/e-book-shell-sidebar.c +modules/addressbook/e-book-shell-view-actions.c +modules/addressbook/e-book-shell-view.c +modules/addressbook/eab-composer-util.c +modules/addressbook/ldap-config.glade +modules/calendar/e-cal-shell-backend.c +modules/calendar/e-cal-shell-content.c +modules/calendar/e-cal-shell-migrate.c +modules/calendar/e-cal-shell-sidebar.c +modules/calendar/e-cal-shell-view-actions.c +modules/calendar/e-cal-shell-view-memopad.c +modules/calendar/e-cal-shell-view-private.c +modules/calendar/e-cal-shell-view-taskpad.c +modules/calendar/e-cal-shell-view.c +modules/calendar/e-memo-shell-backend.c +modules/calendar/e-memo-shell-content.c +modules/calendar/e-memo-shell-migrate.c +modules/calendar/e-memo-shell-sidebar.c +modules/calendar/e-memo-shell-view-actions.c +modules/calendar/e-memo-shell-view-private.c +modules/calendar/e-memo-shell-view.c +modules/calendar/e-task-shell-backend.c +modules/calendar/e-task-shell-content.c +modules/calendar/e-task-shell-migrate.c +modules/calendar/e-task-shell-sidebar.c +modules/calendar/e-task-shell-view-actions.c +modules/calendar/e-task-shell-view-private.c +modules/calendar/e-task-shell-view.c +modules/mail/e-attachment-handler-mail.c +modules/mail/e-mail-shell-backend.c +modules/mail/e-mail-shell-content.c +modules/mail/e-mail-shell-migrate.c +modules/mail/e-mail-shell-view-actions.c +modules/mail/e-mail-shell-view-private.c +modules/mail/e-mail-shell-view.c +modules/mail/em-account-editor.c +modules/mail/em-account-prefs.c +modules/mail/em-composer-prefs.c +modules/mail/em-mailer-prefs.c plugins/addressbook-file/org-gnome-addressbook-file.eplug.xml plugins/attachment-reminder/apps-evolution-attachment-reminder.schemas.in plugins/attachment-reminder/attachment-reminder.c @@ -464,7 +466,6 @@ widgets/menus/gal-view-instance-save-as-dialog.glade widgets/menus/gal-view-instance.c widgets/menus/gal-view-new-dialog.c widgets/menus/gal-view-new-dialog.glade -widgets/misc/a11y/ea-calendar-item.c widgets/misc/e-account-manager.c widgets/misc/e-account-tree-view.c widgets/misc/e-action-combo-box.c @@ -500,13 +501,7 @@ widgets/misc/e-signature-editor.c widgets/misc/e-signature-manager.c widgets/misc/e-signature-script-dialog.c widgets/misc/e-url-entry.c -widgets/table/a11y/gal-a11y-e-cell-popup.c -widgets/table/a11y/gal-a11y-e-cell-text.c -widgets/table/a11y/gal-a11y-e-cell-toggle.c -widgets/table/a11y/gal-a11y-e-cell-tree.c -widgets/table/a11y/gal-a11y-e-cell.c -widgets/table/a11y/gal-a11y-e-table-click-to-add.c -widgets/table/a11y/gal-a11y-e-table-column-header.c +widgets/misc/ea-calendar-item.c widgets/table/e-cell-combo.c widgets/table/e-cell-date-edit.c widgets/table/e-cell-date.c @@ -533,4 +528,11 @@ widgets/table/e-table.c widgets/table/e-tree-scrolled.c widgets/table/e-tree-selection-model.c widgets/table/e-tree.c +widgets/table/gal-a11y-e-cell-popup.c +widgets/table/gal-a11y-e-cell-text.c +widgets/table/gal-a11y-e-cell-toggle.c +widgets/table/gal-a11y-e-cell-tree.c +widgets/table/gal-a11y-e-cell.c +widgets/table/gal-a11y-e-table-click-to-add.c +widgets/table/gal-a11y-e-table-column-header.c widgets/text/e-text.c diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am index cbbd283fb2..c7123d6977 100644 --- a/widgets/misc/Makefile.am +++ b/widgets/misc/Makefile.am @@ -84,9 +84,9 @@ widgetsinclude_HEADERS = \ e-spinner.h \ e-timeout-activity.h \ e-url-entry.h \ - a11y/ea-calendar-cell.h \ - a11y/ea-calendar-item.h \ - a11y/ea-widgets.h + ea-calendar-cell.h \ + ea-calendar-item.h \ + ea-widgets.h libemiscwidgets_la_SOURCES = \ $(widgetsinclude_HEADERS) \ @@ -145,9 +145,9 @@ libemiscwidgets_la_SOURCES = \ e-signature-tree-view.c \ e-timeout-activity.c \ e-url-entry.c \ - a11y/ea-calendar-cell.c \ - a11y/ea-calendar-item.c \ - a11y/ea-widgets.c + ea-calendar-cell.c \ + ea-calendar-item.c \ + ea-widgets.c libemiscwidgets_la_LDFLAGS = $(NO_UNDEFINED) diff --git a/widgets/misc/a11y/ea-calendar-cell.c b/widgets/misc/a11y/ea-calendar-cell.c deleted file mode 100644 index af9471c5af..0000000000 --- a/widgets/misc/a11y/ea-calendar-cell.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include -#include -#include "ea-calendar-cell.h" -#include "ea-calendar-item.h" -#include "a11y/ea-factory.h" - -/* ECalendarCell */ - -static void e_calendar_cell_class_init (ECalendarCellClass *class); - -EA_FACTORY_GOBJECT (EA_TYPE_CALENDAR_CELL, ea_calendar_cell, ea_calendar_cell_new) - -GType -e_calendar_cell_get_type (void) -{ - static GType type = 0; - - if (!type) { - static GTypeInfo tinfo = { - sizeof (ECalendarCellClass), - (GBaseInitFunc) NULL, /* base init */ - (GBaseFinalizeFunc) NULL, /* base finalize */ - (GClassInitFunc) e_calendar_cell_class_init, /* class init */ - (GClassFinalizeFunc) NULL, /* class finalize */ - NULL, /* class data */ - sizeof (ECalendarCell), /* instance size */ - 0, /* nb preallocs */ - (GInstanceInitFunc) NULL, /* instance init */ - NULL /* value table */ - }; - - type = g_type_register_static (G_TYPE_OBJECT, - "ECalendarCell", &tinfo, 0); - } - - return type; -} - -static void -e_calendar_cell_class_init (ECalendarCellClass *class) -{ - EA_SET_FACTORY (e_calendar_cell_get_type (), ea_calendar_cell); -} - -ECalendarCell * -e_calendar_cell_new (ECalendarItem *calitem, gint row, gint column) -{ - GObject *object; - ECalendarCell *cell; - - g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), NULL); - - object = g_object_new (E_TYPE_CALENDAR_CELL, NULL); - cell = E_CALENDAR_CELL (object); - cell->calitem = calitem; - cell->row = row; - cell->column = column; - -#ifdef ACC_DEBUG - g_print ("EvoAcc: e_calendar_cell created %p\n", (gpointer)cell); -#endif - - return cell; -} - -/* EaCalendarCell */ - -static void ea_calendar_cell_class_init (EaCalendarCellClass *klass); -static void ea_calendar_cell_init (EaCalendarCell *a11y); - -static G_CONST_RETURN gchar * ea_calendar_cell_get_name (AtkObject *accessible); -static G_CONST_RETURN gchar * ea_calendar_cell_get_description (AtkObject *accessible); -static AtkObject * ea_calendar_cell_get_parent (AtkObject *accessible); -static gint ea_calendar_cell_get_index_in_parent (AtkObject *accessible); -static AtkStateSet *ea_calendar_cell_ref_state_set (AtkObject *accessible); - -/* component interface */ -static void atk_component_interface_init (AtkComponentIface *iface); -static void component_interface_get_extents (AtkComponent *component, - gint *x, gint *y, - gint *width, gint *height, - AtkCoordType coord_type); -static gboolean component_interface_grab_focus (AtkComponent *component); - -static gpointer parent_class = NULL; - -#ifdef ACC_DEBUG -static gint n_ea_calendar_cell_created = 0, n_ea_calendar_cell_destroyed = 0; -static void ea_calendar_cell_finalize (GObject *object); -#endif - -GType -ea_calendar_cell_get_type (void) -{ - static GType type = 0; - - if (!type) { - static GTypeInfo tinfo = { - sizeof (EaCalendarCellClass), - (GBaseInitFunc) NULL, /* base init */ - (GBaseFinalizeFunc) NULL, /* base finalize */ - (GClassInitFunc) ea_calendar_cell_class_init, /* class init */ - (GClassFinalizeFunc) NULL, /* class finalize */ - NULL, /* class data */ - sizeof (EaCalendarCell), /* instance size */ - 0, /* nb preallocs */ - (GInstanceInitFunc) ea_calendar_cell_init, /* instance init */ - NULL /* value table */ - }; - - static const GInterfaceInfo atk_component_info = { - (GInterfaceInitFunc) atk_component_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - type = g_type_register_static (ATK_TYPE_GOBJECT_ACCESSIBLE, - "EaCalendarCell", &tinfo, 0); - g_type_add_interface_static (type, ATK_TYPE_COMPONENT, - &atk_component_info); - } - - return type; -} - -static void -ea_calendar_cell_class_init (EaCalendarCellClass *klass) -{ - AtkObjectClass *class = ATK_OBJECT_CLASS (klass); - -#ifdef ACC_DEBUG - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = ea_calendar_cell_finalize; -#endif - - parent_class = g_type_class_peek_parent (klass); - - class->get_name = ea_calendar_cell_get_name; - class->get_description = ea_calendar_cell_get_description; - - class->get_parent = ea_calendar_cell_get_parent; - class->get_index_in_parent = ea_calendar_cell_get_index_in_parent; - class->ref_state_set = ea_calendar_cell_ref_state_set; -} - -static void -ea_calendar_cell_init (EaCalendarCell *a11y) -{ - a11y->state_set = atk_state_set_new (); - atk_state_set_add_state (a11y->state_set, ATK_STATE_TRANSIENT); - atk_state_set_add_state (a11y->state_set, ATK_STATE_ENABLED); - atk_state_set_add_state (a11y->state_set, ATK_STATE_SENSITIVE); - atk_state_set_add_state (a11y->state_set, ATK_STATE_SELECTABLE); - atk_state_set_add_state (a11y->state_set, ATK_STATE_SHOWING); - atk_state_set_add_state (a11y->state_set, ATK_STATE_FOCUSABLE); -} - -AtkObject* -ea_calendar_cell_new (GObject *obj) -{ - gpointer object; - AtkObject *atk_object; - - g_return_val_if_fail (E_IS_CALENDAR_CELL (obj), NULL); - object = g_object_new (EA_TYPE_CALENDAR_CELL, NULL); - atk_object = ATK_OBJECT (object); - atk_object_initialize (atk_object, obj); - atk_object->role = ATK_ROLE_TABLE_CELL; - -#ifdef ACC_DEBUG - ++n_ea_calendar_cell_created; - g_print ("ACC_DEBUG: n_ea_calendar_cell_created = %d\n", - n_ea_calendar_cell_created); -#endif - return atk_object; -} - -#ifdef ACC_DEBUG -static void ea_calendar_cell_finalize (GObject *object) -{ - G_OBJECT_CLASS (parent_class)->finalize (object); - - ++n_ea_calendar_cell_destroyed; - g_print ("ACC_DEBUG: n_ea_calendar_cell_destroyed = %d\n", - n_ea_calendar_cell_destroyed); -} -#endif - -static G_CONST_RETURN gchar * -ea_calendar_cell_get_name (AtkObject *accessible) -{ - GObject *g_obj; - - g_return_val_if_fail (EA_IS_CALENDAR_CELL (accessible), NULL); - - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible)); - if (!g_obj) - /* defunct object*/ - return NULL; - - if (!accessible->name) { - AtkObject *atk_obj; - EaCalendarItem *ea_calitem; - ECalendarCell *cell; - gint day_index; - gint year, month, day; - gchar buffer[128]; - - cell = E_CALENDAR_CELL (g_obj); - atk_obj = ea_calendar_cell_get_parent (accessible); - ea_calitem = EA_CALENDAR_ITEM (atk_obj); - day_index = atk_table_get_index_at (ATK_TABLE (ea_calitem), - cell->row, cell->column); - e_calendar_item_get_date_for_offset (cell->calitem, day_index, - &year, &month, &day); - - g_snprintf (buffer, 128, "%d-%d-%d", year, month + 1, day); - ATK_OBJECT_CLASS (parent_class)->set_name (accessible, buffer); - } - return accessible->name; -} - -static G_CONST_RETURN gchar * -ea_calendar_cell_get_description (AtkObject *accessible) -{ - return ea_calendar_cell_get_name (accessible); -} - -static AtkObject * -ea_calendar_cell_get_parent (AtkObject *accessible) -{ - GObject *g_obj; - ECalendarCell *cell; - ECalendarItem *calitem; - - g_return_val_if_fail (EA_IS_CALENDAR_CELL (accessible), NULL); - - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible)); - if (!g_obj) - /* defunct object*/ - return NULL; - - cell = E_CALENDAR_CELL (g_obj); - calitem = cell->calitem; - return atk_gobject_accessible_for_object (G_OBJECT (calitem)); -} - -static gint -ea_calendar_cell_get_index_in_parent (AtkObject *accessible) -{ - GObject *g_obj; - ECalendarCell *cell; - AtkObject *parent; - - g_return_val_if_fail (EA_IS_CALENDAR_CELL (accessible), -1); - - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible)); - if (!g_obj) - return -1; - cell = E_CALENDAR_CELL (g_obj); - parent = atk_object_get_parent (accessible); - return atk_table_get_index_at (ATK_TABLE (parent), - cell->row, cell->column); -} - -static AtkStateSet * -ea_calendar_cell_ref_state_set (AtkObject *accessible) -{ - EaCalendarCell *atk_cell = EA_CALENDAR_CELL (accessible); - - g_return_val_if_fail (atk_cell->state_set, NULL); - - g_object_ref(atk_cell->state_set); - - return atk_cell->state_set; - -} - -/* Atk Component Interface */ - -static void -atk_component_interface_init (AtkComponentIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->get_extents = component_interface_get_extents; - iface->grab_focus = component_interface_grab_focus; -} - -static void -component_interface_get_extents (AtkComponent *component, - gint *x, gint *y, gint *width, gint *height, - AtkCoordType coord_type) -{ - GObject *g_obj; - AtkObject *atk_obj, *atk_canvas; - ECalendarCell *cell; - ECalendarItem *calitem; - EaCalendarItem *ea_calitem; - gint day_index; - gint year, month, day; - gint canvas_x, canvas_y, canvas_width, canvas_height; - - *x = *y = *width = *height = 0; - - g_return_if_fail (EA_IS_CALENDAR_CELL (component)); - - - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(component)); - if (!g_obj) - /* defunct object*/ - return; - - cell = E_CALENDAR_CELL (g_obj); - calitem = cell->calitem; - atk_obj = atk_gobject_accessible_for_object (G_OBJECT (calitem)); - ea_calitem = EA_CALENDAR_ITEM (atk_obj); - day_index = atk_table_get_index_at (ATK_TABLE (ea_calitem), - cell->row, cell->column); - e_calendar_item_get_date_for_offset (calitem, day_index, - &year, &month, &day); - - if (!e_calendar_item_get_day_extents (calitem, - year, month, day, - x, y, width, height)) - return; - atk_canvas = atk_object_get_parent (ATK_OBJECT (ea_calitem)); - atk_component_get_extents (ATK_COMPONENT (atk_canvas), - &canvas_x, &canvas_y, - &canvas_width, &canvas_height, - coord_type); - *x += canvas_x; - *y += canvas_y; -} - -static gboolean -component_interface_grab_focus (AtkComponent *component) -{ - GObject *g_obj; - GtkWidget *toplevel; - AtkObject *ea_calitem; - ECalendarItem *calitem; - EaCalendarCell *a11y; - gint index; - - a11y = EA_CALENDAR_CELL (component); - ea_calitem = ea_calendar_cell_get_parent (ATK_OBJECT (a11y)); - - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(ea_calitem)); - calitem = E_CALENDAR_ITEM (g_obj); - - index = atk_object_get_index_in_parent (ATK_OBJECT (a11y)); - - atk_selection_clear_selection (ATK_SELECTION (ea_calitem)); - atk_selection_add_selection (ATK_SELECTION (ea_calitem), index); - - gtk_widget_grab_focus (GTK_WIDGET (GNOME_CANVAS_ITEM (calitem)->canvas)); - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (GNOME_CANVAS_ITEM (calitem)->canvas)); - if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel)) - gtk_window_present (GTK_WINDOW (toplevel)); - - return TRUE; - -} diff --git a/widgets/misc/a11y/ea-calendar-cell.h b/widgets/misc/a11y/ea-calendar-cell.h deleted file mode 100644 index fa68fdca55..0000000000 --- a/widgets/misc/a11y/ea-calendar-cell.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EA_CALENDAR_CELL_H__ -#define __EA_CALENDAR_CELL_H__ - -#include -#include "misc/e-calendar-item.h" - -G_BEGIN_DECLS - -#define E_TYPE_CALENDAR_CELL (e_calendar_cell_get_type ()) -#define E_CALENDAR_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_CALENDAR_CELL, ECalendarCell)) -#define E_CALENDAR_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_CALENDAR_CELL, ECalendarCellClass)) -#define E_IS_CALENDAR_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_CALENDAR_CELL)) -#define E_IS_CALENDAR_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_CALENDAR_CELL)) -#define E_CALENDAR_CELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_CALENDAR_CELL, ECalendarCellClass)) - -typedef struct _ECalendarCell ECalendarCell; -typedef struct _ECalendarCellClass ECalendarCellClass; - -struct _ECalendarCell -{ - GObject parent; - ECalendarItem *calitem; - gint row; - gint column; -}; - -GType e_calendar_cell_get_type (void); - -struct _ECalendarCellClass -{ - GObjectClass parent_class; -}; - -ECalendarCell * e_calendar_cell_new (ECalendarItem *calitem, - gint row, gint column); - -#define EA_TYPE_CALENDAR_CELL (ea_calendar_cell_get_type ()) -#define EA_CALENDAR_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_CALENDAR_CELL, EaCalendarCell)) -#define EA_CALENDAR_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_CALENDAR_CELL, EaCalendarCellClass)) -#define EA_IS_CALENDAR_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_CALENDAR_CELL)) -#define EA_IS_CALENDAR_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_CALENDAR_CELL)) -#define EA_CALENDAR_CELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_CALENDAR_CELL, EaCalendarCellClass)) - -typedef struct _EaCalendarCell EaCalendarCell; -typedef struct _EaCalendarCellClass EaCalendarCellClass; - -struct _EaCalendarCell -{ - AtkGObjectAccessible parent; - AtkStateSet *state_set; -}; - -GType ea_calendar_cell_get_type (void); - -struct _EaCalendarCellClass -{ - AtkGObjectAccessibleClass parent_class; -}; - -AtkObject* ea_calendar_cell_new (GObject *gobj); - -G_END_DECLS - -#endif /* __EA_CALENDAR_CELL_H__ */ diff --git a/widgets/misc/a11y/ea-calendar-item.c b/widgets/misc/a11y/ea-calendar-item.c deleted file mode 100644 index 56a01b510b..0000000000 --- a/widgets/misc/a11y/ea-calendar-item.c +++ /dev/null @@ -1,1314 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "ea-calendar-item.h" -#include "ea-calendar-cell.h" -#include "a11y/ea-cell-table.h" - -#define EA_CALENDAR_COLUMN_NUM E_CALENDAR_COLS_PER_MONTH - -/* EaCalendarItem */ -static void ea_calendar_item_class_init (EaCalendarItemClass *klass); -static void ea_calendar_item_finalize (GObject *object); - -static G_CONST_RETURN gchar * ea_calendar_item_get_name (AtkObject *accessible); -static G_CONST_RETURN gchar * ea_calendar_item_get_description (AtkObject *accessible); -static gint ea_calendar_item_get_n_children (AtkObject *accessible); -static AtkObject *ea_calendar_item_ref_child (AtkObject *accessible, gint index); -static AtkStateSet* ea_calendar_item_ref_state_set (AtkObject *accessible); - -/* atk table interface */ -static void atk_table_interface_init (AtkTableIface *iface); -static gint table_interface_get_index_at (AtkTable *table, - gint row, - gint column); -static gint table_interface_get_column_at_index (AtkTable *table, - gint index); -static gint table_interface_get_row_at_index (AtkTable *table, - gint index); -static AtkObject* table_interface_ref_at (AtkTable *table, - gint row, - gint column); -static gint table_interface_get_n_rows (AtkTable *table); -static gint table_interface_get_n_columns (AtkTable *table); -static gint table_interface_get_column_extent_at (AtkTable *table, - gint row, - gint column); -static gint table_interface_get_row_extent_at (AtkTable *table, - gint row, - gint column); - -static gboolean table_interface_is_row_selected (AtkTable *table, - gint row); -static gboolean table_interface_is_column_selected (AtkTable *table, - gint row); -static gboolean table_interface_is_selected (AtkTable *table, - gint row, - gint column); -static gint table_interface_get_selected_rows (AtkTable *table, - gint **rows_selected); -static gint table_interface_get_selected_columns (AtkTable *table, - gint **columns_selected); -static gboolean table_interface_add_row_selection (AtkTable *table, gint row); -static gboolean table_interface_remove_row_selection (AtkTable *table, - gint row); -static gboolean table_interface_add_column_selection (AtkTable *table, - gint column); -static gboolean table_interface_remove_column_selection (AtkTable *table, - gint column); -static AtkObject* table_interface_get_row_header (AtkTable *table, gint row); -static AtkObject* table_interface_get_column_header (AtkTable *table, - gint in_col); -static AtkObject* table_interface_get_caption (AtkTable *table); - -static G_CONST_RETURN gchar * -table_interface_get_column_description (AtkTable *table, gint in_col); - -static G_CONST_RETURN gchar * -table_interface_get_row_description (AtkTable *table, gint row); - -static AtkObject* table_interface_get_summary (AtkTable *table); - -/* atk selection interface */ -static void atk_selection_interface_init (AtkSelectionIface *iface); -static gboolean selection_interface_add_selection (AtkSelection *selection, - gint i); -static gboolean selection_interface_clear_selection (AtkSelection *selection); -static AtkObject* selection_interface_ref_selection (AtkSelection *selection, - gint i); -static gint selection_interface_get_selection_count (AtkSelection *selection); -static gboolean selection_interface_is_child_selected (AtkSelection *selection, - gint i); - -/* callbacks */ -static void selection_preview_change_cb (ECalendarItem *calitem); -static void date_range_changed_cb (ECalendarItem *calitem); - -/* helpers */ -static EaCellTable *ea_calendar_item_get_cell_data (EaCalendarItem *ea_calitem); -static void ea_calendar_item_destory_cell_data (EaCalendarItem *ea_calitem); -static gboolean ea_calendar_item_get_column_label (EaCalendarItem *ea_calitem, - gint column, - gchar *buffer, - gint buffer_size); -static gboolean ea_calendar_item_get_row_label (EaCalendarItem *ea_calitem, - gint row, - gchar *buffer, - gint buffer_size); -static gboolean e_calendar_item_get_offset_for_date (ECalendarItem *calitem, - gint year, gint month, gint day, - gint *offset); -static void ea_calendar_set_focus_object (EaCalendarItem *ea_calitem, - AtkObject *item_cell); - -#ifdef ACC_DEBUG -static gint n_ea_calendar_item_created = 0; -static gint n_ea_calendar_item_destroyed = 0; -#endif - -static gpointer parent_class = NULL; - -GType -ea_calendar_item_get_type (void) -{ - static GType type = 0; - AtkObjectFactory *factory; - GTypeQuery query; - GType derived_atk_type; - - if (!type) { - static GTypeInfo tinfo = { - sizeof (EaCalendarItemClass), - (GBaseInitFunc) NULL, /* base init */ - (GBaseFinalizeFunc) NULL, /* base finalize */ - (GClassInitFunc) ea_calendar_item_class_init, /* class init */ - (GClassFinalizeFunc) NULL, /* class finalize */ - NULL, /* class data */ - sizeof (EaCalendarItem), /* instance size */ - 0, /* nb preallocs */ - (GInstanceInitFunc) NULL, /* instance init */ - NULL /* value table */ - }; - - static const GInterfaceInfo atk_table_info = { - (GInterfaceInitFunc) atk_table_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - static const GInterfaceInfo atk_selection_info = { - (GInterfaceInitFunc) atk_selection_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - /* - * Figure out the size of the class and instance - * we are run-time deriving from (GailCanvasItem, in this case) - */ - - factory = atk_registry_get_factory (atk_get_default_registry (), - GNOME_TYPE_CANVAS_ITEM); - derived_atk_type = atk_object_factory_get_accessible_type (factory); - g_type_query (derived_atk_type, &query); - - tinfo.class_size = query.class_size; - tinfo.instance_size = query.instance_size; - - type = g_type_register_static (derived_atk_type, - "EaCalendarItem", &tinfo, 0); - g_type_add_interface_static (type, ATK_TYPE_TABLE, - &atk_table_info); - g_type_add_interface_static (type, ATK_TYPE_SELECTION, - &atk_selection_info); - } - - return type; -} - -static void -ea_calendar_item_class_init (EaCalendarItemClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - AtkObjectClass *class = ATK_OBJECT_CLASS (klass); - - gobject_class->finalize = ea_calendar_item_finalize; - parent_class = g_type_class_peek_parent (klass); - - class->get_name = ea_calendar_item_get_name; - class->get_description = ea_calendar_item_get_description; - class->ref_state_set = ea_calendar_item_ref_state_set; - - class->get_n_children = ea_calendar_item_get_n_children; - class->ref_child = ea_calendar_item_ref_child; -} - -AtkObject* -ea_calendar_item_new (GObject *obj) -{ - gpointer object; - AtkObject *atk_object; - AtkObject *item_cell; - - g_return_val_if_fail (E_IS_CALENDAR_ITEM (obj), NULL); - object = g_object_new (EA_TYPE_CALENDAR_ITEM, NULL); - atk_object = ATK_OBJECT (object); - atk_object_initialize (atk_object, obj); - atk_object->role = ATK_ROLE_CALENDAR; - - item_cell = atk_selection_ref_selection (ATK_SELECTION (atk_object), - 0); - if (item_cell) - ea_calendar_set_focus_object (EA_CALENDAR_ITEM (atk_object), item_cell); - -#ifdef ACC_DEBUG - ++n_ea_calendar_item_created; - g_print ("ACC_DEBUG: n_ea_calendar_item_created = %d\n", - n_ea_calendar_item_created); -#endif - /* connect signal handlers */ - g_signal_connect (obj, "selection_preview_changed", - G_CALLBACK (selection_preview_change_cb), - atk_object); - g_signal_connect (obj, "date_range_changed", - G_CALLBACK (date_range_changed_cb), - atk_object); - - return atk_object; -} - -static void -ea_calendar_item_finalize (GObject *object) -{ - EaCalendarItem *ea_calitem; - - g_return_if_fail (EA_IS_CALENDAR_ITEM (object)); - - ea_calitem = EA_CALENDAR_ITEM (object); - - /* Free the allocated cell data */ - ea_calendar_item_destory_cell_data (ea_calitem); - - G_OBJECT_CLASS (parent_class)->finalize (object); -#ifdef ACC_DEBUG - ++n_ea_calendar_item_destroyed; - printf ("ACC_DEBUG: n_ea_calendar_item_destroyed = %d\n", - n_ea_calendar_item_destroyed); -#endif -} - -static G_CONST_RETURN gchar * -ea_calendar_item_get_name (AtkObject *accessible) -{ - GObject *g_obj; - ECalendarItem *calitem; - gint start_year, start_month, start_day; - gint end_year, end_month, end_day; - gchar *name_str = NULL; - gchar buffer_start[128] = ""; - gchar buffer_end[128] = ""; - struct tm day_start = { 0 }; - struct tm day_end = { 0 }; - - g_return_val_if_fail (EA_IS_CALENDAR_ITEM (accessible), NULL); - - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible)); - if (!g_obj) - return NULL; - g_return_val_if_fail (E_IS_CALENDAR_ITEM (g_obj), NULL); - - calitem = E_CALENDAR_ITEM (g_obj); - if (e_calendar_item_get_date_range (calitem, - &start_year, &start_month, &start_day, - &end_year, &end_month, &end_day)) { - - day_start.tm_year = start_year - 1900; - day_start.tm_mon = start_month; - day_start.tm_mday = start_day; - day_start.tm_isdst = -1; - e_utf8_strftime (buffer_start, sizeof (buffer_start), _("%d %B %Y"), &day_start); - - day_end.tm_year = end_year - 1900; - day_end.tm_mon = end_month; - day_end.tm_mday = end_day; - day_end.tm_isdst = -1; - e_utf8_strftime (buffer_end, sizeof (buffer_end), _("%d %B %Y"), &day_end); - - name_str = g_strdup_printf (_("Calendar: from %s to %s"), buffer_start, buffer_end); - } - -#if 0 - if (e_calendar_item_get_selection (calitem, &select_start, &select_end)) { - GDate select_start, select_end; - gint year1, year2, month1, month2, day1, day2; - - year1 = g_date_get_year (&select_start); - month1 = g_date_get_month (&select_start); - day1 = g_date_get_day (&select_start); - - year2 = g_date_get_year (&select_end); - month2 = g_date_get_month (&select_end); - day2 = g_date_get_day (&select_end); - - sprintf (new_name + strlen (new_name), - " : current selection: from %d-%d-%d to %d-%d-%d.", - year1, month1, day1, - year2, month2, day2); - } -#endif - - ATK_OBJECT_CLASS (parent_class)->set_name (accessible, name_str); - g_free (name_str); - - return accessible->name; -} - -static G_CONST_RETURN gchar * -ea_calendar_item_get_description (AtkObject *accessible) -{ - if (accessible->description) - return accessible->description; - - return _("evolution calendar item"); -} - -static AtkStateSet* -ea_calendar_item_ref_state_set (AtkObject *accessible) -{ - AtkStateSet *state_set; - GObject *g_obj; - - state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (accessible); - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible)); - if (!g_obj) - return state_set; - - atk_state_set_add_state (state_set, ATK_STATE_ENABLED); - atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE); - - return state_set; -} - -static gint -ea_calendar_item_get_n_children (AtkObject *accessible) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - ECalendarItem *calitem; - gint n_children = 0; - gint start_year, start_month, start_day; - gint end_year, end_month, end_day; - GDate *start_date, *end_date; - - g_return_val_if_fail (EA_IS_CALENDAR_ITEM (accessible), -1); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - calitem = E_CALENDAR_ITEM (g_obj); - if (!e_calendar_item_get_date_range (calitem, &start_year, - &start_month, &start_day, - &end_year, &end_month, - &end_day)) - return 0; - - start_date = g_date_new_dmy (start_day, start_month + 1, start_year); - end_date = g_date_new_dmy (end_day, end_month + 1, end_year); - - n_children = g_date_days_between (start_date, end_date) + 1; - g_free (start_date); - g_free (end_date); - return n_children; -} - -static AtkObject * -ea_calendar_item_ref_child (AtkObject *accessible, gint index) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - ECalendarItem *calitem; - gint n_children; - ECalendarCell *cell; - EaCellTable *cell_data; - EaCalendarItem *ea_calitem; - - g_return_val_if_fail (EA_IS_CALENDAR_ITEM (accessible), NULL); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return NULL; - - calitem = E_CALENDAR_ITEM (g_obj); - - n_children = ea_calendar_item_get_n_children (accessible); - if (index < 0 || index >= n_children) - return NULL; - - ea_calitem = EA_CALENDAR_ITEM (accessible); - cell_data = ea_calendar_item_get_cell_data (ea_calitem); - if (!cell_data) - return NULL; - - cell = ea_cell_table_get_cell_at_index (cell_data, index); - if (!cell) { - cell = e_calendar_cell_new (calitem, - index / EA_CALENDAR_COLUMN_NUM, - index % EA_CALENDAR_COLUMN_NUM); - ea_cell_table_set_cell_at_index (cell_data, index, cell); - g_object_unref (cell); - } - -#ifdef ACC_DEBUG - g_print ("AccDebug: ea_calendar_item children[%d]=%p\n", index, - (gpointer)cell); -#endif - return g_object_ref (atk_gobject_accessible_for_object (G_OBJECT(cell))); -} - -/* atk table interface */ - -static void -atk_table_interface_init (AtkTableIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->ref_at = table_interface_ref_at; - - iface->get_n_rows = table_interface_get_n_rows; - iface->get_n_columns = table_interface_get_n_columns; - iface->get_index_at = table_interface_get_index_at; - iface->get_column_at_index = table_interface_get_column_at_index; - iface->get_row_at_index = table_interface_get_row_at_index; - iface->get_column_extent_at = table_interface_get_column_extent_at; - iface->get_row_extent_at = table_interface_get_row_extent_at; - - iface->is_selected = table_interface_is_selected; - iface->get_selected_rows = table_interface_get_selected_rows; - iface->get_selected_columns = table_interface_get_selected_columns; - iface->is_row_selected = table_interface_is_row_selected; - iface->is_column_selected = table_interface_is_column_selected; - iface->add_row_selection = table_interface_add_row_selection; - iface->remove_row_selection = table_interface_remove_row_selection; - iface->add_column_selection = table_interface_add_column_selection; - iface->remove_column_selection = table_interface_remove_column_selection; - - iface->get_row_header = table_interface_get_row_header; - iface->get_column_header = table_interface_get_column_header; - iface->get_caption = table_interface_get_caption; - iface->get_summary = table_interface_get_summary; - iface->get_row_description = table_interface_get_row_description; - iface->get_column_description = table_interface_get_column_description; -} - -static AtkObject* -table_interface_ref_at (AtkTable *table, - gint row, - gint column) -{ - gint index; - - EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); - index = EA_CALENDAR_COLUMN_NUM * row + column; - return ea_calendar_item_ref_child (ATK_OBJECT (ea_calitem), index); -} - -static gint -table_interface_get_n_rows (AtkTable *table) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); - gint n_children; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - n_children = ea_calendar_item_get_n_children (ATK_OBJECT (ea_calitem)); - return (n_children - 1) / EA_CALENDAR_COLUMN_NUM + 1; -} - -static gint -table_interface_get_n_columns (AtkTable *table) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - return EA_CALENDAR_COLUMN_NUM; -} - -static gint -table_interface_get_index_at (AtkTable *table, - gint row, - gint column) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - return row * EA_CALENDAR_COLUMN_NUM + column; -} - -static gint -table_interface_get_column_at_index (AtkTable *table, - gint index) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); - gint n_children; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - n_children = ea_calendar_item_get_n_children (ATK_OBJECT (ea_calitem)); - if (index >= 0 && index < n_children) - return index % EA_CALENDAR_COLUMN_NUM; - return -1; -} - -static gint -table_interface_get_row_at_index (AtkTable *table, - gint index) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); - gint n_children; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return -1; - - n_children = ea_calendar_item_get_n_children (ATK_OBJECT (ea_calitem)); - if (index >= 0 && index < n_children) - return index / EA_CALENDAR_COLUMN_NUM; - return -1; -} - -static gint -table_interface_get_column_extent_at (AtkTable *table, - gint row, - gint column) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - ECalendarItem *calitem; - EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - calitem = E_CALENDAR_ITEM (g_obj); - return calitem->cell_width; -} - -static gint -table_interface_get_row_extent_at (AtkTable *table, - gint row, gint column) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - ECalendarItem *calitem; - EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - calitem = E_CALENDAR_ITEM (g_obj); - return calitem->cell_height; -} - -/* any day in the row is selected, the row is selected */ -static gboolean -table_interface_is_row_selected (AtkTable *table, - gint row) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - gint n_rows; - ECalendarItem *calitem; - gint row_index_start, row_index_end; - gint sel_index_start, sel_index_end; - - GDate start_date, end_date; - - g_return_val_if_fail (EA_IS_CALENDAR_ITEM (table), FALSE); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (table); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - n_rows = table_interface_get_n_rows (table); - if (row < 0 || row >= n_rows) - return FALSE; - - row_index_start = row * EA_CALENDAR_COLUMN_NUM; - row_index_end = row_index_start + EA_CALENDAR_COLUMN_NUM - 1; - - calitem = E_CALENDAR_ITEM (g_obj); - if (!e_calendar_item_get_selection (calitem, &start_date, &end_date)) - return FALSE; - - e_calendar_item_get_offset_for_date (calitem, - g_date_get_year (&start_date), - g_date_get_month (&start_date), - g_date_get_day (&start_date), - &sel_index_start); - e_calendar_item_get_offset_for_date (calitem, - g_date_get_year (&end_date), - g_date_get_month (&end_date), - g_date_get_day (&end_date), - &sel_index_end); - - if ((sel_index_start < row_index_start && - sel_index_end >= row_index_start) || - (sel_index_start >= row_index_start && - sel_index_start <= row_index_end)) - return TRUE; - return FALSE; -} - -static gboolean -table_interface_is_selected (AtkTable *table, - gint row, - gint column) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - gint n_rows, n_columns; - ECalendarItem *calitem; - gint index; - gint sel_index_start, sel_index_end; - - GDate start_date, end_date; - - g_return_val_if_fail (EA_IS_CALENDAR_ITEM (table), FALSE); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (table); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - n_rows = table_interface_get_n_rows (table); - if (row < 0 || row >= n_rows) - return FALSE; - n_columns = table_interface_get_n_columns (table); - if (column < 0 || column >= n_columns) - return FALSE; - - index = table_interface_get_index_at (table, row, column); - - calitem = E_CALENDAR_ITEM (g_obj); - if (!e_calendar_item_get_selection (calitem, &start_date, &end_date)) - return FALSE; - - e_calendar_item_get_offset_for_date (calitem, - g_date_get_year (&start_date), - g_date_get_month (&start_date), - g_date_get_day (&start_date), - &sel_index_start); - e_calendar_item_get_offset_for_date (calitem, - g_date_get_year (&end_date), - g_date_get_month (&end_date), - g_date_get_day (&end_date), &sel_index_end); - - if (sel_index_start <= index && sel_index_end >= index) - return TRUE; - return FALSE; -} - -static gboolean -table_interface_is_column_selected (AtkTable *table, - gint column) -{ - return FALSE; -} - -static gint -table_interface_get_selected_rows (AtkTable *table, - gint **rows_selected) -{ - *rows_selected = NULL; - return -1; -} - -static gint -table_interface_get_selected_columns (AtkTable *table, - gint **columns_selected) -{ - *columns_selected = NULL; - return -1; -} - -static gboolean -table_interface_add_row_selection (AtkTable *table, - gint row) -{ - return FALSE; -} - -static gboolean -table_interface_remove_row_selection (AtkTable *table, - gint row) -{ - return FALSE; -} - -static gboolean -table_interface_add_column_selection (AtkTable *table, - gint column) -{ - return FALSE; -} - -static gboolean -table_interface_remove_column_selection (AtkTable *table, - gint column) -{ - /* FIXME: NOT IMPLEMENTED */ - return FALSE; -} - -static AtkObject* -table_interface_get_row_header (AtkTable *table, - gint row) -{ - /* FIXME: NOT IMPLEMENTED */ - return NULL; -} - -static AtkObject* -table_interface_get_column_header (AtkTable *table, - gint in_col) -{ - /* FIXME: NOT IMPLEMENTED */ - return NULL; -} - -static AtkObject* -table_interface_get_caption (AtkTable *table) -{ - /* FIXME: NOT IMPLEMENTED */ - return NULL; -} - -static G_CONST_RETURN gchar * -table_interface_get_column_description (AtkTable *table, gint in_col) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); - const gchar *description = NULL; - EaCellTable *cell_data; - gint n_columns; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return NULL; - - n_columns = table_interface_get_n_columns (table); - if (in_col < 0 || in_col >= n_columns) - return NULL; - cell_data = ea_calendar_item_get_cell_data (ea_calitem); - if (!cell_data) - return NULL; - - description = ea_cell_table_get_column_label (cell_data, in_col); - if (!description) { - gchar buffer[128] = "column description"; - ea_calendar_item_get_column_label (ea_calitem, in_col, - buffer, sizeof (buffer)); - ea_cell_table_set_column_label (cell_data, in_col, buffer); - description = ea_cell_table_get_column_label (cell_data, - in_col); - } - return description; -} - -static G_CONST_RETURN gchar * -table_interface_get_row_description (AtkTable *table, gint row) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); - const gchar *description = NULL; - EaCellTable *cell_data; - gint n_rows; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return NULL; - - n_rows = table_interface_get_n_rows (table); - if (row < 0 || row >= n_rows) - return NULL; - cell_data = ea_calendar_item_get_cell_data (ea_calitem); - if (!cell_data) - return NULL; - - description = ea_cell_table_get_row_label (cell_data, row); - if (!description) { - gchar buffer[128] = "row description"; - ea_calendar_item_get_row_label (ea_calitem, row, - buffer, sizeof (buffer)); - ea_cell_table_set_row_label (cell_data, row, buffer); - description = ea_cell_table_get_row_label (cell_data, - row); - } - return description; -} - -static AtkObject* -table_interface_get_summary (AtkTable *table) -{ - /* FIXME: NOT IMPLEMENTED */ - return NULL; -} - -/* atkselection interface */ - -static void -atk_selection_interface_init (AtkSelectionIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->add_selection = selection_interface_add_selection; - iface->clear_selection = selection_interface_clear_selection; - iface->ref_selection = selection_interface_ref_selection; - iface->get_selection_count = selection_interface_get_selection_count; - iface->is_child_selected = selection_interface_is_child_selected; -} - -static gboolean -selection_interface_add_selection (AtkSelection *selection, gint index) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - ECalendarItem *calitem; - EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection); - gint year, month, day; - GDate start_date, end_date; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - calitem = E_CALENDAR_ITEM (g_obj); - if (!e_calendar_item_get_date_for_offset (calitem, index, - &year, &month, &day)) - return FALSE; - - /* FIXME: not support mulit-selection */ - g_date_set_dmy (&start_date, day, month + 1, year); - end_date = start_date; - e_calendar_item_set_selection (calitem, &start_date, &end_date); - return TRUE; -} - -static gboolean -selection_interface_clear_selection (AtkSelection *selection) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - ECalendarItem *calitem; - EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - calitem = E_CALENDAR_ITEM (g_obj); - e_calendar_item_set_selection (calitem, NULL, NULL); - - return TRUE; -} - -static AtkObject* -selection_interface_ref_selection (AtkSelection *selection, gint i) -{ - GObject *g_obj; - ECalendarItem *calitem; - EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection); - gint count, sel_offset; - GDate start_date, end_date; - - count = selection_interface_get_selection_count (selection); - if (i < 0 || i >= count) - return NULL; - - g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (ea_calitem)); - - calitem = E_CALENDAR_ITEM (g_obj); - if (!e_calendar_item_get_selection (calitem, &start_date, &end_date)) - return NULL; - if (!e_calendar_item_get_offset_for_date (calitem, - g_date_get_year (&start_date), - g_date_get_month (&start_date) - 1, - g_date_get_day (&start_date), - &sel_offset)) - return NULL; - - return ea_calendar_item_ref_child (ATK_OBJECT (selection), sel_offset + i); -} - -static gint -selection_interface_get_selection_count (AtkSelection *selection) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - ECalendarItem *calitem; - EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection); - GDate start_date, end_date; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return 0; - - calitem = E_CALENDAR_ITEM (g_obj); - if (e_calendar_item_get_selection (calitem, &start_date, &end_date)) - return g_date_days_between (&start_date, &end_date) + 1; - else - return 0; -} - -static gboolean -selection_interface_is_child_selected (AtkSelection *selection, gint index) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection); - gint row, column, n_children; - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - n_children = atk_object_get_n_accessible_children (ATK_OBJECT (selection)); - if (index < 0 || index >= n_children) - return FALSE; - - row = index / EA_CALENDAR_COLUMN_NUM; - column = index % EA_CALENDAR_COLUMN_NUM; - - return table_interface_is_selected (ATK_TABLE (selection), row, column); -} - -/* callbacks */ - -static void -selection_preview_change_cb (ECalendarItem *calitem) -{ - AtkObject *atk_obj; - AtkObject *item_cell; - - g_return_if_fail (E_IS_CALENDAR_ITEM (calitem)); - atk_obj = atk_gobject_accessible_for_object (G_OBJECT (calitem)); - ea_calendar_item_destory_cell_data (EA_CALENDAR_ITEM (atk_obj)); - - /* only deal with the first selected child, for now */ - item_cell = atk_selection_ref_selection (ATK_SELECTION (atk_obj), - 0); - - if (item_cell) - ea_calendar_set_focus_object (EA_CALENDAR_ITEM (atk_obj), item_cell); - - g_signal_emit_by_name (atk_obj, - "active-descendant-changed", - item_cell); - g_signal_emit_by_name (atk_obj, "selection_changed"); -} - -static void -date_range_changed_cb (ECalendarItem *calitem) -{ - AtkObject *atk_obj; - AtkObject *item_cell; - - g_return_if_fail (E_IS_CALENDAR_ITEM (calitem)); - atk_obj = atk_gobject_accessible_for_object (G_OBJECT (calitem)); - ea_calendar_item_destory_cell_data (EA_CALENDAR_ITEM (atk_obj)); - - item_cell = atk_selection_ref_selection (ATK_SELECTION (atk_obj), - 0); - if (item_cell) - ea_calendar_set_focus_object (EA_CALENDAR_ITEM (atk_obj), item_cell); - - g_signal_emit_by_name (atk_obj, "model_changed"); -} - -/* helpers */ - -static EaCellTable * -ea_calendar_item_get_cell_data (EaCalendarItem *ea_calitem) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - EaCellTable *cell_data; - - g_return_val_if_fail (ea_calitem, NULL); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return NULL; - - cell_data = g_object_get_data (G_OBJECT(ea_calitem), - "ea-calendar-cell-table"); - - if (!cell_data) { - gint n_cells = ea_calendar_item_get_n_children (ATK_OBJECT(ea_calitem)); - cell_data = ea_cell_table_create (n_cells/EA_CALENDAR_COLUMN_NUM, - EA_CALENDAR_COLUMN_NUM, - FALSE); - g_object_set_data (G_OBJECT(ea_calitem), - "ea-calendar-cell-table", cell_data); - } - return cell_data; -} - -static void -ea_calendar_item_destory_cell_data (EaCalendarItem *ea_calitem) -{ - EaCellTable *cell_data; - - g_return_if_fail (ea_calitem); - - cell_data = g_object_get_data (G_OBJECT(ea_calitem), - "ea-calendar-cell-table"); - if (cell_data) { - g_object_set_data (G_OBJECT(ea_calitem), - "ea-calendar-cell-table", NULL); - ea_cell_table_destroy (cell_data); - } -} - -static gboolean -ea_calendar_item_get_row_label (EaCalendarItem *ea_calitem, gint row, - gchar *buffer, gint buffer_size) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - ECalendarItem *calitem; - gint index, week_num; - gint year, month, day; - - g_return_val_if_fail (ea_calitem, FALSE); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - calitem = E_CALENDAR_ITEM (g_obj); - - index = atk_table_get_index_at (ATK_TABLE (ea_calitem), row, 0); - if (!e_calendar_item_get_date_for_offset (calitem, index, - &year, &month, &day)) - return FALSE; - - week_num = e_calendar_item_get_week_number (calitem, - day, month, year); - - g_snprintf (buffer, buffer_size, "week number : %d", week_num); - return TRUE; -} - -static gboolean -ea_calendar_item_get_column_label (EaCalendarItem *ea_calitem, gint column, - gchar *buffer, gint buffer_size) -{ - AtkGObjectAccessible *atk_gobj; - GObject *g_obj; - ECalendarItem *calitem; - const gchar *abbr_name; - - g_return_val_if_fail (ea_calitem, FALSE); - - atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); - g_obj = atk_gobject_accessible_get_object (atk_gobj); - if (!g_obj) - return FALSE; - - /* Columns are 0 = Monday ... 6 = Sunday */ - calitem = E_CALENDAR_ITEM (g_obj); - abbr_name = e_get_weekday_name (column + 1, TRUE); - g_strlcpy (buffer, abbr_name, buffer_size); - - return TRUE; -} - -/* the coordinate the e-calendar canvas coord */ -gboolean -e_calendar_item_get_day_extents (ECalendarItem *calitem, - gint year, gint month, gint date, - gint *x, gint *y, - gint *width, gint *height) -{ - GnomeCanvasItem *item; - GtkWidget *widget; - GtkStyle *style; - PangoFontDescription *font_desc; - PangoContext *pango_context; - PangoFontMetrics *font_metrics; - gint char_height, xthickness, ythickness, text_y; - gint new_year, new_month, num_months, months_offset; - gint month_x, month_y, month_cell_x, month_cell_y; - gint month_row, month_col; - gint day_row, day_col; - gint days_from_week_start; - - g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), FALSE); - - item = GNOME_CANVAS_ITEM (calitem); - widget = GTK_WIDGET (item->canvas); - style = widget->style; - - /* Set up Pango prerequisites */ - font_desc = calitem->font_desc; - if (!font_desc) - font_desc = style->font_desc; - pango_context = gtk_widget_get_pango_context (widget); - font_metrics = pango_context_get_metrics (pango_context, font_desc, - pango_context_get_language (pango_context)); - - char_height = - PANGO_PIXELS (pango_font_metrics_get_ascent (font_metrics)) + - PANGO_PIXELS (pango_font_metrics_get_descent (font_metrics)); - - xthickness = style->xthickness; - ythickness = style->ythickness; - - new_year = year; - new_month = month; - e_calendar_item_normalize_date (calitem, &new_year, &new_month); - num_months = calitem->rows * calitem->cols; - months_offset = (new_year - calitem->year) * 12 - + new_month - calitem->month; - - if (months_offset > num_months || months_offset < 0) - return FALSE; - - month_row = months_offset / calitem->cols; - month_col = months_offset % calitem->cols; - - month_x = item->x1 + xthickness + calitem->x_offset - + month_col * calitem->month_width; - month_y = item->y1 + ythickness + month_row * calitem->month_height; - - month_cell_x = month_x + E_CALENDAR_ITEM_XPAD_BEFORE_WEEK_NUMBERS - + calitem->month_lpad + E_CALENDAR_ITEM_XPAD_BEFORE_CELLS; - text_y = month_y + ythickness * 2 - + E_CALENDAR_ITEM_YPAD_ABOVE_MONTH_NAME - + char_height + E_CALENDAR_ITEM_YPAD_BELOW_MONTH_NAME - + E_CALENDAR_ITEM_YPAD_ABOVE_DAY_LETTERS + calitem->month_tpad; - - month_cell_y = text_y + char_height - + E_CALENDAR_ITEM_YPAD_BELOW_DAY_LETTERS + 1 - + E_CALENDAR_ITEM_YPAD_ABOVE_CELLS; - - days_from_week_start = - e_calendar_item_get_n_days_from_week_start (calitem, new_year, - new_month); - day_row = (date + days_from_week_start - 1) / EA_CALENDAR_COLUMN_NUM; - day_col = (date + days_from_week_start - 1) % EA_CALENDAR_COLUMN_NUM; - - *x = month_cell_x + day_col * calitem->cell_width; - *y = month_cell_y + day_row * calitem->cell_height; - *width = calitem->cell_width; - *height = calitem->cell_height; - - return TRUE; -} - -/* month is from 0 to 11 */ -gboolean -e_calendar_item_get_date_for_offset (ECalendarItem *calitem, gint day_offset, - gint *year, gint *month, gint *day) -{ - gint start_year, start_month, start_day; - gint end_year, end_month, end_day; - GDate *start_date; - - g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), FALSE); - - if (!e_calendar_item_get_date_range (calitem, &start_year, - &start_month, &start_day, - &end_year, &end_month, - &end_day)) - return FALSE; - - start_date = g_date_new_dmy (start_day, start_month + 1, start_year); - - g_date_add_days (start_date, day_offset); - - *year = g_date_get_year (start_date); - *month = g_date_get_month (start_date) - 1; - *day = g_date_get_day (start_date); - - return TRUE; -} - -/* the arg month is from 0 to 11 */ -static gboolean -e_calendar_item_get_offset_for_date (ECalendarItem *calitem, - gint year, gint month, gint day, - gint *offset) -{ - gint start_year, start_month, start_day; - gint end_year, end_month, end_day; - GDate *start_date, *end_date; - - *offset = 0; - g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), FALSE); - - if (!e_calendar_item_get_date_range (calitem, &start_year, - &start_month, &start_day, - &end_year, &end_month, - &end_day)) - return FALSE; - - start_date = g_date_new_dmy (start_day, start_month + 1, start_year); - end_date = g_date_new_dmy (day, month + 1, year); - - *offset = g_date_days_between (start_date, end_date); - g_free (start_date); - g_free (end_date); - - return TRUE; -} - -gint -e_calendar_item_get_n_days_from_week_start (ECalendarItem *calitem, - gint year, gint month) -{ - struct tm tmp_tm; - gint start_weekday, days_from_week_start; - - memset (&tmp_tm, 0, sizeof (tmp_tm)); - tmp_tm.tm_year = year - 1900; - tmp_tm.tm_mon = month; - tmp_tm.tm_mday = 1; - tmp_tm.tm_isdst = -1; - mktime (&tmp_tm); - start_weekday = (tmp_tm.tm_wday + 6) % 7; /* 0 to 6 */ - days_from_week_start = (start_weekday + 7 - calitem->week_start_day) - % 7; - return days_from_week_start; -} - -static void -ea_calendar_set_focus_object (EaCalendarItem *ea_calitem, AtkObject *item_cell) -{ - AtkStateSet *state_set, *old_state_set; - AtkObject *old_cell; - - old_cell = (AtkObject *)g_object_get_data (G_OBJECT(ea_calitem), "gail-focus-object"); - if (old_cell && EA_IS_CALENDAR_CELL (old_cell)) { - old_state_set = atk_object_ref_state_set (old_cell); - atk_state_set_remove_state (old_state_set, ATK_STATE_FOCUSED); - g_object_unref (old_state_set); - } - if (old_cell) - g_object_unref (old_cell); - - state_set = atk_object_ref_state_set (item_cell); - atk_state_set_add_state (state_set, ATK_STATE_FOCUSED); - g_object_set_data (G_OBJECT(ea_calitem), "gail-focus-object", item_cell); - g_object_unref (state_set); -} diff --git a/widgets/misc/a11y/ea-calendar-item.h b/widgets/misc/a11y/ea-calendar-item.h deleted file mode 100644 index 36cc671a3b..0000000000 --- a/widgets/misc/a11y/ea-calendar-item.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EA_CALENDAR_ITEM_H__ -#define __EA_CALENDAR_ITEM_H__ - -#include -#include - -G_BEGIN_DECLS - -#define EA_TYPE_CALENDAR_ITEM (ea_calendar_item_get_type ()) -#define EA_CALENDAR_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_CALENDAR_ITEM, EaCalendarItem)) -#define EA_CALENDAR_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_CALENDAR_ITEM, EaCalendarItemClass)) -#define EA_IS_CALENDAR_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_CALENDAR_ITEM)) -#define EA_IS_CALENDAR_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_CALENDAR_ITEM)) -#define EA_CALENDAR_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_CALENDAR_ITEM, EaCalendarItemClass)) - -typedef struct _EaCalendarItem EaCalendarItem; -typedef struct _EaCalendarItemClass EaCalendarItemClass; - -struct _EaCalendarItem -{ - AtkGObjectAccessible parent; -}; - -GType ea_calendar_item_get_type (void); - -struct _EaCalendarItemClass -{ - AtkGObjectAccessibleClass parent_class; -}; - -AtkObject *ea_calendar_item_new (GObject *obj); -gboolean e_calendar_item_get_day_extents (ECalendarItem *calitem, - gint year, gint month, gint date, - gint *x, gint *y, - gint *width, gint *height); -gboolean e_calendar_item_get_date_for_offset (ECalendarItem *calitem, - gint day_offset, - gint *year, gint *month, - gint *day); -gint e_calendar_item_get_n_days_from_week_start (ECalendarItem *calitem, - gint year, gint month); - -G_END_DECLS - - -#endif /* __EA_CALENDAR_ITEM_H__ */ diff --git a/widgets/misc/a11y/ea-widgets.c b/widgets/misc/a11y/ea-widgets.c deleted file mode 100644 index 9deede235e..0000000000 --- a/widgets/misc/a11y/ea-widgets.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "a11y/ea-factory.h" -#include "ea-calendar-item.h" -#include "ea-widgets.h" - -EA_FACTORY_GOBJECT (EA_TYPE_CALENDAR_ITEM, ea_calendar_item, ea_calendar_item_new) - -void e_calendar_item_a11y_init (void) -{ - EA_SET_FACTORY (e_calendar_item_get_type (), ea_calendar_item); -} diff --git a/widgets/misc/a11y/ea-widgets.h b/widgets/misc/a11y/ea-widgets.h deleted file mode 100644 index 495222ae05..0000000000 --- a/widgets/misc/a11y/ea-widgets.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -/* Evolution Accessibility -*/ - -#ifndef _EA_WIDGETS_H__ -#define _EA_WIDGETS_H__ - -void e_calendar_item_a11y_init (void); - -#endif /* _EA_WIDGETS_H__ */ diff --git a/widgets/misc/e-calendar-item.c b/widgets/misc/e-calendar-item.c index 9c9bd94b15..890355620b 100644 --- a/widgets/misc/e-calendar-item.c +++ b/widgets/misc/e-calendar-item.c @@ -26,7 +26,7 @@ #endif #include "e-calendar-item.h" -#include "a11y/ea-widgets.h" +#include "ea-widgets.h" #include #include diff --git a/widgets/misc/ea-calendar-cell.c b/widgets/misc/ea-calendar-cell.c new file mode 100644 index 0000000000..af9471c5af --- /dev/null +++ b/widgets/misc/ea-calendar-cell.c @@ -0,0 +1,387 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include +#include +#include "ea-calendar-cell.h" +#include "ea-calendar-item.h" +#include "a11y/ea-factory.h" + +/* ECalendarCell */ + +static void e_calendar_cell_class_init (ECalendarCellClass *class); + +EA_FACTORY_GOBJECT (EA_TYPE_CALENDAR_CELL, ea_calendar_cell, ea_calendar_cell_new) + +GType +e_calendar_cell_get_type (void) +{ + static GType type = 0; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (ECalendarCellClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) e_calendar_cell_class_init, /* class init */ + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (ECalendarCell), /* instance size */ + 0, /* nb preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + type = g_type_register_static (G_TYPE_OBJECT, + "ECalendarCell", &tinfo, 0); + } + + return type; +} + +static void +e_calendar_cell_class_init (ECalendarCellClass *class) +{ + EA_SET_FACTORY (e_calendar_cell_get_type (), ea_calendar_cell); +} + +ECalendarCell * +e_calendar_cell_new (ECalendarItem *calitem, gint row, gint column) +{ + GObject *object; + ECalendarCell *cell; + + g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), NULL); + + object = g_object_new (E_TYPE_CALENDAR_CELL, NULL); + cell = E_CALENDAR_CELL (object); + cell->calitem = calitem; + cell->row = row; + cell->column = column; + +#ifdef ACC_DEBUG + g_print ("EvoAcc: e_calendar_cell created %p\n", (gpointer)cell); +#endif + + return cell; +} + +/* EaCalendarCell */ + +static void ea_calendar_cell_class_init (EaCalendarCellClass *klass); +static void ea_calendar_cell_init (EaCalendarCell *a11y); + +static G_CONST_RETURN gchar * ea_calendar_cell_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar * ea_calendar_cell_get_description (AtkObject *accessible); +static AtkObject * ea_calendar_cell_get_parent (AtkObject *accessible); +static gint ea_calendar_cell_get_index_in_parent (AtkObject *accessible); +static AtkStateSet *ea_calendar_cell_ref_state_set (AtkObject *accessible); + +/* component interface */ +static void atk_component_interface_init (AtkComponentIface *iface); +static void component_interface_get_extents (AtkComponent *component, + gint *x, gint *y, + gint *width, gint *height, + AtkCoordType coord_type); +static gboolean component_interface_grab_focus (AtkComponent *component); + +static gpointer parent_class = NULL; + +#ifdef ACC_DEBUG +static gint n_ea_calendar_cell_created = 0, n_ea_calendar_cell_destroyed = 0; +static void ea_calendar_cell_finalize (GObject *object); +#endif + +GType +ea_calendar_cell_get_type (void) +{ + static GType type = 0; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaCalendarCellClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) ea_calendar_cell_class_init, /* class init */ + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (EaCalendarCell), /* instance size */ + 0, /* nb preallocs */ + (GInstanceInitFunc) ea_calendar_cell_init, /* instance init */ + NULL /* value table */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) atk_component_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + type = g_type_register_static (ATK_TYPE_GOBJECT_ACCESSIBLE, + "EaCalendarCell", &tinfo, 0); + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, + &atk_component_info); + } + + return type; +} + +static void +ea_calendar_cell_class_init (EaCalendarCellClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + +#ifdef ACC_DEBUG + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = ea_calendar_cell_finalize; +#endif + + parent_class = g_type_class_peek_parent (klass); + + class->get_name = ea_calendar_cell_get_name; + class->get_description = ea_calendar_cell_get_description; + + class->get_parent = ea_calendar_cell_get_parent; + class->get_index_in_parent = ea_calendar_cell_get_index_in_parent; + class->ref_state_set = ea_calendar_cell_ref_state_set; +} + +static void +ea_calendar_cell_init (EaCalendarCell *a11y) +{ + a11y->state_set = atk_state_set_new (); + atk_state_set_add_state (a11y->state_set, ATK_STATE_TRANSIENT); + atk_state_set_add_state (a11y->state_set, ATK_STATE_ENABLED); + atk_state_set_add_state (a11y->state_set, ATK_STATE_SENSITIVE); + atk_state_set_add_state (a11y->state_set, ATK_STATE_SELECTABLE); + atk_state_set_add_state (a11y->state_set, ATK_STATE_SHOWING); + atk_state_set_add_state (a11y->state_set, ATK_STATE_FOCUSABLE); +} + +AtkObject* +ea_calendar_cell_new (GObject *obj) +{ + gpointer object; + AtkObject *atk_object; + + g_return_val_if_fail (E_IS_CALENDAR_CELL (obj), NULL); + object = g_object_new (EA_TYPE_CALENDAR_CELL, NULL); + atk_object = ATK_OBJECT (object); + atk_object_initialize (atk_object, obj); + atk_object->role = ATK_ROLE_TABLE_CELL; + +#ifdef ACC_DEBUG + ++n_ea_calendar_cell_created; + g_print ("ACC_DEBUG: n_ea_calendar_cell_created = %d\n", + n_ea_calendar_cell_created); +#endif + return atk_object; +} + +#ifdef ACC_DEBUG +static void ea_calendar_cell_finalize (GObject *object) +{ + G_OBJECT_CLASS (parent_class)->finalize (object); + + ++n_ea_calendar_cell_destroyed; + g_print ("ACC_DEBUG: n_ea_calendar_cell_destroyed = %d\n", + n_ea_calendar_cell_destroyed); +} +#endif + +static G_CONST_RETURN gchar * +ea_calendar_cell_get_name (AtkObject *accessible) +{ + GObject *g_obj; + + g_return_val_if_fail (EA_IS_CALENDAR_CELL (accessible), NULL); + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible)); + if (!g_obj) + /* defunct object*/ + return NULL; + + if (!accessible->name) { + AtkObject *atk_obj; + EaCalendarItem *ea_calitem; + ECalendarCell *cell; + gint day_index; + gint year, month, day; + gchar buffer[128]; + + cell = E_CALENDAR_CELL (g_obj); + atk_obj = ea_calendar_cell_get_parent (accessible); + ea_calitem = EA_CALENDAR_ITEM (atk_obj); + day_index = atk_table_get_index_at (ATK_TABLE (ea_calitem), + cell->row, cell->column); + e_calendar_item_get_date_for_offset (cell->calitem, day_index, + &year, &month, &day); + + g_snprintf (buffer, 128, "%d-%d-%d", year, month + 1, day); + ATK_OBJECT_CLASS (parent_class)->set_name (accessible, buffer); + } + return accessible->name; +} + +static G_CONST_RETURN gchar * +ea_calendar_cell_get_description (AtkObject *accessible) +{ + return ea_calendar_cell_get_name (accessible); +} + +static AtkObject * +ea_calendar_cell_get_parent (AtkObject *accessible) +{ + GObject *g_obj; + ECalendarCell *cell; + ECalendarItem *calitem; + + g_return_val_if_fail (EA_IS_CALENDAR_CELL (accessible), NULL); + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible)); + if (!g_obj) + /* defunct object*/ + return NULL; + + cell = E_CALENDAR_CELL (g_obj); + calitem = cell->calitem; + return atk_gobject_accessible_for_object (G_OBJECT (calitem)); +} + +static gint +ea_calendar_cell_get_index_in_parent (AtkObject *accessible) +{ + GObject *g_obj; + ECalendarCell *cell; + AtkObject *parent; + + g_return_val_if_fail (EA_IS_CALENDAR_CELL (accessible), -1); + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible)); + if (!g_obj) + return -1; + cell = E_CALENDAR_CELL (g_obj); + parent = atk_object_get_parent (accessible); + return atk_table_get_index_at (ATK_TABLE (parent), + cell->row, cell->column); +} + +static AtkStateSet * +ea_calendar_cell_ref_state_set (AtkObject *accessible) +{ + EaCalendarCell *atk_cell = EA_CALENDAR_CELL (accessible); + + g_return_val_if_fail (atk_cell->state_set, NULL); + + g_object_ref(atk_cell->state_set); + + return atk_cell->state_set; + +} + +/* Atk Component Interface */ + +static void +atk_component_interface_init (AtkComponentIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->get_extents = component_interface_get_extents; + iface->grab_focus = component_interface_grab_focus; +} + +static void +component_interface_get_extents (AtkComponent *component, + gint *x, gint *y, gint *width, gint *height, + AtkCoordType coord_type) +{ + GObject *g_obj; + AtkObject *atk_obj, *atk_canvas; + ECalendarCell *cell; + ECalendarItem *calitem; + EaCalendarItem *ea_calitem; + gint day_index; + gint year, month, day; + gint canvas_x, canvas_y, canvas_width, canvas_height; + + *x = *y = *width = *height = 0; + + g_return_if_fail (EA_IS_CALENDAR_CELL (component)); + + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(component)); + if (!g_obj) + /* defunct object*/ + return; + + cell = E_CALENDAR_CELL (g_obj); + calitem = cell->calitem; + atk_obj = atk_gobject_accessible_for_object (G_OBJECT (calitem)); + ea_calitem = EA_CALENDAR_ITEM (atk_obj); + day_index = atk_table_get_index_at (ATK_TABLE (ea_calitem), + cell->row, cell->column); + e_calendar_item_get_date_for_offset (calitem, day_index, + &year, &month, &day); + + if (!e_calendar_item_get_day_extents (calitem, + year, month, day, + x, y, width, height)) + return; + atk_canvas = atk_object_get_parent (ATK_OBJECT (ea_calitem)); + atk_component_get_extents (ATK_COMPONENT (atk_canvas), + &canvas_x, &canvas_y, + &canvas_width, &canvas_height, + coord_type); + *x += canvas_x; + *y += canvas_y; +} + +static gboolean +component_interface_grab_focus (AtkComponent *component) +{ + GObject *g_obj; + GtkWidget *toplevel; + AtkObject *ea_calitem; + ECalendarItem *calitem; + EaCalendarCell *a11y; + gint index; + + a11y = EA_CALENDAR_CELL (component); + ea_calitem = ea_calendar_cell_get_parent (ATK_OBJECT (a11y)); + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(ea_calitem)); + calitem = E_CALENDAR_ITEM (g_obj); + + index = atk_object_get_index_in_parent (ATK_OBJECT (a11y)); + + atk_selection_clear_selection (ATK_SELECTION (ea_calitem)); + atk_selection_add_selection (ATK_SELECTION (ea_calitem), index); + + gtk_widget_grab_focus (GTK_WIDGET (GNOME_CANVAS_ITEM (calitem)->canvas)); + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (GNOME_CANVAS_ITEM (calitem)->canvas)); + if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel)) + gtk_window_present (GTK_WINDOW (toplevel)); + + return TRUE; + +} diff --git a/widgets/misc/ea-calendar-cell.h b/widgets/misc/ea-calendar-cell.h new file mode 100644 index 0000000000..fa68fdca55 --- /dev/null +++ b/widgets/misc/ea-calendar-cell.h @@ -0,0 +1,86 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_CALENDAR_CELL_H__ +#define __EA_CALENDAR_CELL_H__ + +#include +#include "misc/e-calendar-item.h" + +G_BEGIN_DECLS + +#define E_TYPE_CALENDAR_CELL (e_calendar_cell_get_type ()) +#define E_CALENDAR_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_CALENDAR_CELL, ECalendarCell)) +#define E_CALENDAR_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_CALENDAR_CELL, ECalendarCellClass)) +#define E_IS_CALENDAR_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_CALENDAR_CELL)) +#define E_IS_CALENDAR_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_CALENDAR_CELL)) +#define E_CALENDAR_CELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_CALENDAR_CELL, ECalendarCellClass)) + +typedef struct _ECalendarCell ECalendarCell; +typedef struct _ECalendarCellClass ECalendarCellClass; + +struct _ECalendarCell +{ + GObject parent; + ECalendarItem *calitem; + gint row; + gint column; +}; + +GType e_calendar_cell_get_type (void); + +struct _ECalendarCellClass +{ + GObjectClass parent_class; +}; + +ECalendarCell * e_calendar_cell_new (ECalendarItem *calitem, + gint row, gint column); + +#define EA_TYPE_CALENDAR_CELL (ea_calendar_cell_get_type ()) +#define EA_CALENDAR_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_CALENDAR_CELL, EaCalendarCell)) +#define EA_CALENDAR_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_CALENDAR_CELL, EaCalendarCellClass)) +#define EA_IS_CALENDAR_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_CALENDAR_CELL)) +#define EA_IS_CALENDAR_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_CALENDAR_CELL)) +#define EA_CALENDAR_CELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_CALENDAR_CELL, EaCalendarCellClass)) + +typedef struct _EaCalendarCell EaCalendarCell; +typedef struct _EaCalendarCellClass EaCalendarCellClass; + +struct _EaCalendarCell +{ + AtkGObjectAccessible parent; + AtkStateSet *state_set; +}; + +GType ea_calendar_cell_get_type (void); + +struct _EaCalendarCellClass +{ + AtkGObjectAccessibleClass parent_class; +}; + +AtkObject* ea_calendar_cell_new (GObject *gobj); + +G_END_DECLS + +#endif /* __EA_CALENDAR_CELL_H__ */ diff --git a/widgets/misc/ea-calendar-item.c b/widgets/misc/ea-calendar-item.c new file mode 100644 index 0000000000..56a01b510b --- /dev/null +++ b/widgets/misc/ea-calendar-item.c @@ -0,0 +1,1314 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ea-calendar-item.h" +#include "ea-calendar-cell.h" +#include "a11y/ea-cell-table.h" + +#define EA_CALENDAR_COLUMN_NUM E_CALENDAR_COLS_PER_MONTH + +/* EaCalendarItem */ +static void ea_calendar_item_class_init (EaCalendarItemClass *klass); +static void ea_calendar_item_finalize (GObject *object); + +static G_CONST_RETURN gchar * ea_calendar_item_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar * ea_calendar_item_get_description (AtkObject *accessible); +static gint ea_calendar_item_get_n_children (AtkObject *accessible); +static AtkObject *ea_calendar_item_ref_child (AtkObject *accessible, gint index); +static AtkStateSet* ea_calendar_item_ref_state_set (AtkObject *accessible); + +/* atk table interface */ +static void atk_table_interface_init (AtkTableIface *iface); +static gint table_interface_get_index_at (AtkTable *table, + gint row, + gint column); +static gint table_interface_get_column_at_index (AtkTable *table, + gint index); +static gint table_interface_get_row_at_index (AtkTable *table, + gint index); +static AtkObject* table_interface_ref_at (AtkTable *table, + gint row, + gint column); +static gint table_interface_get_n_rows (AtkTable *table); +static gint table_interface_get_n_columns (AtkTable *table); +static gint table_interface_get_column_extent_at (AtkTable *table, + gint row, + gint column); +static gint table_interface_get_row_extent_at (AtkTable *table, + gint row, + gint column); + +static gboolean table_interface_is_row_selected (AtkTable *table, + gint row); +static gboolean table_interface_is_column_selected (AtkTable *table, + gint row); +static gboolean table_interface_is_selected (AtkTable *table, + gint row, + gint column); +static gint table_interface_get_selected_rows (AtkTable *table, + gint **rows_selected); +static gint table_interface_get_selected_columns (AtkTable *table, + gint **columns_selected); +static gboolean table_interface_add_row_selection (AtkTable *table, gint row); +static gboolean table_interface_remove_row_selection (AtkTable *table, + gint row); +static gboolean table_interface_add_column_selection (AtkTable *table, + gint column); +static gboolean table_interface_remove_column_selection (AtkTable *table, + gint column); +static AtkObject* table_interface_get_row_header (AtkTable *table, gint row); +static AtkObject* table_interface_get_column_header (AtkTable *table, + gint in_col); +static AtkObject* table_interface_get_caption (AtkTable *table); + +static G_CONST_RETURN gchar * +table_interface_get_column_description (AtkTable *table, gint in_col); + +static G_CONST_RETURN gchar * +table_interface_get_row_description (AtkTable *table, gint row); + +static AtkObject* table_interface_get_summary (AtkTable *table); + +/* atk selection interface */ +static void atk_selection_interface_init (AtkSelectionIface *iface); +static gboolean selection_interface_add_selection (AtkSelection *selection, + gint i); +static gboolean selection_interface_clear_selection (AtkSelection *selection); +static AtkObject* selection_interface_ref_selection (AtkSelection *selection, + gint i); +static gint selection_interface_get_selection_count (AtkSelection *selection); +static gboolean selection_interface_is_child_selected (AtkSelection *selection, + gint i); + +/* callbacks */ +static void selection_preview_change_cb (ECalendarItem *calitem); +static void date_range_changed_cb (ECalendarItem *calitem); + +/* helpers */ +static EaCellTable *ea_calendar_item_get_cell_data (EaCalendarItem *ea_calitem); +static void ea_calendar_item_destory_cell_data (EaCalendarItem *ea_calitem); +static gboolean ea_calendar_item_get_column_label (EaCalendarItem *ea_calitem, + gint column, + gchar *buffer, + gint buffer_size); +static gboolean ea_calendar_item_get_row_label (EaCalendarItem *ea_calitem, + gint row, + gchar *buffer, + gint buffer_size); +static gboolean e_calendar_item_get_offset_for_date (ECalendarItem *calitem, + gint year, gint month, gint day, + gint *offset); +static void ea_calendar_set_focus_object (EaCalendarItem *ea_calitem, + AtkObject *item_cell); + +#ifdef ACC_DEBUG +static gint n_ea_calendar_item_created = 0; +static gint n_ea_calendar_item_destroyed = 0; +#endif + +static gpointer parent_class = NULL; + +GType +ea_calendar_item_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaCalendarItemClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) ea_calendar_item_class_init, /* class init */ + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (EaCalendarItem), /* instance size */ + 0, /* nb preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + static const GInterfaceInfo atk_table_info = { + (GInterfaceInitFunc) atk_table_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + static const GInterfaceInfo atk_selection_info = { + (GInterfaceInitFunc) atk_selection_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (GailCanvasItem, in this case) + */ + + factory = atk_registry_get_factory (atk_get_default_registry (), + GNOME_TYPE_CANVAS_ITEM); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + type = g_type_register_static (derived_atk_type, + "EaCalendarItem", &tinfo, 0); + g_type_add_interface_static (type, ATK_TYPE_TABLE, + &atk_table_info); + g_type_add_interface_static (type, ATK_TYPE_SELECTION, + &atk_selection_info); + } + + return type; +} + +static void +ea_calendar_item_class_init (EaCalendarItemClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + gobject_class->finalize = ea_calendar_item_finalize; + parent_class = g_type_class_peek_parent (klass); + + class->get_name = ea_calendar_item_get_name; + class->get_description = ea_calendar_item_get_description; + class->ref_state_set = ea_calendar_item_ref_state_set; + + class->get_n_children = ea_calendar_item_get_n_children; + class->ref_child = ea_calendar_item_ref_child; +} + +AtkObject* +ea_calendar_item_new (GObject *obj) +{ + gpointer object; + AtkObject *atk_object; + AtkObject *item_cell; + + g_return_val_if_fail (E_IS_CALENDAR_ITEM (obj), NULL); + object = g_object_new (EA_TYPE_CALENDAR_ITEM, NULL); + atk_object = ATK_OBJECT (object); + atk_object_initialize (atk_object, obj); + atk_object->role = ATK_ROLE_CALENDAR; + + item_cell = atk_selection_ref_selection (ATK_SELECTION (atk_object), + 0); + if (item_cell) + ea_calendar_set_focus_object (EA_CALENDAR_ITEM (atk_object), item_cell); + +#ifdef ACC_DEBUG + ++n_ea_calendar_item_created; + g_print ("ACC_DEBUG: n_ea_calendar_item_created = %d\n", + n_ea_calendar_item_created); +#endif + /* connect signal handlers */ + g_signal_connect (obj, "selection_preview_changed", + G_CALLBACK (selection_preview_change_cb), + atk_object); + g_signal_connect (obj, "date_range_changed", + G_CALLBACK (date_range_changed_cb), + atk_object); + + return atk_object; +} + +static void +ea_calendar_item_finalize (GObject *object) +{ + EaCalendarItem *ea_calitem; + + g_return_if_fail (EA_IS_CALENDAR_ITEM (object)); + + ea_calitem = EA_CALENDAR_ITEM (object); + + /* Free the allocated cell data */ + ea_calendar_item_destory_cell_data (ea_calitem); + + G_OBJECT_CLASS (parent_class)->finalize (object); +#ifdef ACC_DEBUG + ++n_ea_calendar_item_destroyed; + printf ("ACC_DEBUG: n_ea_calendar_item_destroyed = %d\n", + n_ea_calendar_item_destroyed); +#endif +} + +static G_CONST_RETURN gchar * +ea_calendar_item_get_name (AtkObject *accessible) +{ + GObject *g_obj; + ECalendarItem *calitem; + gint start_year, start_month, start_day; + gint end_year, end_month, end_day; + gchar *name_str = NULL; + gchar buffer_start[128] = ""; + gchar buffer_end[128] = ""; + struct tm day_start = { 0 }; + struct tm day_end = { 0 }; + + g_return_val_if_fail (EA_IS_CALENDAR_ITEM (accessible), NULL); + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible)); + if (!g_obj) + return NULL; + g_return_val_if_fail (E_IS_CALENDAR_ITEM (g_obj), NULL); + + calitem = E_CALENDAR_ITEM (g_obj); + if (e_calendar_item_get_date_range (calitem, + &start_year, &start_month, &start_day, + &end_year, &end_month, &end_day)) { + + day_start.tm_year = start_year - 1900; + day_start.tm_mon = start_month; + day_start.tm_mday = start_day; + day_start.tm_isdst = -1; + e_utf8_strftime (buffer_start, sizeof (buffer_start), _("%d %B %Y"), &day_start); + + day_end.tm_year = end_year - 1900; + day_end.tm_mon = end_month; + day_end.tm_mday = end_day; + day_end.tm_isdst = -1; + e_utf8_strftime (buffer_end, sizeof (buffer_end), _("%d %B %Y"), &day_end); + + name_str = g_strdup_printf (_("Calendar: from %s to %s"), buffer_start, buffer_end); + } + +#if 0 + if (e_calendar_item_get_selection (calitem, &select_start, &select_end)) { + GDate select_start, select_end; + gint year1, year2, month1, month2, day1, day2; + + year1 = g_date_get_year (&select_start); + month1 = g_date_get_month (&select_start); + day1 = g_date_get_day (&select_start); + + year2 = g_date_get_year (&select_end); + month2 = g_date_get_month (&select_end); + day2 = g_date_get_day (&select_end); + + sprintf (new_name + strlen (new_name), + " : current selection: from %d-%d-%d to %d-%d-%d.", + year1, month1, day1, + year2, month2, day2); + } +#endif + + ATK_OBJECT_CLASS (parent_class)->set_name (accessible, name_str); + g_free (name_str); + + return accessible->name; +} + +static G_CONST_RETURN gchar * +ea_calendar_item_get_description (AtkObject *accessible) +{ + if (accessible->description) + return accessible->description; + + return _("evolution calendar item"); +} + +static AtkStateSet* +ea_calendar_item_ref_state_set (AtkObject *accessible) +{ + AtkStateSet *state_set; + GObject *g_obj; + + state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (accessible); + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible)); + if (!g_obj) + return state_set; + + atk_state_set_add_state (state_set, ATK_STATE_ENABLED); + atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE); + + return state_set; +} + +static gint +ea_calendar_item_get_n_children (AtkObject *accessible) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarItem *calitem; + gint n_children = 0; + gint start_year, start_month, start_day; + gint end_year, end_month, end_day; + GDate *start_date, *end_date; + + g_return_val_if_fail (EA_IS_CALENDAR_ITEM (accessible), -1); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + calitem = E_CALENDAR_ITEM (g_obj); + if (!e_calendar_item_get_date_range (calitem, &start_year, + &start_month, &start_day, + &end_year, &end_month, + &end_day)) + return 0; + + start_date = g_date_new_dmy (start_day, start_month + 1, start_year); + end_date = g_date_new_dmy (end_day, end_month + 1, end_year); + + n_children = g_date_days_between (start_date, end_date) + 1; + g_free (start_date); + g_free (end_date); + return n_children; +} + +static AtkObject * +ea_calendar_item_ref_child (AtkObject *accessible, gint index) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarItem *calitem; + gint n_children; + ECalendarCell *cell; + EaCellTable *cell_data; + EaCalendarItem *ea_calitem; + + g_return_val_if_fail (EA_IS_CALENDAR_ITEM (accessible), NULL); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + calitem = E_CALENDAR_ITEM (g_obj); + + n_children = ea_calendar_item_get_n_children (accessible); + if (index < 0 || index >= n_children) + return NULL; + + ea_calitem = EA_CALENDAR_ITEM (accessible); + cell_data = ea_calendar_item_get_cell_data (ea_calitem); + if (!cell_data) + return NULL; + + cell = ea_cell_table_get_cell_at_index (cell_data, index); + if (!cell) { + cell = e_calendar_cell_new (calitem, + index / EA_CALENDAR_COLUMN_NUM, + index % EA_CALENDAR_COLUMN_NUM); + ea_cell_table_set_cell_at_index (cell_data, index, cell); + g_object_unref (cell); + } + +#ifdef ACC_DEBUG + g_print ("AccDebug: ea_calendar_item children[%d]=%p\n", index, + (gpointer)cell); +#endif + return g_object_ref (atk_gobject_accessible_for_object (G_OBJECT(cell))); +} + +/* atk table interface */ + +static void +atk_table_interface_init (AtkTableIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->ref_at = table_interface_ref_at; + + iface->get_n_rows = table_interface_get_n_rows; + iface->get_n_columns = table_interface_get_n_columns; + iface->get_index_at = table_interface_get_index_at; + iface->get_column_at_index = table_interface_get_column_at_index; + iface->get_row_at_index = table_interface_get_row_at_index; + iface->get_column_extent_at = table_interface_get_column_extent_at; + iface->get_row_extent_at = table_interface_get_row_extent_at; + + iface->is_selected = table_interface_is_selected; + iface->get_selected_rows = table_interface_get_selected_rows; + iface->get_selected_columns = table_interface_get_selected_columns; + iface->is_row_selected = table_interface_is_row_selected; + iface->is_column_selected = table_interface_is_column_selected; + iface->add_row_selection = table_interface_add_row_selection; + iface->remove_row_selection = table_interface_remove_row_selection; + iface->add_column_selection = table_interface_add_column_selection; + iface->remove_column_selection = table_interface_remove_column_selection; + + iface->get_row_header = table_interface_get_row_header; + iface->get_column_header = table_interface_get_column_header; + iface->get_caption = table_interface_get_caption; + iface->get_summary = table_interface_get_summary; + iface->get_row_description = table_interface_get_row_description; + iface->get_column_description = table_interface_get_column_description; +} + +static AtkObject* +table_interface_ref_at (AtkTable *table, + gint row, + gint column) +{ + gint index; + + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + index = EA_CALENDAR_COLUMN_NUM * row + column; + return ea_calendar_item_ref_child (ATK_OBJECT (ea_calitem), index); +} + +static gint +table_interface_get_n_rows (AtkTable *table) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + gint n_children; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + n_children = ea_calendar_item_get_n_children (ATK_OBJECT (ea_calitem)); + return (n_children - 1) / EA_CALENDAR_COLUMN_NUM + 1; +} + +static gint +table_interface_get_n_columns (AtkTable *table) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + return EA_CALENDAR_COLUMN_NUM; +} + +static gint +table_interface_get_index_at (AtkTable *table, + gint row, + gint column) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + return row * EA_CALENDAR_COLUMN_NUM + column; +} + +static gint +table_interface_get_column_at_index (AtkTable *table, + gint index) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + gint n_children; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + n_children = ea_calendar_item_get_n_children (ATK_OBJECT (ea_calitem)); + if (index >= 0 && index < n_children) + return index % EA_CALENDAR_COLUMN_NUM; + return -1; +} + +static gint +table_interface_get_row_at_index (AtkTable *table, + gint index) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + gint n_children; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + n_children = ea_calendar_item_get_n_children (ATK_OBJECT (ea_calitem)); + if (index >= 0 && index < n_children) + return index / EA_CALENDAR_COLUMN_NUM; + return -1; +} + +static gint +table_interface_get_column_extent_at (AtkTable *table, + gint row, + gint column) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarItem *calitem; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + calitem = E_CALENDAR_ITEM (g_obj); + return calitem->cell_width; +} + +static gint +table_interface_get_row_extent_at (AtkTable *table, + gint row, gint column) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarItem *calitem; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + calitem = E_CALENDAR_ITEM (g_obj); + return calitem->cell_height; +} + +/* any day in the row is selected, the row is selected */ +static gboolean +table_interface_is_row_selected (AtkTable *table, + gint row) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + gint n_rows; + ECalendarItem *calitem; + gint row_index_start, row_index_end; + gint sel_index_start, sel_index_end; + + GDate start_date, end_date; + + g_return_val_if_fail (EA_IS_CALENDAR_ITEM (table), FALSE); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (table); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + n_rows = table_interface_get_n_rows (table); + if (row < 0 || row >= n_rows) + return FALSE; + + row_index_start = row * EA_CALENDAR_COLUMN_NUM; + row_index_end = row_index_start + EA_CALENDAR_COLUMN_NUM - 1; + + calitem = E_CALENDAR_ITEM (g_obj); + if (!e_calendar_item_get_selection (calitem, &start_date, &end_date)) + return FALSE; + + e_calendar_item_get_offset_for_date (calitem, + g_date_get_year (&start_date), + g_date_get_month (&start_date), + g_date_get_day (&start_date), + &sel_index_start); + e_calendar_item_get_offset_for_date (calitem, + g_date_get_year (&end_date), + g_date_get_month (&end_date), + g_date_get_day (&end_date), + &sel_index_end); + + if ((sel_index_start < row_index_start && + sel_index_end >= row_index_start) || + (sel_index_start >= row_index_start && + sel_index_start <= row_index_end)) + return TRUE; + return FALSE; +} + +static gboolean +table_interface_is_selected (AtkTable *table, + gint row, + gint column) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + gint n_rows, n_columns; + ECalendarItem *calitem; + gint index; + gint sel_index_start, sel_index_end; + + GDate start_date, end_date; + + g_return_val_if_fail (EA_IS_CALENDAR_ITEM (table), FALSE); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (table); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + n_rows = table_interface_get_n_rows (table); + if (row < 0 || row >= n_rows) + return FALSE; + n_columns = table_interface_get_n_columns (table); + if (column < 0 || column >= n_columns) + return FALSE; + + index = table_interface_get_index_at (table, row, column); + + calitem = E_CALENDAR_ITEM (g_obj); + if (!e_calendar_item_get_selection (calitem, &start_date, &end_date)) + return FALSE; + + e_calendar_item_get_offset_for_date (calitem, + g_date_get_year (&start_date), + g_date_get_month (&start_date), + g_date_get_day (&start_date), + &sel_index_start); + e_calendar_item_get_offset_for_date (calitem, + g_date_get_year (&end_date), + g_date_get_month (&end_date), + g_date_get_day (&end_date), &sel_index_end); + + if (sel_index_start <= index && sel_index_end >= index) + return TRUE; + return FALSE; +} + +static gboolean +table_interface_is_column_selected (AtkTable *table, + gint column) +{ + return FALSE; +} + +static gint +table_interface_get_selected_rows (AtkTable *table, + gint **rows_selected) +{ + *rows_selected = NULL; + return -1; +} + +static gint +table_interface_get_selected_columns (AtkTable *table, + gint **columns_selected) +{ + *columns_selected = NULL; + return -1; +} + +static gboolean +table_interface_add_row_selection (AtkTable *table, + gint row) +{ + return FALSE; +} + +static gboolean +table_interface_remove_row_selection (AtkTable *table, + gint row) +{ + return FALSE; +} + +static gboolean +table_interface_add_column_selection (AtkTable *table, + gint column) +{ + return FALSE; +} + +static gboolean +table_interface_remove_column_selection (AtkTable *table, + gint column) +{ + /* FIXME: NOT IMPLEMENTED */ + return FALSE; +} + +static AtkObject* +table_interface_get_row_header (AtkTable *table, + gint row) +{ + /* FIXME: NOT IMPLEMENTED */ + return NULL; +} + +static AtkObject* +table_interface_get_column_header (AtkTable *table, + gint in_col) +{ + /* FIXME: NOT IMPLEMENTED */ + return NULL; +} + +static AtkObject* +table_interface_get_caption (AtkTable *table) +{ + /* FIXME: NOT IMPLEMENTED */ + return NULL; +} + +static G_CONST_RETURN gchar * +table_interface_get_column_description (AtkTable *table, gint in_col) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + const gchar *description = NULL; + EaCellTable *cell_data; + gint n_columns; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + n_columns = table_interface_get_n_columns (table); + if (in_col < 0 || in_col >= n_columns) + return NULL; + cell_data = ea_calendar_item_get_cell_data (ea_calitem); + if (!cell_data) + return NULL; + + description = ea_cell_table_get_column_label (cell_data, in_col); + if (!description) { + gchar buffer[128] = "column description"; + ea_calendar_item_get_column_label (ea_calitem, in_col, + buffer, sizeof (buffer)); + ea_cell_table_set_column_label (cell_data, in_col, buffer); + description = ea_cell_table_get_column_label (cell_data, + in_col); + } + return description; +} + +static G_CONST_RETURN gchar * +table_interface_get_row_description (AtkTable *table, gint row) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + const gchar *description = NULL; + EaCellTable *cell_data; + gint n_rows; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + n_rows = table_interface_get_n_rows (table); + if (row < 0 || row >= n_rows) + return NULL; + cell_data = ea_calendar_item_get_cell_data (ea_calitem); + if (!cell_data) + return NULL; + + description = ea_cell_table_get_row_label (cell_data, row); + if (!description) { + gchar buffer[128] = "row description"; + ea_calendar_item_get_row_label (ea_calitem, row, + buffer, sizeof (buffer)); + ea_cell_table_set_row_label (cell_data, row, buffer); + description = ea_cell_table_get_row_label (cell_data, + row); + } + return description; +} + +static AtkObject* +table_interface_get_summary (AtkTable *table) +{ + /* FIXME: NOT IMPLEMENTED */ + return NULL; +} + +/* atkselection interface */ + +static void +atk_selection_interface_init (AtkSelectionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->add_selection = selection_interface_add_selection; + iface->clear_selection = selection_interface_clear_selection; + iface->ref_selection = selection_interface_ref_selection; + iface->get_selection_count = selection_interface_get_selection_count; + iface->is_child_selected = selection_interface_is_child_selected; +} + +static gboolean +selection_interface_add_selection (AtkSelection *selection, gint index) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarItem *calitem; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection); + gint year, month, day; + GDate start_date, end_date; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + calitem = E_CALENDAR_ITEM (g_obj); + if (!e_calendar_item_get_date_for_offset (calitem, index, + &year, &month, &day)) + return FALSE; + + /* FIXME: not support mulit-selection */ + g_date_set_dmy (&start_date, day, month + 1, year); + end_date = start_date; + e_calendar_item_set_selection (calitem, &start_date, &end_date); + return TRUE; +} + +static gboolean +selection_interface_clear_selection (AtkSelection *selection) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarItem *calitem; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + calitem = E_CALENDAR_ITEM (g_obj); + e_calendar_item_set_selection (calitem, NULL, NULL); + + return TRUE; +} + +static AtkObject* +selection_interface_ref_selection (AtkSelection *selection, gint i) +{ + GObject *g_obj; + ECalendarItem *calitem; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection); + gint count, sel_offset; + GDate start_date, end_date; + + count = selection_interface_get_selection_count (selection); + if (i < 0 || i >= count) + return NULL; + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (ea_calitem)); + + calitem = E_CALENDAR_ITEM (g_obj); + if (!e_calendar_item_get_selection (calitem, &start_date, &end_date)) + return NULL; + if (!e_calendar_item_get_offset_for_date (calitem, + g_date_get_year (&start_date), + g_date_get_month (&start_date) - 1, + g_date_get_day (&start_date), + &sel_offset)) + return NULL; + + return ea_calendar_item_ref_child (ATK_OBJECT (selection), sel_offset + i); +} + +static gint +selection_interface_get_selection_count (AtkSelection *selection) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarItem *calitem; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection); + GDate start_date, end_date; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return 0; + + calitem = E_CALENDAR_ITEM (g_obj); + if (e_calendar_item_get_selection (calitem, &start_date, &end_date)) + return g_date_days_between (&start_date, &end_date) + 1; + else + return 0; +} + +static gboolean +selection_interface_is_child_selected (AtkSelection *selection, gint index) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection); + gint row, column, n_children; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + n_children = atk_object_get_n_accessible_children (ATK_OBJECT (selection)); + if (index < 0 || index >= n_children) + return FALSE; + + row = index / EA_CALENDAR_COLUMN_NUM; + column = index % EA_CALENDAR_COLUMN_NUM; + + return table_interface_is_selected (ATK_TABLE (selection), row, column); +} + +/* callbacks */ + +static void +selection_preview_change_cb (ECalendarItem *calitem) +{ + AtkObject *atk_obj; + AtkObject *item_cell; + + g_return_if_fail (E_IS_CALENDAR_ITEM (calitem)); + atk_obj = atk_gobject_accessible_for_object (G_OBJECT (calitem)); + ea_calendar_item_destory_cell_data (EA_CALENDAR_ITEM (atk_obj)); + + /* only deal with the first selected child, for now */ + item_cell = atk_selection_ref_selection (ATK_SELECTION (atk_obj), + 0); + + if (item_cell) + ea_calendar_set_focus_object (EA_CALENDAR_ITEM (atk_obj), item_cell); + + g_signal_emit_by_name (atk_obj, + "active-descendant-changed", + item_cell); + g_signal_emit_by_name (atk_obj, "selection_changed"); +} + +static void +date_range_changed_cb (ECalendarItem *calitem) +{ + AtkObject *atk_obj; + AtkObject *item_cell; + + g_return_if_fail (E_IS_CALENDAR_ITEM (calitem)); + atk_obj = atk_gobject_accessible_for_object (G_OBJECT (calitem)); + ea_calendar_item_destory_cell_data (EA_CALENDAR_ITEM (atk_obj)); + + item_cell = atk_selection_ref_selection (ATK_SELECTION (atk_obj), + 0); + if (item_cell) + ea_calendar_set_focus_object (EA_CALENDAR_ITEM (atk_obj), item_cell); + + g_signal_emit_by_name (atk_obj, "model_changed"); +} + +/* helpers */ + +static EaCellTable * +ea_calendar_item_get_cell_data (EaCalendarItem *ea_calitem) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaCellTable *cell_data; + + g_return_val_if_fail (ea_calitem, NULL); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + cell_data = g_object_get_data (G_OBJECT(ea_calitem), + "ea-calendar-cell-table"); + + if (!cell_data) { + gint n_cells = ea_calendar_item_get_n_children (ATK_OBJECT(ea_calitem)); + cell_data = ea_cell_table_create (n_cells/EA_CALENDAR_COLUMN_NUM, + EA_CALENDAR_COLUMN_NUM, + FALSE); + g_object_set_data (G_OBJECT(ea_calitem), + "ea-calendar-cell-table", cell_data); + } + return cell_data; +} + +static void +ea_calendar_item_destory_cell_data (EaCalendarItem *ea_calitem) +{ + EaCellTable *cell_data; + + g_return_if_fail (ea_calitem); + + cell_data = g_object_get_data (G_OBJECT(ea_calitem), + "ea-calendar-cell-table"); + if (cell_data) { + g_object_set_data (G_OBJECT(ea_calitem), + "ea-calendar-cell-table", NULL); + ea_cell_table_destroy (cell_data); + } +} + +static gboolean +ea_calendar_item_get_row_label (EaCalendarItem *ea_calitem, gint row, + gchar *buffer, gint buffer_size) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarItem *calitem; + gint index, week_num; + gint year, month, day; + + g_return_val_if_fail (ea_calitem, FALSE); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + calitem = E_CALENDAR_ITEM (g_obj); + + index = atk_table_get_index_at (ATK_TABLE (ea_calitem), row, 0); + if (!e_calendar_item_get_date_for_offset (calitem, index, + &year, &month, &day)) + return FALSE; + + week_num = e_calendar_item_get_week_number (calitem, + day, month, year); + + g_snprintf (buffer, buffer_size, "week number : %d", week_num); + return TRUE; +} + +static gboolean +ea_calendar_item_get_column_label (EaCalendarItem *ea_calitem, gint column, + gchar *buffer, gint buffer_size) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarItem *calitem; + const gchar *abbr_name; + + g_return_val_if_fail (ea_calitem, FALSE); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + /* Columns are 0 = Monday ... 6 = Sunday */ + calitem = E_CALENDAR_ITEM (g_obj); + abbr_name = e_get_weekday_name (column + 1, TRUE); + g_strlcpy (buffer, abbr_name, buffer_size); + + return TRUE; +} + +/* the coordinate the e-calendar canvas coord */ +gboolean +e_calendar_item_get_day_extents (ECalendarItem *calitem, + gint year, gint month, gint date, + gint *x, gint *y, + gint *width, gint *height) +{ + GnomeCanvasItem *item; + GtkWidget *widget; + GtkStyle *style; + PangoFontDescription *font_desc; + PangoContext *pango_context; + PangoFontMetrics *font_metrics; + gint char_height, xthickness, ythickness, text_y; + gint new_year, new_month, num_months, months_offset; + gint month_x, month_y, month_cell_x, month_cell_y; + gint month_row, month_col; + gint day_row, day_col; + gint days_from_week_start; + + g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), FALSE); + + item = GNOME_CANVAS_ITEM (calitem); + widget = GTK_WIDGET (item->canvas); + style = widget->style; + + /* Set up Pango prerequisites */ + font_desc = calitem->font_desc; + if (!font_desc) + font_desc = style->font_desc; + pango_context = gtk_widget_get_pango_context (widget); + font_metrics = pango_context_get_metrics (pango_context, font_desc, + pango_context_get_language (pango_context)); + + char_height = + PANGO_PIXELS (pango_font_metrics_get_ascent (font_metrics)) + + PANGO_PIXELS (pango_font_metrics_get_descent (font_metrics)); + + xthickness = style->xthickness; + ythickness = style->ythickness; + + new_year = year; + new_month = month; + e_calendar_item_normalize_date (calitem, &new_year, &new_month); + num_months = calitem->rows * calitem->cols; + months_offset = (new_year - calitem->year) * 12 + + new_month - calitem->month; + + if (months_offset > num_months || months_offset < 0) + return FALSE; + + month_row = months_offset / calitem->cols; + month_col = months_offset % calitem->cols; + + month_x = item->x1 + xthickness + calitem->x_offset + + month_col * calitem->month_width; + month_y = item->y1 + ythickness + month_row * calitem->month_height; + + month_cell_x = month_x + E_CALENDAR_ITEM_XPAD_BEFORE_WEEK_NUMBERS + + calitem->month_lpad + E_CALENDAR_ITEM_XPAD_BEFORE_CELLS; + text_y = month_y + ythickness * 2 + + E_CALENDAR_ITEM_YPAD_ABOVE_MONTH_NAME + + char_height + E_CALENDAR_ITEM_YPAD_BELOW_MONTH_NAME + + E_CALENDAR_ITEM_YPAD_ABOVE_DAY_LETTERS + calitem->month_tpad; + + month_cell_y = text_y + char_height + + E_CALENDAR_ITEM_YPAD_BELOW_DAY_LETTERS + 1 + + E_CALENDAR_ITEM_YPAD_ABOVE_CELLS; + + days_from_week_start = + e_calendar_item_get_n_days_from_week_start (calitem, new_year, + new_month); + day_row = (date + days_from_week_start - 1) / EA_CALENDAR_COLUMN_NUM; + day_col = (date + days_from_week_start - 1) % EA_CALENDAR_COLUMN_NUM; + + *x = month_cell_x + day_col * calitem->cell_width; + *y = month_cell_y + day_row * calitem->cell_height; + *width = calitem->cell_width; + *height = calitem->cell_height; + + return TRUE; +} + +/* month is from 0 to 11 */ +gboolean +e_calendar_item_get_date_for_offset (ECalendarItem *calitem, gint day_offset, + gint *year, gint *month, gint *day) +{ + gint start_year, start_month, start_day; + gint end_year, end_month, end_day; + GDate *start_date; + + g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), FALSE); + + if (!e_calendar_item_get_date_range (calitem, &start_year, + &start_month, &start_day, + &end_year, &end_month, + &end_day)) + return FALSE; + + start_date = g_date_new_dmy (start_day, start_month + 1, start_year); + + g_date_add_days (start_date, day_offset); + + *year = g_date_get_year (start_date); + *month = g_date_get_month (start_date) - 1; + *day = g_date_get_day (start_date); + + return TRUE; +} + +/* the arg month is from 0 to 11 */ +static gboolean +e_calendar_item_get_offset_for_date (ECalendarItem *calitem, + gint year, gint month, gint day, + gint *offset) +{ + gint start_year, start_month, start_day; + gint end_year, end_month, end_day; + GDate *start_date, *end_date; + + *offset = 0; + g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), FALSE); + + if (!e_calendar_item_get_date_range (calitem, &start_year, + &start_month, &start_day, + &end_year, &end_month, + &end_day)) + return FALSE; + + start_date = g_date_new_dmy (start_day, start_month + 1, start_year); + end_date = g_date_new_dmy (day, month + 1, year); + + *offset = g_date_days_between (start_date, end_date); + g_free (start_date); + g_free (end_date); + + return TRUE; +} + +gint +e_calendar_item_get_n_days_from_week_start (ECalendarItem *calitem, + gint year, gint month) +{ + struct tm tmp_tm; + gint start_weekday, days_from_week_start; + + memset (&tmp_tm, 0, sizeof (tmp_tm)); + tmp_tm.tm_year = year - 1900; + tmp_tm.tm_mon = month; + tmp_tm.tm_mday = 1; + tmp_tm.tm_isdst = -1; + mktime (&tmp_tm); + start_weekday = (tmp_tm.tm_wday + 6) % 7; /* 0 to 6 */ + days_from_week_start = (start_weekday + 7 - calitem->week_start_day) + % 7; + return days_from_week_start; +} + +static void +ea_calendar_set_focus_object (EaCalendarItem *ea_calitem, AtkObject *item_cell) +{ + AtkStateSet *state_set, *old_state_set; + AtkObject *old_cell; + + old_cell = (AtkObject *)g_object_get_data (G_OBJECT(ea_calitem), "gail-focus-object"); + if (old_cell && EA_IS_CALENDAR_CELL (old_cell)) { + old_state_set = atk_object_ref_state_set (old_cell); + atk_state_set_remove_state (old_state_set, ATK_STATE_FOCUSED); + g_object_unref (old_state_set); + } + if (old_cell) + g_object_unref (old_cell); + + state_set = atk_object_ref_state_set (item_cell); + atk_state_set_add_state (state_set, ATK_STATE_FOCUSED); + g_object_set_data (G_OBJECT(ea_calitem), "gail-focus-object", item_cell); + g_object_unref (state_set); +} diff --git a/widgets/misc/ea-calendar-item.h b/widgets/misc/ea-calendar-item.h new file mode 100644 index 0000000000..36cc671a3b --- /dev/null +++ b/widgets/misc/ea-calendar-item.h @@ -0,0 +1,68 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_CALENDAR_ITEM_H__ +#define __EA_CALENDAR_ITEM_H__ + +#include +#include + +G_BEGIN_DECLS + +#define EA_TYPE_CALENDAR_ITEM (ea_calendar_item_get_type ()) +#define EA_CALENDAR_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_CALENDAR_ITEM, EaCalendarItem)) +#define EA_CALENDAR_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_CALENDAR_ITEM, EaCalendarItemClass)) +#define EA_IS_CALENDAR_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_CALENDAR_ITEM)) +#define EA_IS_CALENDAR_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_CALENDAR_ITEM)) +#define EA_CALENDAR_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_CALENDAR_ITEM, EaCalendarItemClass)) + +typedef struct _EaCalendarItem EaCalendarItem; +typedef struct _EaCalendarItemClass EaCalendarItemClass; + +struct _EaCalendarItem +{ + AtkGObjectAccessible parent; +}; + +GType ea_calendar_item_get_type (void); + +struct _EaCalendarItemClass +{ + AtkGObjectAccessibleClass parent_class; +}; + +AtkObject *ea_calendar_item_new (GObject *obj); +gboolean e_calendar_item_get_day_extents (ECalendarItem *calitem, + gint year, gint month, gint date, + gint *x, gint *y, + gint *width, gint *height); +gboolean e_calendar_item_get_date_for_offset (ECalendarItem *calitem, + gint day_offset, + gint *year, gint *month, + gint *day); +gint e_calendar_item_get_n_days_from_week_start (ECalendarItem *calitem, + gint year, gint month); + +G_END_DECLS + + +#endif /* __EA_CALENDAR_ITEM_H__ */ diff --git a/widgets/misc/ea-widgets.c b/widgets/misc/ea-widgets.c new file mode 100644 index 0000000000..9deede235e --- /dev/null +++ b/widgets/misc/ea-widgets.c @@ -0,0 +1,32 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "a11y/ea-factory.h" +#include "ea-calendar-item.h" +#include "ea-widgets.h" + +EA_FACTORY_GOBJECT (EA_TYPE_CALENDAR_ITEM, ea_calendar_item, ea_calendar_item_new) + +void e_calendar_item_a11y_init (void) +{ + EA_SET_FACTORY (e_calendar_item_get_type (), ea_calendar_item); +} diff --git a/widgets/misc/ea-widgets.h b/widgets/misc/ea-widgets.h new file mode 100644 index 0000000000..495222ae05 --- /dev/null +++ b/widgets/misc/ea-widgets.h @@ -0,0 +1,32 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/* Evolution Accessibility +*/ + +#ifndef _EA_WIDGETS_H__ +#define _EA_WIDGETS_H__ + +void e_calendar_item_a11y_init (void); + +#endif /* _EA_WIDGETS_H__ */ diff --git a/widgets/table/Makefile.am b/widgets/table/Makefile.am index a53b249ce4..c4fc858a74 100644 --- a/widgets/table/Makefile.am +++ b/widgets/table/Makefile.am @@ -73,22 +73,22 @@ libetable_la_SOURCES = \ e-tree-sorted.c \ e-tree-table-adapter.c \ e-tree.c \ - a11y/gal-a11y-e-cell.c \ - a11y/gal-a11y-e-cell-popup.c \ - a11y/gal-a11y-e-cell-registry.c \ - a11y/gal-a11y-e-cell-text.c \ - a11y/gal-a11y-e-cell-toggle.c \ - a11y/gal-a11y-e-cell-tree.c \ - a11y/gal-a11y-e-cell-vbox.c \ - a11y/gal-a11y-e-table.c \ - a11y/gal-a11y-e-table-click-to-add.c \ - a11y/gal-a11y-e-table-click-to-add-factory.c \ - a11y/gal-a11y-e-table-column-header.c \ - a11y/gal-a11y-e-table-factory.c \ - a11y/gal-a11y-e-table-item.c \ - a11y/gal-a11y-e-table-item-factory.c \ - a11y/gal-a11y-e-tree.c \ - a11y/gal-a11y-e-tree-factory.c + gal-a11y-e-cell.c \ + gal-a11y-e-cell-popup.c \ + gal-a11y-e-cell-registry.c \ + gal-a11y-e-cell-text.c \ + gal-a11y-e-cell-toggle.c \ + gal-a11y-e-cell-tree.c \ + gal-a11y-e-cell-vbox.c \ + gal-a11y-e-table.c \ + gal-a11y-e-table-click-to-add.c \ + gal-a11y-e-table-click-to-add-factory.c \ + gal-a11y-e-table-column-header.c \ + gal-a11y-e-table-factory.c \ + gal-a11y-e-table-item.c \ + gal-a11y-e-table-item-factory.c \ + gal-a11y-e-tree.c \ + gal-a11y-e-tree-factory.c libetableincludedir = $(privincludedir)/table @@ -155,22 +155,22 @@ libetableinclude_HEADERS = \ e-tree-sorted.h \ e-tree-table-adapter.h \ e-tree.h \ - a11y/gal-a11y-e-cell.h \ - a11y/gal-a11y-e-cell-popup.h \ - a11y/gal-a11y-e-cell-registry.h \ - a11y/gal-a11y-e-cell-text.h \ - a11y/gal-a11y-e-cell-toggle.h \ - a11y/gal-a11y-e-cell-tree.h \ - a11y/gal-a11y-e-cell-vbox.h \ - a11y/gal-a11y-e-table.h \ - a11y/gal-a11y-e-table-click-to-add.h \ - a11y/gal-a11y-e-table-click-to-add-factory.h \ - a11y/gal-a11y-e-table-column-header.h \ - a11y/gal-a11y-e-table-factory.h \ - a11y/gal-a11y-e-table-item.h \ - a11y/gal-a11y-e-table-item-factory.h \ - a11y/gal-a11y-e-tree.h \ - a11y/gal-a11y-e-tree-factory.h + gal-a11y-e-cell.h \ + gal-a11y-e-cell-popup.h \ + gal-a11y-e-cell-registry.h \ + gal-a11y-e-cell-text.h \ + gal-a11y-e-cell-toggle.h \ + gal-a11y-e-cell-tree.h \ + gal-a11y-e-cell-vbox.h \ + gal-a11y-e-table.h \ + gal-a11y-e-table-click-to-add.h \ + gal-a11y-e-table-click-to-add-factory.h \ + gal-a11y-e-table-column-header.h \ + gal-a11y-e-table-factory.h \ + gal-a11y-e-table-item.h \ + gal-a11y-e-table-item-factory.h \ + gal-a11y-e-tree.h \ + gal-a11y-e-tree-factory.h libetable_la_LDFLAGS = $(NO_UNDEFINED) diff --git a/widgets/table/a11y/gal-a11y-e-cell-popup.c b/widgets/table/a11y/gal-a11y-e-cell-popup.c deleted file mode 100644 index 141ce172a4..0000000000 --- a/widgets/table/a11y/gal-a11y-e-cell-popup.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Yang Wu - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include - -#include -#include - -#include "a11y/gal-a11y-util.h" -#include "table/e-cell-popup.h" -#include - -#include "gal-a11y-e-cell-popup.h" -#include "gal-a11y-e-cell-registry.h" - -static AtkObjectClass *parent_class = NULL; -#define PARENT_TYPE (gal_a11y_e_cell_get_type ()) - -static void gal_a11y_e_cell_popup_class_init (GalA11yECellPopupClass *klass); -static void popup_cell_action (GalA11yECell *cell); - -/** - * gal_a11y_e_cell_popup_get_type: - * @void: - * - * Registers the &GalA11yECellPopup class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &GalA11yECellPopup class. - **/ -GType -gal_a11y_e_cell_popup_get_type (void) -{ - static GType type = 0; - - if (!type) { - GTypeInfo info = { - sizeof (GalA11yECellPopupClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gal_a11y_e_cell_popup_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (GalA11yECellPopup), - 0, - (GInstanceInitFunc) NULL, - NULL /* value_cell_popup */ - }; - - type = g_type_register_static (PARENT_TYPE, "GalA11yECellPopup", &info, 0); - gal_a11y_e_cell_type_add_action_interface (type); - } - - return type; -} - -static void -gal_a11y_e_cell_popup_class_init (GalA11yECellPopupClass *klass) -{ - parent_class = g_type_class_ref (PARENT_TYPE); -} - -AtkObject * -gal_a11y_e_cell_popup_new (ETableItem *item, - ECellView *cell_view, - AtkObject *parent, - gint model_col, - gint view_col, - gint row) -{ - AtkObject *a11y; - GalA11yECell *cell; - ECellPopup *popupcell; - ECellView* child_view = NULL; - - popupcell= E_CELL_POPUP(cell_view->ecell); - - if (popupcell && popupcell->popup_cell_view) - child_view = popupcell->popup_cell_view->child_view; - - if (child_view && child_view->ecell) { - a11y = gal_a11y_e_cell_registry_get_object (NULL, - item, - child_view, - parent, - model_col, - view_col, - row); - } else { - a11y = g_object_new (GAL_A11Y_TYPE_E_CELL_POPUP, NULL); - gal_a11y_e_cell_construct (a11y, - item, - cell_view, - parent, - model_col, - view_col, - row); - } - g_return_val_if_fail (a11y != NULL, NULL); - cell = GAL_A11Y_E_CELL(a11y); - gal_a11y_e_cell_add_action (cell, - _("popup"), /* action name*/ - _("popup a child"), /* action description */ - "Down", /* action keybinding */ - popup_cell_action); - - a11y->role = ATK_ROLE_TABLE_CELL; - return a11y; -} - -static void -popup_cell_action (GalA11yECell *cell) -{ - gint finished; - GdkEvent event; - - event.key.type = GDK_KEY_PRESS; - event.key.window = GTK_LAYOUT(GNOME_CANVAS_ITEM(cell->item)->canvas)->bin_window;; - event.key.send_event = TRUE; - event.key.time = GDK_CURRENT_TIME; - event.key.state = GDK_MOD1_MASK; - event.key.keyval = GDK_Down; - - g_signal_emit_by_name (cell->item, "event", &event, &finished); -} diff --git a/widgets/table/a11y/gal-a11y-e-cell-popup.h b/widgets/table/a11y/gal-a11y-e-cell-popup.h deleted file mode 100644 index 76ad0ffec9..0000000000 --- a/widgets/table/a11y/gal-a11y-e-cell-popup.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Yang Wu - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __GAL_A11Y_E_CELL_POPUP_H__ -#define __GAL_A11Y_E_CELL_POPUP_H__ - -#include -#include
-#include
-#include - -#define GAL_A11Y_TYPE_E_CELL_POPUP (gal_a11y_e_cell_popup_get_type ()) -#define GAL_A11Y_E_CELL_POPUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_POPUP, GalA11yECellPopup)) -#define GAL_A11Y_E_CELL_POPUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL_POPUP, GalA11yECellPopupClass)) -#define GAL_A11Y_IS_E_CELL_POPUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_POPUP)) -#define GAL_A11Y_IS_E_CELL_POPUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_POPUP)) - -typedef struct _GalA11yECellPopup GalA11yECellPopup; -typedef struct _GalA11yECellPopupClass GalA11yECellPopupClass; - -/* This struct should actually be larger as this isn't what we derive from. - * The GalA11yECellPopupPrivate comes right after the parent class structure. - **/ -struct _GalA11yECellPopup { - GalA11yECell object; -}; - -struct _GalA11yECellPopupClass { - GalA11yECellClass parent_class; -}; - - -/* Standard Glib function */ -GType gal_a11y_e_cell_popup_get_type (void); -AtkObject *gal_a11y_e_cell_popup_new (ETableItem *item, - ECellView *cell_view, - AtkObject *parent, - gint model_col, - gint view_col, - gint row); - -#endif /* ! __GAL_A11Y_E_CELL_POPUP_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-cell-registry.c b/widgets/table/a11y/gal-a11y-e-cell-registry.c deleted file mode 100644 index 9dc9598608..0000000000 --- a/widgets/table/a11y/gal-a11y-e-cell-registry.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Christopher James Lahey - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include - -#include "gal-a11y-e-cell.h" -#include "gal-a11y-e-cell-registry.h" - -static GObjectClass *parent_class; -static GalA11yECellRegistry *default_registry; -#define PARENT_TYPE (G_TYPE_OBJECT) - -struct _GalA11yECellRegistryPrivate { - GHashTable *table; -}; - -/* Static functions */ - -static void -gal_a11y_e_cell_registry_finalize (GObject *obj) -{ - GalA11yECellRegistry *registry = GAL_A11Y_E_CELL_REGISTRY (obj); - - g_hash_table_destroy (registry->priv->table); - g_free (registry->priv); - - G_OBJECT_CLASS (parent_class)->finalize (obj); -} - -static void -gal_a11y_e_cell_registry_class_init (GalA11yECellRegistryClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - parent_class = g_type_class_ref (PARENT_TYPE); - - object_class->finalize = gal_a11y_e_cell_registry_finalize; -} - -static void -gal_a11y_e_cell_registry_init (GalA11yECellRegistry *registry) -{ - registry->priv = g_new (GalA11yECellRegistryPrivate, 1); - registry->priv->table = g_hash_table_new (NULL, NULL); -} - -/** - * gal_a11y_e_cell_registry_get_type: - * @void: - * - * Registers the &GalA11yECellRegistry class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &GalA11yECellRegistry class. - **/ -GType -gal_a11y_e_cell_registry_get_type (void) -{ - static GType type = 0; - - if (!type) { - GTypeInfo info = { - sizeof (GalA11yECellRegistryClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gal_a11y_e_cell_registry_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (GalA11yECellRegistry), - 0, - (GInstanceInitFunc) gal_a11y_e_cell_registry_init, - NULL /* value_cell */ - }; - - type = g_type_register_static (PARENT_TYPE, "GalA11yECellRegistry", &info, 0); - } - - return type; -} - -static void -init_default_registry (void) -{ - if (default_registry == NULL) { - default_registry = g_object_new (gal_a11y_e_cell_registry_get_type(), NULL); - } -} - - -AtkObject * -gal_a11y_e_cell_registry_get_object (GalA11yECellRegistry *registry, - ETableItem *item, - ECellView *cell_view, - AtkObject *parent, - gint model_col, - gint view_col, - gint row) -{ - GalA11yECellRegistryFunc func = NULL; - GType type; - - if (registry == NULL) { - init_default_registry (); - registry = default_registry; - } - - type = GTK_OBJECT_TYPE (cell_view->ecell); - while (func == NULL && type != 0) { - func = g_hash_table_lookup (registry->priv->table, GINT_TO_POINTER (type)); - type = g_type_parent (type); - } - - if (func) - return func (item, cell_view, parent, model_col, view_col, row); - else - return gal_a11y_e_cell_new (item, cell_view, parent, model_col, view_col, row); -} - -void -gal_a11y_e_cell_registry_add_cell_type (GalA11yECellRegistry *registry, - GType type, - GalA11yECellRegistryFunc func) -{ - if (registry == NULL) { - init_default_registry (); - registry = default_registry; - } - - g_hash_table_insert (registry->priv->table, GINT_TO_POINTER (type), func); -} diff --git a/widgets/table/a11y/gal-a11y-e-cell-registry.h b/widgets/table/a11y/gal-a11y-e-cell-registry.h deleted file mode 100644 index 0620fd1b9c..0000000000 --- a/widgets/table/a11y/gal-a11y-e-cell-registry.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Christopher James Lahey - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __GAL_A11Y_E_CELL_REGISTRY_H__ -#define __GAL_A11Y_E_CELL_REGISTRY_H__ - -#include -#include -#include
-#include
- -#define GAL_A11Y_TYPE_E_CELL_REGISTRY (gal_a11y_e_cell_registry_get_type ()) -#define GAL_A11Y_E_CELL_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_REGISTRY, GalA11yECellRegistry)) -#define GAL_A11Y_E_CELL_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL_REGISTRY, GalA11yECellRegistryClass)) -#define GAL_A11Y_IS_E_CELL_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_REGISTRY)) -#define GAL_A11Y_IS_E_CELL_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_REGISTRY)) - -typedef struct _GalA11yECellRegistry GalA11yECellRegistry; -typedef struct _GalA11yECellRegistryClass GalA11yECellRegistryClass; -typedef struct _GalA11yECellRegistryPrivate GalA11yECellRegistryPrivate; - -typedef AtkObject *(*GalA11yECellRegistryFunc) (ETableItem *item, - ECellView *cell_view, - AtkObject *parent, - gint model_col, - gint view_col, - gint row); - -struct _GalA11yECellRegistry { - GObject object; - - GalA11yECellRegistryPrivate *priv; -}; - -struct _GalA11yECellRegistryClass { - GObjectClass parent_class; -}; - - -/* Standard Glib function */ -GType gal_a11y_e_cell_registry_get_type (void); -AtkObject *gal_a11y_e_cell_registry_get_object (GalA11yECellRegistry *registry, - ETableItem *item, - ECellView *cell_view, - AtkObject *parent, - gint model_col, - gint view_col, - gint row); -void gal_a11y_e_cell_registry_add_cell_type (GalA11yECellRegistry *registry, - GType type, - GalA11yECellRegistryFunc func); - -#endif /* ! __GAL_A11Y_E_CELL_REGISTRY_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-cell-text.c b/widgets/table/a11y/gal-a11y-e-cell-text.c deleted file mode 100644 index 77823b0a7c..0000000000 --- a/widgets/table/a11y/gal-a11y-e-cell-text.c +++ /dev/null @@ -1,737 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Christopher James Lahey - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include - -#include - -#include - -#include "a11y/gal-a11y-util.h" -#include "table/e-cell-text.h" -#include - -#include "gal-a11y-e-cell-text.h" - -#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yECellTextClass)) -static AtkObjectClass *parent_class; -#define PARENT_TYPE (gal_a11y_e_cell_get_type ()) - -/* Static functions */ -static void -ect_dispose (GObject *object) -{ - GObjectClass *g_class; - GalA11yECell *gaec = GAL_A11Y_E_CELL (object); - GalA11yECellText *gaet = GAL_A11Y_E_CELL_TEXT (object); - - if (gaet->inserted_id != 0) { - ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell); - - if (ect) { - g_signal_handler_disconnect (ect, gaet->inserted_id); - g_signal_handler_disconnect (ect, gaet->deleted_id); - } - - gaet->inserted_id = 0; - gaet->deleted_id = 0; - } - - g_class = (GObjectClass *)parent_class; - if (g_class->dispose) - g_class->dispose (object); - -} - -static gboolean -ect_check (gpointer a11y) -{ - GalA11yECell *gaec = GAL_A11Y_E_CELL (a11y); - ETableItem *item = gaec->item; - - g_return_val_if_fail ((gaec->item != NULL), FALSE); - g_return_val_if_fail ((gaec->cell_view != NULL), FALSE); - g_return_val_if_fail ((gaec->cell_view->ecell != NULL), FALSE); - - if (atk_state_set_contains_state (gaec->state_set, ATK_STATE_DEFUNCT)) - return FALSE; - - if (gaec->row < 0 || gaec->row >= item->rows - || gaec->view_col <0 || gaec->view_col >= item->cols - || gaec->model_col <0 || gaec->model_col >= e_table_model_column_count (item->table_model)) - return FALSE; - - if (!E_IS_CELL_TEXT (gaec->cell_view->ecell)) - return FALSE; - - return TRUE; -} - -static G_CONST_RETURN gchar * -ect_get_name (AtkObject * a11y) -{ - GalA11yECell *gaec; - gchar *name; - - if (!ect_check (a11y)) - return NULL; - - gaec = GAL_A11Y_E_CELL (a11y); - name = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); - if (name != NULL) { - ATK_OBJECT_CLASS (parent_class)->set_name (a11y, name); - g_free (name); - } - - if (a11y->name != NULL && strcmp (a11y->name, "")) { - return a11y->name; - } else { - return parent_class->get_name (a11y); - } -} - -static gchar * -ect_get_text (AtkText *text, - gint start_offset, - gint end_offset) -{ - GalA11yECell *gaec = GAL_A11Y_E_CELL (text); - gchar *full_text; - gchar *ret_val; - - if (!ect_check (text)) - return NULL; - - full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); - - if (end_offset == -1) - end_offset = strlen (full_text); - else - end_offset = g_utf8_offset_to_pointer (full_text, end_offset) - full_text; - - start_offset = g_utf8_offset_to_pointer (full_text, start_offset) - full_text; - - ret_val = g_strndup (full_text + start_offset, end_offset - start_offset); - - g_free (full_text); - - return ret_val; -} - -static gchar * -ect_get_text_after_offset (AtkText *text, - gint offset, - AtkTextBoundary boundary_type, - gint *start_offset, - gint *end_offset) -{ - /* Unimplemented */ - return NULL; -} - -static gchar * -ect_get_text_at_offset (AtkText *text, - gint offset, - AtkTextBoundary boundary_type, - gint *start_offset, - gint *end_offset) -{ - /* Unimplemented */ - return NULL; -} - -static gunichar -ect_get_character_at_offset (AtkText *text, - gint offset) -{ - GalA11yECell *gaec = GAL_A11Y_E_CELL (text); - gunichar ret_val; - gchar *at_offset; - gchar *full_text; - - if (!ect_check (text)) - return -1; - - full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); - at_offset = g_utf8_offset_to_pointer (full_text, offset); - ret_val = g_utf8_get_char_validated (at_offset, -1); - g_free (full_text); - - return ret_val; -} - - -static gchar * -ect_get_text_before_offset (AtkText *text, - gint offset, - AtkTextBoundary boundary_type, - gint *start_offset, - gint *end_offset) -{ - /* Unimplemented */ - return NULL; -} - - -static gint -ect_get_caret_offset (AtkText *text) -{ - GalA11yECell *gaec = GAL_A11Y_E_CELL (text); - gint start, end; - - if (!ect_check (text)) - return -1; - - if (e_cell_text_get_selection (gaec->cell_view, - gaec->view_col, gaec->row, - &start, &end)) { - gchar *full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); - end = g_utf8_pointer_to_offset (full_text, full_text + end); - g_free (full_text); - - return end; - } - else - return -1; -} - -static AtkAttributeSet* -ect_get_run_attributes (AtkText *text, - gint offset, - gint *start_offset, - gint *end_offset) -{ - /* Unimplemented */ - return NULL; -} - - -static AtkAttributeSet* -ect_get_default_attributes (AtkText *text) -{ - /* Unimplemented */ - return NULL; -} - - -static void -ect_get_character_extents (AtkText *text, - gint offset, - gint *x, - gint *y, - gint *width, - gint *height, - AtkCoordType coords) -{ - /* Unimplemented */ -} - - -static gint -ect_get_character_count (AtkText *text) -{ - GalA11yECell *gaec = GAL_A11Y_E_CELL (text); - gint ret_val; - gchar *full_text; - - if (!ect_check (text)) - return -1; - - full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); - - ret_val = g_utf8_strlen (full_text, -1); - g_free (full_text); - return ret_val; -} - - -static gint -ect_get_offset_at_point (AtkText *text, - gint x, - gint y, - AtkCoordType coords) -{ - /* Unimplemented */ - return 0; -} - - -static gint -ect_get_n_selections (AtkText *text) -{ - GalA11yECell *gaec = GAL_A11Y_E_CELL (text); - gint selection_start, selection_end; - - if (!ect_check (text)) - return 0; - - if (e_cell_text_get_selection (gaec->cell_view, - gaec->view_col, gaec->row, - &selection_start, - &selection_end) - && selection_start != selection_end) - return 1; - return 0; -} - - -static gchar * -ect_get_selection (AtkText *text, - gint selection_num, - gint *start_offset, - gint *end_offset) -{ - GalA11yECell *gaec = GAL_A11Y_E_CELL (text); - gchar *ret_val; - gint selection_start, selection_end; - - if (selection_num == 0 - && e_cell_text_get_selection (gaec->cell_view, - gaec->view_col, gaec->row, - &selection_start, - &selection_end) - && selection_start != selection_end) { - gint real_start, real_end, len; - gchar *full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); - len = strlen (full_text); - real_start = MIN (selection_start, selection_end); - real_end = MAX (selection_start, selection_end); - real_start = MIN (MAX (0, real_start), len); - real_end = MIN (MAX (0, real_end), len); - - ret_val = g_strndup (full_text + real_start, real_end - real_start); - - real_start = g_utf8_pointer_to_offset (full_text, full_text + real_start); - real_end = g_utf8_pointer_to_offset (full_text, full_text + real_end); - - if (start_offset) - *start_offset = real_start; - if (end_offset) - *end_offset = real_end; - g_free (full_text); - } else { - if (start_offset) - *start_offset = 0; - if (end_offset) - *end_offset = 0; - ret_val = NULL; - } - - return ret_val; -} - - -static gboolean -ect_add_selection (AtkText *text, - gint start_offset, - gint end_offset) -{ - GalA11yECell *gaec = GAL_A11Y_E_CELL (text); - - if (start_offset != end_offset) { - gint real_start, real_end, len; - gchar *full_text = - e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); - - len = g_utf8_strlen (full_text, -1); - if (end_offset == -1) - end_offset = len; - - real_start = MIN (start_offset, end_offset); - real_end = MAX (start_offset, end_offset); - - real_start = MIN (MAX (0, real_start), len); - real_end = MIN (MAX (0, real_end), len); - - real_start = g_utf8_offset_to_pointer (full_text, real_start) - full_text; - real_end = g_utf8_offset_to_pointer (full_text, real_end) - full_text; - g_free (full_text); - - if (e_cell_text_set_selection (gaec->cell_view, - gaec->view_col, gaec->row, - real_start, real_end)) { - g_signal_emit_by_name (ATK_OBJECT(text), "text_selection_changed"); - return TRUE; - } - } - - return FALSE; -} - - -static gboolean -ect_remove_selection (AtkText *text, - gint selection_num) -{ - GalA11yECell *gaec = GAL_A11Y_E_CELL (text); - gint selection_start, selection_end; - - if (selection_num == 0 - && e_cell_text_get_selection (gaec->cell_view, - gaec->view_col, gaec->row, - &selection_start, - &selection_end) - && selection_start != selection_end - && e_cell_text_set_selection (gaec->cell_view, - gaec->view_col, gaec->row, - selection_end, selection_end)) { - g_signal_emit_by_name (ATK_OBJECT(text), "text_selection_changed"); - return TRUE; - } - else - return FALSE; -} - - -static gboolean -ect_set_selection (AtkText *text, - gint selection_num, - gint start_offset, - gint end_offset) -{ - if (selection_num == 0) { - atk_text_add_selection (text, start_offset, end_offset); - return TRUE; - } - else - return FALSE; -} - - -static gboolean -ect_set_caret_offset (AtkText *text, - gint offset) -{ - GalA11yECell *gaec = GAL_A11Y_E_CELL (text); - gchar *full_text; - gint len; - - full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); - - len = g_utf8_strlen (full_text, -1); - if (offset == -1) - offset = len; - else - offset = MIN (MAX (0, offset), len); - - offset = g_utf8_offset_to_pointer (full_text, offset) - full_text; - - g_free (full_text); - - return e_cell_text_set_selection (gaec->cell_view, - gaec->view_col, gaec->row, - offset, offset); -} - -static gboolean -ect_set_run_attributes (AtkEditableText *text, - AtkAttributeSet *attrib_set, - gint start_offset, - gint end_offset) -{ - /* Unimplemented */ - return FALSE; -} - -static void -ect_set_text_contents (AtkEditableText *text, - const gchar *string) -{ - GalA11yECell *gaec = GAL_A11Y_E_CELL (text); - ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell); - - e_cell_text_set_value (ect, gaec->item->table_model, gaec->model_col, gaec->row, string); - e_table_item_enter_edit (gaec->item, gaec->view_col, gaec->row); -} - -static void -ect_insert_text (AtkEditableText *text, - const gchar *string, - gint length, - gint *position) -{ - /* Utf8 unimplemented */ - GalA11yECell *gaec = GAL_A11Y_E_CELL (text); - ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell); - - gchar *full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); - gchar *result = g_strdup_printf ("%.*s%.*s%s", *position, full_text, length, string, full_text + *position); - - e_cell_text_set_value (ect, gaec->item->table_model, gaec->model_col, gaec->row, result); - - *position += length; - - g_free (result); - g_free (full_text); -} - -static void -ect_copy_text (AtkEditableText *text, - gint start_pos, - gint end_pos) -{ - GalA11yECell *gaec = GAL_A11Y_E_CELL (text); - if (start_pos != end_pos - && atk_text_set_selection (ATK_TEXT (text), 0, start_pos, end_pos)) - e_cell_text_copy_clipboard (gaec->cell_view, - gaec->view_col, gaec->row); -} - -static void -ect_delete_text (AtkEditableText *text, - gint start_pos, - gint end_pos) -{ - GalA11yECell *gaec = GAL_A11Y_E_CELL (text); - if (start_pos != end_pos - && atk_text_set_selection (ATK_TEXT (text), 0, start_pos, end_pos)) - e_cell_text_delete_selection (gaec->cell_view, - gaec->view_col, gaec->row); -} - -static void -ect_cut_text (AtkEditableText *text, - gint start_pos, - gint end_pos) -{ - ect_copy_text (text, start_pos, end_pos); - ect_delete_text (text, start_pos, end_pos); -} - -static void -ect_paste_text (AtkEditableText *text, - gint position) -{ - GalA11yECell *gaec = GAL_A11Y_E_CELL (text); - - e_table_item_enter_edit (gaec->item, gaec->view_col, gaec->row); - - if (atk_text_set_caret_offset (ATK_TEXT (text), position)) - e_cell_text_paste_clipboard (gaec->cell_view, - gaec->view_col, gaec->row); -} - -static void -ect_do_action_edit (AtkAction *action) -{ - GalA11yECell *a11y = GAL_A11Y_E_CELL (action); - ETableModel *e_table_model = a11y->item->table_model; - - if (e_table_model_is_cell_editable(e_table_model, a11y->model_col, a11y->row)) { - e_table_item_enter_edit (a11y->item, a11y->view_col, a11y->row); - } -} - -/* text signal handlers */ -static void -ect_text_inserted_cb (ECellText *text, ECellView *cell_view, gint pos, gint len, gint row, gint model_col, gpointer data) -{ - GalA11yECellText *gaet; - GalA11yECell *gaec; - - if (!ect_check (data)) - return; - gaet = GAL_A11Y_E_CELL_TEXT (data); - gaec = GAL_A11Y_E_CELL (data); - - if (cell_view == gaec->cell_view && row == gaec->row && model_col == gaec->model_col) { - g_signal_emit_by_name (gaet, "text_changed::insert", pos, len); - - } -} - -static void -ect_text_deleted_cb (ECellText *text, ECellView *cell_view, gint pos, gint len, gint row, gint model_col, gpointer data) -{ - GalA11yECellText *gaet; - GalA11yECell *gaec; - if (!ect_check (data)) - return; - gaet = GAL_A11Y_E_CELL_TEXT (data); - gaec = GAL_A11Y_E_CELL (data); - if (cell_view == gaec->cell_view && row == gaec->row && model_col == gaec->model_col) { - g_signal_emit_by_name (gaet, "text_changed::delete", pos, len); - } -} - -static void -ect_atk_text_iface_init (AtkTextIface *iface) -{ - iface->get_text = ect_get_text; - iface->get_text_after_offset = ect_get_text_after_offset; - iface->get_text_at_offset = ect_get_text_at_offset; - iface->get_character_at_offset = ect_get_character_at_offset; - iface->get_text_before_offset = ect_get_text_before_offset; - iface->get_caret_offset = ect_get_caret_offset; - iface->get_run_attributes = ect_get_run_attributes; - iface->get_default_attributes = ect_get_default_attributes; - iface->get_character_extents = ect_get_character_extents; - iface->get_character_count = ect_get_character_count; - iface->get_offset_at_point = ect_get_offset_at_point; - iface->get_n_selections = ect_get_n_selections; - iface->get_selection = ect_get_selection; - iface->add_selection = ect_add_selection; - iface->remove_selection = ect_remove_selection; - iface->set_selection = ect_set_selection; - iface->set_caret_offset = ect_set_caret_offset; -} - -static void -ect_atk_editable_text_iface_init (AtkEditableTextIface *iface) -{ - iface->set_run_attributes = ect_set_run_attributes; - iface->set_text_contents = ect_set_text_contents; - iface->insert_text = ect_insert_text; - iface->copy_text = ect_copy_text; - iface->cut_text = ect_cut_text; - iface->delete_text = ect_delete_text; - iface->paste_text = ect_paste_text; -} - -static void -ect_class_init (GalA11yECellTextClass *klass) -{ - AtkObjectClass *a11y = ATK_OBJECT_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - parent_class = g_type_class_ref (PARENT_TYPE); - a11y->get_name = ect_get_name; - object_class->dispose = ect_dispose; -} - -static void -ect_action_init (GalA11yECellText *a11y) -{ - GalA11yECell *gaec = GAL_A11Y_E_CELL (a11y); - ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell); - if (ect->editable && e_table_model_is_cell_editable (gaec->cell_view->e_table_model, gaec->model_col, gaec->row)) - gal_a11y_e_cell_add_action (gaec, - _("edit"), - _("begin editing this cell"), - NULL, - (ACTION_FUNC) ect_do_action_edit); -} - -/** - * gal_a11y_e_cell_text_get_type: - * @void: - * - * Registers the &GalA11yECellText class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &GalA11yECellText class. - **/ -GType -gal_a11y_e_cell_text_get_type (void) -{ - static GType type = 0; - - if (!type) { - GTypeInfo info = { - sizeof (GalA11yECellTextClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) ect_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (GalA11yECellText), - 0, - (GInstanceInitFunc) NULL, - NULL /* value_cell_text */ - }; - - static const GInterfaceInfo atk_text_info = { - (GInterfaceInitFunc) ect_atk_text_iface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - static const GInterfaceInfo atk_editable_text_info = { - (GInterfaceInitFunc) ect_atk_editable_text_iface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - type = g_type_register_static (PARENT_TYPE, "GalA11yECellText", &info, 0); - g_type_add_interface_static (type, ATK_TYPE_TEXT, &atk_text_info); - g_type_add_interface_static (type, ATK_TYPE_EDITABLE_TEXT, &atk_editable_text_info); - gal_a11y_e_cell_type_add_action_interface (type); - } - - return type; -} - -static void -cell_text_destroyed (gpointer data) -{ - g_return_if_fail (GAL_A11Y_IS_E_CELL_TEXT (data)); - - g_object_unref (data); -} - -AtkObject * -gal_a11y_e_cell_text_new (ETableItem *item, - ECellView *cell_view, - AtkObject *parent, - gint model_col, - gint view_col, - gint row) -{ - AtkObject *a11y; - GalA11yECell *gaec; - GalA11yECellText *gaet; - ECellText *ect; - - a11y = g_object_new (gal_a11y_e_cell_text_get_type (), NULL); - - gal_a11y_e_cell_construct (a11y, - item, - cell_view, - parent, - model_col, - view_col, - row); - gaet = GAL_A11Y_E_CELL_TEXT (a11y); - - /* will be unrefed in cell_text_destroyed */ - g_object_ref (a11y); - - gaet->inserted_id = g_signal_connect (E_CELL_TEXT (((ECellView *)cell_view)->ecell), - "text_inserted", G_CALLBACK (ect_text_inserted_cb), a11y); - gaet->deleted_id = g_signal_connect (E_CELL_TEXT (((ECellView *)cell_view)->ecell), - "text_deleted", G_CALLBACK (ect_text_deleted_cb), a11y); - - g_object_weak_ref (G_OBJECT (((ECellView *)cell_view)->ecell), - (GWeakNotify) cell_text_destroyed, - a11y); - - ect_action_init (gaet); - - ect = E_CELL_TEXT (cell_view->ecell); - gaec = GAL_A11Y_E_CELL (a11y); - if (ect->editable && e_table_model_is_cell_editable (gaec->cell_view->e_table_model, gaec->model_col, gaec->row)) - gal_a11y_e_cell_add_state (gaec, ATK_STATE_EDITABLE, FALSE); - else - gal_a11y_e_cell_remove_state (gaec, ATK_STATE_EDITABLE, FALSE); - - return a11y; -} diff --git a/widgets/table/a11y/gal-a11y-e-cell-text.h b/widgets/table/a11y/gal-a11y-e-cell-text.h deleted file mode 100644 index 1a378a459c..0000000000 --- a/widgets/table/a11y/gal-a11y-e-cell-text.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Christopher James Lahey - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __GAL_A11Y_E_CELL_TEXT_H__ -#define __GAL_A11Y_E_CELL_TEXT_H__ - -#include -#include
-#include
-#include
- -#define GAL_A11Y_TYPE_E_CELL_TEXT (gal_a11y_e_cell_text_get_type ()) -#define GAL_A11Y_E_CELL_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_TEXT, GalA11yECellText)) -#define GAL_A11Y_E_CELL_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL_TEXT, GalA11yECellTextClass)) -#define GAL_A11Y_IS_E_CELL_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_TEXT)) -#define GAL_A11Y_IS_E_CELL_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_TEXT)) - -typedef struct _GalA11yECellText GalA11yECellText; -typedef struct _GalA11yECellTextClass GalA11yECellTextClass; -typedef struct _GalA11yECellTextPrivate GalA11yECellTextPrivate; - -/* This struct should actually be larger as this isn't what we derive from. - * The GalA11yECellTextPrivate comes right after the parent class structure. - **/ -struct _GalA11yECellText { - GalA11yECell object; - gint inserted_id; - gint deleted_id; -}; - -struct _GalA11yECellTextClass { - GalA11yECellClass parent_class; -}; - - -/* Standard Glib function */ -GType gal_a11y_e_cell_text_get_type (void); -AtkObject *gal_a11y_e_cell_text_new (ETableItem *item, - ECellView *cell_view, - AtkObject *parent, - gint model_col, - gint view_col, - gint row); - -#endif /* ! __GAL_A11Y_E_CELL_TEXT_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-cell-toggle.c b/widgets/table/a11y/gal-a11y-e-cell-toggle.c deleted file mode 100644 index df687f4005..0000000000 --- a/widgets/table/a11y/gal-a11y-e-cell-toggle.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include - -#include "table/e-cell-toggle.h" -#include "table/e-table-model.h" -#include - -#include "gal-a11y-e-cell-toggle.h" - -#define PARENT_TYPE (gal_a11y_e_cell_get_type ()) -static GObjectClass *parent_class; - -static void gal_a11y_e_cell_toggle_class_init (GalA11yECellToggleClass *klass); - -static void -gal_a11y_e_cell_toggle_dispose (GObject *object) -{ - GalA11yECellToggle *a11y = GAL_A11Y_E_CELL_TOGGLE (object); - - ETableModel *e_table_model = GAL_A11Y_E_CELL (a11y)->item->table_model; - - if (e_table_model && a11y->model_id > 0) { - g_signal_handler_disconnect (e_table_model, a11y->model_id); - a11y->model_id = 0; - } - - if (parent_class->dispose) - parent_class->dispose (object); -} - -GType -gal_a11y_e_cell_toggle_get_type (void) -{ - static GType type = 0; - - if (!type) - { - static const GTypeInfo tinfo = - { - sizeof (GalA11yECellToggleClass), - (GBaseInitFunc) NULL, /* base init */ - (GBaseFinalizeFunc) NULL, /* base finalize */ - (GClassInitFunc) gal_a11y_e_cell_toggle_class_init, /* class init */ - (GClassFinalizeFunc) NULL, /* class finalize */ - NULL, /* class data */ - sizeof (GalA11yECellToggle), /* instance size */ - 0, /* nb preallocs */ - NULL, /* instance init */ - NULL /* value table */ - }; - - - type = g_type_register_static (GAL_A11Y_TYPE_E_CELL, - "GalA11yECellToggle", &tinfo, 0); - gal_a11y_e_cell_type_add_action_interface (type); - - } - return type; -} - - -static void -gal_a11y_e_cell_toggle_class_init (GalA11yECellToggleClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = gal_a11y_e_cell_toggle_dispose; - parent_class = g_type_class_ref (PARENT_TYPE); -} - -static void -toggle_cell_action (GalA11yECell *cell) -{ - gint finished; - GdkEventButton event; - gint x, y, width, height; - gint row, col; - - row = cell->row; - col = cell->view_col; - - e_table_item_get_cell_geometry (cell->item, &row, &col, - &x, &y, &width, &height); - - event.x = x + width / 2 + (gint)(GNOME_CANVAS_ITEM (cell->item)->x1); - event.y = y + height / 2 + (gint)(GNOME_CANVAS_ITEM (cell->item)->y1); - - event.type = GDK_BUTTON_PRESS; - event.window = GTK_LAYOUT(GNOME_CANVAS_ITEM(cell->item)->canvas)->bin_window; - event.button = 1; - event.send_event = TRUE; - event.time = GDK_CURRENT_TIME; - event.axes = NULL; - - g_signal_emit_by_name (cell->item, "event", &event, &finished); -} - -static void -model_change_cb (ETableModel *etm, - gint col, - gint row, - GalA11yECell *cell) -{ - gint value; - - if (col == cell->model_col && row == cell->row) { - - value = GPOINTER_TO_INT ( - e_table_model_value_at (cell->cell_view->e_table_model, - cell->model_col, cell->row)); - /* Cheat gnopernicus, or it will ignore the state change signal */ - atk_focus_tracker_notify (ATK_OBJECT (cell)); - - if (value) - gal_a11y_e_cell_add_state (cell, ATK_STATE_CHECKED, TRUE); - else - gal_a11y_e_cell_remove_state (cell, ATK_STATE_CHECKED, TRUE); - } -} - - -AtkObject* -gal_a11y_e_cell_toggle_new (ETableItem *item, - ECellView *cell_view, - AtkObject *parent, - gint model_col, - gint view_col, - gint row) -{ - AtkObject *a11y; - GalA11yECell *cell; - GalA11yECellToggle *toggle_cell; - gint value; - - a11y = ATK_OBJECT(g_object_new (GAL_A11Y_TYPE_E_CELL_TOGGLE, NULL)); - - g_return_val_if_fail (a11y != NULL, NULL); - - cell = GAL_A11Y_E_CELL(a11y); - toggle_cell = GAL_A11Y_E_CELL_TOGGLE(a11y); - a11y->role = ATK_ROLE_TABLE_CELL; - - gal_a11y_e_cell_construct (a11y, - item, - cell_view, - parent, - model_col, - view_col, - row); - - gal_a11y_e_cell_add_action (cell, - _("toggle"), /* action name*/ - _("toggle the cell"), /* action description */ - NULL, /* action keybinding */ - toggle_cell_action); - - toggle_cell->model_id = g_signal_connect (item->table_model, - "model_cell_changed", - (GCallback) model_change_cb, - a11y); - - value = GPOINTER_TO_INT ( - e_table_model_value_at (cell->cell_view->e_table_model, - cell->model_col, cell->row)); - if (value) - gal_a11y_e_cell_add_state (cell, ATK_STATE_CHECKED, FALSE); - else - gal_a11y_e_cell_remove_state (cell, ATK_STATE_CHECKED, FALSE); - - return a11y; -} diff --git a/widgets/table/a11y/gal-a11y-e-cell-toggle.h b/widgets/table/a11y/gal-a11y-e-cell-toggle.h deleted file mode 100644 index 8e9b4def08..0000000000 --- a/widgets/table/a11y/gal-a11y-e-cell-toggle.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __GAL_A11Y_E_CELL_TOGGLE_H__ -#define __GAL_A11Y_E_CELL_TOGGLE_H__ - -#include -#include "gal-a11y-e-cell.h" -#include "gal-a11y-e-cell-toggle.h" - -G_BEGIN_DECLS - -#define GAL_A11Y_TYPE_E_CELL_TOGGLE (gal_a11y_e_cell_toggle_get_type ()) -#define GAL_A11Y_E_CELL_TOGGLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_TOGGLE, GalA11yECellToggle)) -#define GAL_A11Y_E_CELL_TOGGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_E_CELL_TOGGLE, GalA11yECellToggleClass)) -#define GAL_A11Y_IS_E_CELL_TOGGLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_TOGGLE)) -#define GAL_A11Y_IS_E_CELL_TOGGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_TOGGLE)) -#define GAL_A11Y_E_CELL_TOGGLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAL_A11Y_TYPE_E_CELL_TOGGLE, GalA11yECellToggleClass)) - -typedef struct _GalA11yECellToggle GalA11yECellToggle; -typedef struct _GalA11yECellToggleClass GalA11yECellToggleClass; - -struct _GalA11yECellToggle -{ - GalA11yECell parent; - gint model_id; -}; - -GType gal_a11y_e_cell_toggle_get_type (void); - -struct _GalA11yECellToggleClass -{ - GalA11yECellClass parent_class; -}; - -AtkObject *gal_a11y_e_cell_toggle_new (ETableItem *item, - ECellView *cell_view, - AtkObject *parent, - gint model_col, - gint view_col, - gint row); - -G_END_DECLS - - -#endif /* __GAL_A11Y_E_CELL_TOGGLE_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-cell-tree.c b/widgets/table/a11y/gal-a11y-e-cell-tree.c deleted file mode 100644 index aaf490c726..0000000000 --- a/widgets/table/a11y/gal-a11y-e-cell-tree.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Tim Wo - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include - -#include - -#include "a11y/gal-a11y-util.h" -#include "table/e-cell-tree.h" -#include "table/e-table.h" -#include "table/e-tree-table-adapter.h" -#include - -#include "gal-a11y-e-cell-tree.h" -#include "gal-a11y-e-cell-registry.h" - -#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yECellTreeClass)) -static AtkObjectClass *a11y_parent_class; -#define A11Y_PARENT_TYPE (gal_a11y_e_cell_get_type ()) - -#define d(x) - -static void -ectr_model_row_changed_cb (ETableModel *etm, - gint row, - GalA11yECell *a11y) -{ - ETreePath node; - ETreeModel *tree_model; - ETreeTableAdapter *tree_table_adapter; - - g_return_if_fail (a11y); - if (a11y->row != row) - return; - - node = e_table_model_value_at (etm, -1, a11y->row); - tree_model = e_table_model_value_at (etm, -2, a11y->row); - tree_table_adapter = e_table_model_value_at (etm, -3, a11y->row); - - if (e_tree_model_node_is_expandable (tree_model, node)) { - gboolean is_exp = e_tree_table_adapter_node_is_expanded (tree_table_adapter, node); - if (is_exp) - gal_a11y_e_cell_add_state (a11y, ATK_STATE_EXPANDED, TRUE); - else - gal_a11y_e_cell_remove_state (a11y, ATK_STATE_EXPANDED, TRUE); - } -} - -static void -kill_view_cb(ECellView *subcell_view, - gpointer psubcell_a11ies) -{ - GList *node; - GList *subcell_a11ies = (GList *) psubcell_a11ies; - GalA11yECell *subcell; - - for (node = subcell_a11ies; node != NULL; node = g_list_next (node)) - { - subcell = GAL_A11Y_E_CELL(node->data); - if (subcell && subcell->cell_view == subcell_view) - { - d(fprintf(stderr, "subcell_view %p deleted before the a11y object %p\n", subcell_view, subcell)); - subcell->cell_view = NULL; - } - } -} - -static void -ectr_subcell_weak_ref (GalA11yECellTree *a11y, - GalA11yECell *subcell_a11y) -{ - ECellView *subcell_view = subcell_a11y ? subcell_a11y->cell_view : NULL; - if (subcell_a11y && subcell_view && subcell_view->kill_view_cb_data) - subcell_view->kill_view_cb_data = g_list_remove(subcell_view->kill_view_cb_data, subcell_a11y); - - g_signal_handler_disconnect (GAL_A11Y_E_CELL (a11y)->item->table_model, - a11y->model_row_changed_id); - g_object_unref (a11y); -} - -static void -ectr_do_action_expand (AtkAction *action) -{ - GalA11yECell *a11y; - ETableModel *table_model; - ETreePath node; - ETreeModel *tree_model; - ETreeTableAdapter *tree_table_adapter; - - a11y = GAL_A11Y_E_CELL (action); - table_model = a11y->item->table_model; - node = e_table_model_value_at (table_model, -1, a11y->row); - tree_model = e_table_model_value_at (table_model, -2, a11y->row); - tree_table_adapter = e_table_model_value_at (table_model, -3, a11y->row); - - if (e_tree_model_node_is_expandable (tree_model, node)) { - e_tree_table_adapter_node_set_expanded (tree_table_adapter, - node, - TRUE); - gal_a11y_e_cell_add_state (a11y, ATK_STATE_EXPANDED, TRUE); - } -} - -static void -ectr_do_action_collapse (AtkAction *action) -{ - GalA11yECell *a11y; - ETableModel *table_model; - ETreePath node; - ETreeModel *tree_model; - ETreeTableAdapter *tree_table_adapter; - - a11y = GAL_A11Y_E_CELL (action); - table_model = a11y->item->table_model; - node = e_table_model_value_at (table_model, -1, a11y->row); - tree_model = e_table_model_value_at (table_model, -2, a11y->row); - tree_table_adapter = e_table_model_value_at (table_model, -3, a11y->row); - - if (e_tree_model_node_is_expandable (tree_model, node)) { - e_tree_table_adapter_node_set_expanded (tree_table_adapter, - node, - FALSE); - gal_a11y_e_cell_remove_state (a11y, ATK_STATE_EXPANDED, TRUE); - } -} - -static void -ectr_class_init (GalA11yECellTreeClass *klass) -{ - a11y_parent_class = g_type_class_ref (A11Y_PARENT_TYPE); -} - -static void -ectr_init (GalA11yECellTree *a11y) -{ -} - -GType -gal_a11y_e_cell_tree_get_type (void) -{ - static GType type = 0; - - if (!type) { - GTypeInfo info = { - sizeof (GalA11yECellTreeClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) ectr_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (GalA11yECellTree), - 0, - (GInstanceInitFunc) ectr_init, - NULL /* value_cell_text */ - }; - - type = g_type_register_static (A11Y_PARENT_TYPE, "GalA11yECellTree", &info, 0); - gal_a11y_e_cell_type_add_action_interface (type); - } - - return type; -} - -AtkObject * -gal_a11y_e_cell_tree_new (ETableItem *item, - ECellView *cell_view, - AtkObject *parent, - gint model_col, - gint view_col, - gint row) -{ - AtkObject *subcell_a11y; - GalA11yECellTree *a11y; - - ETreePath node; - ETreeModel *tree_model; - ETreeTableAdapter *tree_table_adapter; - - ECellView *subcell_view; - subcell_view = e_cell_tree_view_get_subcell_view (cell_view); - - if (subcell_view->ecell) { - subcell_a11y = gal_a11y_e_cell_registry_get_object (NULL, - item, - subcell_view, - parent, - model_col, - view_col, - row); - gal_a11y_e_cell_add_action (GAL_A11Y_E_CELL (subcell_a11y), - _("expand"), - _("expands the row in the ETree containing this cell"), - NULL, - (ACTION_FUNC)ectr_do_action_expand); - - gal_a11y_e_cell_add_action (GAL_A11Y_E_CELL (subcell_a11y), - _("collapse"), - _("collapses the row in the ETree containing this cell"), - NULL, - (ACTION_FUNC)ectr_do_action_collapse); - - /* init AtkStates for the cell's a11y object */ - node = e_table_model_value_at (item->table_model, -1, row); - tree_model = e_table_model_value_at (item->table_model, -2, row); - tree_table_adapter = e_table_model_value_at (item->table_model, -3, row); - if (e_tree_model_node_is_expandable (tree_model, node)) { - gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (subcell_a11y), ATK_STATE_EXPANDABLE, FALSE); - if (e_tree_table_adapter_node_is_expanded (tree_table_adapter, node)) - gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (subcell_a11y), ATK_STATE_EXPANDED, FALSE); - } - } - else - subcell_a11y = NULL; - - /* create a companion a11y object, this object has type GalA11yECellTree - and it connects to some signals to determine whether a tree cell is - expanded or collapsed */ - a11y = g_object_new (gal_a11y_e_cell_tree_get_type (), NULL); - gal_a11y_e_cell_construct (ATK_OBJECT (a11y), - item, - cell_view, - parent, - model_col, - view_col, - row); - a11y->model_row_changed_id = - g_signal_connect (item->table_model, "model_row_changed", - G_CALLBACK (ectr_model_row_changed_cb), - subcell_a11y); - - if (subcell_a11y && subcell_view) - { - subcell_view->kill_view_cb = kill_view_cb; - if (!g_list_find(subcell_view->kill_view_cb_data, subcell_a11y)) - subcell_view->kill_view_cb_data = g_list_append(subcell_view->kill_view_cb_data, subcell_a11y); - } - - g_object_weak_ref (G_OBJECT (subcell_a11y), (GWeakNotify) ectr_subcell_weak_ref, a11y); - - return subcell_a11y; -} diff --git a/widgets/table/a11y/gal-a11y-e-cell-tree.h b/widgets/table/a11y/gal-a11y-e-cell-tree.h deleted file mode 100644 index 497590b351..0000000000 --- a/widgets/table/a11y/gal-a11y-e-cell-tree.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Tim Wo - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __GAL_A11Y_E_CELL_TREE_H__ -#define __GAL_A11Y_E_CELL_TREE_H__ - -#include -#include
-#include
-#include "gal-a11y-e-cell.h" - -#define GAL_A11Y_TYPE_E_CELL_TREE (gal_a11y_e_cell_tree_get_type ()) -#define GAL_A11Y_E_CELL_TREE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_TREE, GalA11yECellTree)) -#define GAL_A11Y_E_CELL_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL_TREE, GalA11yECellTreeClass)) -#define GAL_A11Y_IS_E_CELL_TREE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_TREE)) -#define GAL_A11Y_IS_E_CELL_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_TREE)) - -typedef struct _GalA11yECellTree GalA11yECellTree; -typedef struct _GalA11yECellTreeClass GalA11yECellTreeClass; -typedef struct _GalA11yECellTreePrivate GalA11yECellTreePrivate; - -/* This struct should actually be larger as this isn't what we derive from. - * The GalA11yECellTreePrivate comes right after the parent class structure. - **/ -struct _GalA11yECellTree { - GalA11yECell object; - - gint model_row_changed_id; -}; - -struct _GalA11yECellTreeClass { - GalA11yECellClass parent_class; -}; - - -/* Standard Glib function */ -GType gal_a11y_e_cell_tree_get_type (void); -AtkObject *gal_a11y_e_cell_tree_new (ETableItem *item, - ECellView *cell_view, - AtkObject *parent, - gint model_col, - gint view_col, - gint row); - -#endif /* ! __GAL_A11Y_E_CELL_TREE_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-cell-vbox.c b/widgets/table/a11y/gal-a11y-e-cell-vbox.c deleted file mode 100644 index b3f92a695a..0000000000 --- a/widgets/table/a11y/gal-a11y-e-cell-vbox.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Eric Zhao - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * Copyright (C) 2004 Sun Microsystem, Inc. - * - */ - -#include - -#include - -#include "table/e-cell-vbox.h" - -#include "gal-a11y-e-cell-registry.h" -#include "gal-a11y-e-cell-vbox.h" - -static GObjectClass *parent_class; -static AtkComponentIface *component_parent_iface; -#define PARENT_TYPE (gal_a11y_e_cell_get_type ()) - -static gint -ecv_get_n_children (AtkObject *a11y) -{ - g_return_val_if_fail (GAL_A11Y_IS_E_CELL_VBOX (a11y), 0); - - return GAL_A11Y_E_CELL_VBOX (a11y)->a11y_subcell_count; -} - -static void -subcell_destroyed (gpointer data) -{ - GalA11yECell *cell; - AtkObject *parent; - GalA11yECellVbox *gaev; - - g_return_if_fail (GAL_A11Y_IS_E_CELL (data)); - cell = GAL_A11Y_E_CELL (data); - - parent = atk_object_get_parent (ATK_OBJECT (cell)); - g_return_if_fail (GAL_A11Y_IS_E_CELL_VBOX (parent)); - gaev = GAL_A11Y_E_CELL_VBOX (parent); - - if (cell->view_col < gaev->a11y_subcell_count) - gaev->a11y_subcells[cell->view_col] = NULL; -} - -static AtkObject* -ecv_ref_child (AtkObject *a11y, gint i) -{ - GalA11yECellVbox *gaev = GAL_A11Y_E_CELL_VBOX (a11y); - GalA11yECell *gaec = GAL_A11Y_E_CELL (a11y); - ECellVboxView *ecvv = (ECellVboxView *) (gaec->cell_view); - AtkObject *ret; - if (i < gaev->a11y_subcell_count) { - if (gaev->a11y_subcells[i] == NULL) { - ECellView *subcell_view; - gint model_col, row; - row = gaec->row; - model_col = ecvv->model_cols[i]; - subcell_view = ecvv->subcell_views[i]; - ret = gal_a11y_e_cell_registry_get_object (NULL, - gaec->item, - subcell_view, - a11y, - model_col, - gaec->view_col, /* FIXME should the view column use a fake one or the same as its parent? */ - row); - gaev->a11y_subcells[i] = ret; - g_object_ref (ret); - g_object_weak_ref (G_OBJECT (ret), - (GWeakNotify) subcell_destroyed, - ret); - } else { - ret = (AtkObject *) gaev->a11y_subcells[i]; - if (ATK_IS_OBJECT (ret)) - g_object_ref (ret); - else - ret = NULL; - } - } else { - ret = NULL; - } - - return ret; -} - -static void -ecv_dispose (GObject *object) -{ - GalA11yECellVbox *gaev = GAL_A11Y_E_CELL_VBOX (object); - if (gaev->a11y_subcells) - g_free (gaev->a11y_subcells); - - if (parent_class->dispose) - parent_class->dispose (object); -} - -/* AtkComponet interface */ -static AtkObject* -ecv_ref_accessible_at_point (AtkComponent *component, - gint x, - gint y, - AtkCoordType coord_type) -{ - gint x0, y0, width, height; - gint subcell_height, i; - - GalA11yECell *gaec = GAL_A11Y_E_CELL (component); - ECellVboxView *ecvv = (ECellVboxView *) (gaec->cell_view); - - atk_component_get_extents (component, &x0, &y0, &width, &height, coord_type); - x -= x0; - y -= y0; - if (x < 0 || x > width || y < 0 || y > height) - return NULL; - - for (i = 0; i < ecvv->subcell_view_count; i++) { - subcell_height = e_cell_height (ecvv->subcell_views[i], ecvv->model_cols[i], gaec->view_col, gaec->row); - if ( 0 <= y && y <= subcell_height) { - return ecv_ref_child ((AtkObject *)component, i); - } else - y -= subcell_height; - } - - return NULL; -} - -static void -ecv_class_init (GalA11yECellVboxClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - AtkObjectClass *a11y_class = ATK_OBJECT_CLASS (klass); - parent_class = g_type_class_ref (PARENT_TYPE); - - object_class->dispose = ecv_dispose; - - a11y_class->get_n_children = ecv_get_n_children; - a11y_class->ref_child = ecv_ref_child; -} - -static void -ecv_init (GalA11yECellVbox *a11y) -{ -} - -static void -ecv_atk_component_iface_init (AtkComponentIface *iface) -{ - component_parent_iface = g_type_interface_peek_parent (iface); - - iface->ref_accessible_at_point = ecv_ref_accessible_at_point; -} - -GType -gal_a11y_e_cell_vbox_get_type (void) -{ - static GType type = 0; - if (!type) { - GTypeInfo info = { - sizeof (GalA11yECellVboxClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) ecv_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (GalA11yECellVbox), - 0, - (GInstanceInitFunc) ecv_init, - NULL /* value_cell */ - }; - - static const GInterfaceInfo atk_component_info = { - (GInterfaceInitFunc) ecv_atk_component_iface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - type = g_type_register_static (PARENT_TYPE, "GalA11yECellVbox", &info, 0); - gal_a11y_e_cell_type_add_action_interface (type); - g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); - } - - return type; -} - -AtkObject *gal_a11y_e_cell_vbox_new (ETableItem *item, - ECellView *cell_view, - AtkObject *parent, - gint model_col, - gint view_col, - gint row) -{ - AtkObject *a11y; - GalA11yECell *gaec; - GalA11yECellVbox *gaev; - ECellVboxView *ecvv; - - a11y = g_object_new (gal_a11y_e_cell_vbox_get_type (), NULL); - - gal_a11y_e_cell_construct (a11y, item, cell_view, parent, model_col, view_col, row); - - gaec = GAL_A11Y_E_CELL (a11y); - gaev = GAL_A11Y_E_CELL_VBOX (a11y); - ecvv = (ECellVboxView *) (gaec->cell_view); - gaev->a11y_subcell_count = ecvv->subcell_view_count; - gaev->a11y_subcells = g_malloc0 (sizeof(AtkObject *)*gaev->a11y_subcell_count); - return a11y; -} diff --git a/widgets/table/a11y/gal-a11y-e-cell-vbox.h b/widgets/table/a11y/gal-a11y-e-cell-vbox.h deleted file mode 100644 index 657cb5d9a5..0000000000 --- a/widgets/table/a11y/gal-a11y-e-cell-vbox.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Eric Zhao - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * Copyright (C) 2004 Sun Microsystem, Inc. - * - */ - -#ifndef __GAL_A11Y_E_CELL_VBOX_H__ -#define __GAL_A11Y_E_CELL_VBOX_H__ - -#include "gal-a11y-e-cell.h" - -G_BEGIN_DECLS - -#define GAL_A11Y_TYPE_E_CELL_VBOX (gal_a11y_e_cell_vbox_get_type ()) -#define GAL_A11Y_E_CELL_VBOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_VBOX, GalA11yECellVbox)) -#define GAL_A11Y_E_CELL_VBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_E_CELL_VBOX, GalA11yECellVboxClass)) -#define GAL_A11Y_IS_E_CELL_VBOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_VBOX)) -#define GAL_A11Y_IS_E_CELL_VBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_VBOX)) -#define GAL_A11Y_E_CELL_VBOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAL_A11Y_TYPE_E_CELL_VBOX, GalA11yECellVboxClass)) - -typedef struct _GalA11yECellVbox GalA11yECellVbox; -typedef struct _GalA11yECellVboxClass GalA11yECellVboxClass; - -struct _GalA11yECellVbox -{ - GalA11yECell object; - gint a11y_subcell_count; - gpointer *a11y_subcells; -}; - -struct _GalA11yECellVboxClass -{ - GalA11yECellClass parent_class; -}; - -GType gal_a11y_e_cell_vbox_get_type (void); -AtkObject *gal_a11y_e_cell_vbox_new (ETableItem *item, - ECellView *cell_view, - AtkObject *parent, - gint model_col, - gint view_col, - gint row); - -G_END_DECLS -#endif /* __GAL_A11Y_E_CELL_VBOX_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-cell.c b/widgets/table/a11y/gal-a11y-e-cell.c deleted file mode 100644 index e09b5456d9..0000000000 --- a/widgets/table/a11y/gal-a11y-e-cell.c +++ /dev/null @@ -1,644 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Christopher James Lahey - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include - -#include - -#include - -#include "a11y/gal-a11y-util.h" -#include "table/e-table.h" -#include "table/e-tree.h" -#include - -#include "gal-a11y-e-cell.h" -#include "gal-a11y-e-cell-vbox.h" -#include "gal-a11y-e-table-item.h" - -#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yECellClass)) -static GObjectClass *parent_class; -#define PARENT_TYPE (atk_object_get_type ()) - - -#if 0 -static void -unref_item (gpointer user_data, GObject *obj_loc) -{ - GalA11yECell *a11y = GAL_A11Y_E_CELL (user_data); - a11y->item = NULL; - g_object_unref (a11y); -} - -static void -unref_cell (gpointer user_data, GObject *obj_loc) -{ - GalA11yECell *a11y = GAL_A11Y_E_CELL (user_data); - a11y->cell_view = NULL; - g_object_unref (a11y); -} -#endif - -static gboolean -is_valid (AtkObject *cell) -{ - GalA11yECell *a11y = GAL_A11Y_E_CELL (cell); - GalA11yETableItem *a11yItem = GAL_A11Y_E_TABLE_ITEM (a11y->parent); - AtkStateSet *item_ss; - gboolean ret = TRUE; - - item_ss = atk_object_ref_state_set (ATK_OBJECT (a11yItem)); - if (atk_state_set_contains_state (item_ss, ATK_STATE_DEFUNCT)) - ret = FALSE; - - g_object_unref (item_ss); - - if (ret && atk_state_set_contains_state (a11y->state_set, ATK_STATE_DEFUNCT)) - ret = FALSE; - - return ret; -} - -static void -gal_a11y_e_cell_dispose (GObject *object) -{ - GalA11yECell *a11y = GAL_A11Y_E_CELL (object); - -#if 0 - if (a11y->item) - g_object_unref (G_OBJECT (a11y->item)); /*, unref_item, a11y); */ - if (a11y->cell_view) - g_object_unref (G_OBJECT (a11y->cell_view)); /*, unref_cell, a11y); */ - if (a11y->parent) - g_object_unref (a11y->parent); -#endif - - if (a11y->state_set) { - g_object_unref (a11y->state_set); - a11y->state_set = NULL; - } - - if (parent_class->dispose) - parent_class->dispose (object); - -} - -/* Static functions */ -static G_CONST_RETURN gchar * -gal_a11y_e_cell_get_name (AtkObject * a11y) -{ - GalA11yECell *cell = GAL_A11Y_E_CELL (a11y); - ETableCol *ecol; - - if (a11y->name != NULL && strcmp (a11y->name, "")) - return a11y->name; - - if (cell->item != NULL) { - ecol = e_table_header_get_column (cell->item->header, cell->view_col); - if (ecol != NULL) - return ecol->text; - } - - return _("Table Cell"); -} - -static AtkStateSet * -gal_a11y_e_cell_ref_state_set (AtkObject *accessible) -{ - GalA11yECell *cell = GAL_A11Y_E_CELL (accessible); - - g_return_val_if_fail (cell->state_set, NULL); - - g_object_ref(cell->state_set); - - return cell->state_set; -} - -static AtkObject* -gal_a11y_e_cell_get_parent (AtkObject *accessible) -{ - GalA11yECell *a11y = GAL_A11Y_E_CELL (accessible); - return a11y->parent; -} - -static gint -gal_a11y_e_cell_get_index_in_parent (AtkObject *accessible) -{ - GalA11yECell *a11y = GAL_A11Y_E_CELL (accessible); - - if (!is_valid (accessible)) - return -1; - - return (a11y->row + 1) * a11y->item->cols + a11y->view_col; -} - - -/* Component IFace */ -static void -gal_a11y_e_cell_get_extents (AtkComponent *component, - gint *x, - gint *y, - gint *width, - gint *height, - AtkCoordType coord_type) -{ - GalA11yECell *a11y = GAL_A11Y_E_CELL (component); - GtkWidget *tableOrTree; - gint row; - gint col; - gint xval; - gint yval; - - row = a11y->row; - col = a11y->view_col; - - tableOrTree = gtk_widget_get_parent (GTK_WIDGET (a11y->item->parent.canvas)); - if (E_IS_TREE (tableOrTree)) { - e_tree_get_cell_geometry (E_TREE (tableOrTree), - row, col, &xval, &yval, - width, height); - } else { - e_table_get_cell_geometry (E_TABLE (tableOrTree), - row, col, &xval, &yval, - width, height); - } - - atk_component_get_position (ATK_COMPONENT (a11y->parent), - x, y, coord_type); - if (x && *x != G_MININT) - *x += xval; - if (y && *y != G_MININT) - *y += yval; -} - -static gboolean -gal_a11y_e_cell_grab_focus (AtkComponent *component) -{ - GalA11yECell *a11y; - gint index; - GtkWidget *toplevel; - GalA11yETableItem *a11yTableItem; - - a11y = GAL_A11Y_E_CELL (component); - - /* for e_cell_vbox's children, we just grab the e_cell_vbox */ - if (GAL_A11Y_IS_E_CELL_VBOX (a11y->parent)) { - return atk_component_grab_focus (ATK_COMPONENT (a11y->parent)); - } - - a11yTableItem = GAL_A11Y_E_TABLE_ITEM (a11y->parent); - index = atk_object_get_index_in_parent (ATK_OBJECT (a11y)); - - atk_selection_clear_selection (ATK_SELECTION (a11yTableItem)); - atk_selection_add_selection (ATK_SELECTION (a11yTableItem), index); - - gtk_widget_grab_focus (GTK_WIDGET (GNOME_CANVAS_ITEM (a11y->item)->canvas)); - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (GNOME_CANVAS_ITEM (a11y->item)->canvas)); - if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel)) - gtk_window_present (GTK_WINDOW (toplevel)); - - return TRUE; -} - -/* Table IFace */ - -static void -gal_a11y_e_cell_atk_component_iface_init (AtkComponentIface *iface) -{ - iface->get_extents = gal_a11y_e_cell_get_extents; - iface->grab_focus = gal_a11y_e_cell_grab_focus; -} - -static void -gal_a11y_e_cell_class_init (GalA11yECellClass *klass) -{ - AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - parent_class = g_type_class_ref (PARENT_TYPE); - - object_class->dispose = gal_a11y_e_cell_dispose; - - atk_object_class->get_parent = gal_a11y_e_cell_get_parent; - atk_object_class->get_index_in_parent = gal_a11y_e_cell_get_index_in_parent; - atk_object_class->ref_state_set = gal_a11y_e_cell_ref_state_set; - atk_object_class->get_name = gal_a11y_e_cell_get_name; -} - -static void -gal_a11y_e_cell_init (GalA11yECell *a11y) -{ - a11y->item = NULL; - a11y->cell_view = NULL; - a11y->parent = NULL; - a11y->model_col = -1; - a11y->view_col = -1; - a11y->row = -1; - - a11y->state_set = atk_state_set_new (); - atk_state_set_add_state (a11y->state_set, ATK_STATE_TRANSIENT); - atk_state_set_add_state (a11y->state_set, ATK_STATE_ENABLED); - atk_state_set_add_state (a11y->state_set, ATK_STATE_SENSITIVE); - atk_state_set_add_state (a11y->state_set, ATK_STATE_SELECTABLE); - atk_state_set_add_state (a11y->state_set, ATK_STATE_SHOWING); - atk_state_set_add_state (a11y->state_set, ATK_STATE_FOCUSABLE); - atk_state_set_add_state (a11y->state_set, ATK_STATE_VISIBLE); -} - - -static ActionInfo * -_gal_a11y_e_cell_get_action_info (GalA11yECell *cell, - gint index) -{ - GList *list_node; - - g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), NULL); - if (cell->action_list == NULL) - return NULL; - list_node = g_list_nth (cell->action_list, index); - if (!list_node) - return NULL; - return (ActionInfo *) (list_node->data); -} - -static void -_gal_a11y_e_cell_destroy_action_info (gpointer action_info, - gpointer user_data) -{ - ActionInfo *info = (ActionInfo *)action_info; - - g_return_if_fail (info != NULL); - g_free (info->name); - g_free (info->description); - g_free (info->keybinding); - g_free (info); -} - - -gboolean -gal_a11y_e_cell_add_action ( GalA11yECell * cell, - const gchar *action_name, - const gchar *action_description, - const gchar *action_keybinding, - ACTION_FUNC action_func) -{ - ActionInfo *info; - g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), FALSE); - info = g_new (ActionInfo, 1); - - if (action_name != NULL) - info->name = g_strdup (action_name); - else - info->name = NULL; - - if (action_description != NULL) - info->description = g_strdup (action_description); - else - info->description = NULL; - if (action_keybinding != NULL) - info->keybinding = g_strdup (action_keybinding); - else - info->keybinding = NULL; - info->do_action_func = action_func; - - cell->action_list = g_list_append (cell->action_list, (gpointer) info); - return TRUE; -} - -gboolean -gal_a11y_e_cell_remove_action (GalA11yECell *cell, - gint action_index) -{ - GList *list_node; - - g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), FALSE); - list_node = g_list_nth (cell->action_list, action_index); - if (!list_node) - return FALSE; - g_return_val_if_fail (list_node->data != NULL, FALSE); - _gal_a11y_e_cell_destroy_action_info (list_node->data, NULL); - cell->action_list = g_list_remove_link (cell->action_list, list_node); - - return TRUE; -} - -gboolean -gal_a11y_e_cell_remove_action_by_name (GalA11yECell *cell, - const gchar *action_name) -{ - GList *list_node; - gboolean action_found= FALSE; - - g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), FALSE); - for (list_node = cell->action_list; list_node && !action_found; - list_node = list_node->next) { - if (!g_ascii_strcasecmp (((ActionInfo *)(list_node->data))->name, action_name)) { - action_found = TRUE; - break; - } - } - - g_return_val_if_fail (action_found, FALSE); - _gal_a11y_e_cell_destroy_action_info (list_node->data, NULL); - cell->action_list = g_list_remove_link (cell->action_list, list_node); - - return TRUE; -} - -static gint -gal_a11y_e_cell_action_get_n_actions (AtkAction *action) -{ - GalA11yECell *cell = GAL_A11Y_E_CELL(action); - if (cell->action_list != NULL) - return g_list_length (cell->action_list); - else - return 0; -} - -static G_CONST_RETURN gchar * -gal_a11y_e_cell_action_get_name (AtkAction *action, - gint index) -{ - GalA11yECell *cell = GAL_A11Y_E_CELL(action); - ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); - - if (info == NULL) - return NULL; - return info->name; -} - -static G_CONST_RETURN gchar * -gal_a11y_e_cell_action_get_description (AtkAction *action, - gint index) -{ - GalA11yECell *cell = GAL_A11Y_E_CELL(action); - ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); - - if (info == NULL) - return NULL; - return info->description; -} - -static gboolean -gal_a11y_e_cell_action_set_description (AtkAction *action, - gint index, - const gchar *desc) -{ - GalA11yECell *cell = GAL_A11Y_E_CELL(action); - ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); - - if (info == NULL) - return FALSE; - g_free (info->description); - info->description = g_strdup (desc); - return TRUE; -} - -static G_CONST_RETURN gchar * -gal_a11y_e_cell_action_get_keybinding (AtkAction *action, - gint index) -{ - GalA11yECell *cell = GAL_A11Y_E_CELL(action); - ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); - if (info == NULL) - return NULL; - - return info->keybinding; -} - -static gboolean -idle_do_action (gpointer data) -{ - GalA11yECell *cell; - - cell = GAL_A11Y_E_CELL (data); - - if (!is_valid (ATK_OBJECT (cell))) - return FALSE; - - cell->action_idle_handler = 0; - cell->action_func (cell); - g_object_unref (cell); - - return FALSE; -} - -static gboolean -gal_a11y_e_cell_action_do_action (AtkAction *action, - gint index) -{ - GalA11yECell *cell = GAL_A11Y_E_CELL(action); - ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); - - if (!is_valid (ATK_OBJECT (action))) - return FALSE; - - if (info == NULL) - return FALSE; - g_return_val_if_fail (info->do_action_func, FALSE); - if (cell->action_idle_handler) - return FALSE; - cell->action_func = info->do_action_func; - g_object_ref (cell); - cell->action_idle_handler = g_idle_add (idle_do_action, cell); - - return TRUE; -} - -static void -gal_a11y_e_cell_atk_action_interface_init (AtkActionIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->get_n_actions = gal_a11y_e_cell_action_get_n_actions; - iface->do_action = gal_a11y_e_cell_action_do_action; - iface->get_name = gal_a11y_e_cell_action_get_name; - iface->get_description = gal_a11y_e_cell_action_get_description; - iface->set_description = gal_a11y_e_cell_action_set_description; - iface->get_keybinding = gal_a11y_e_cell_action_get_keybinding; -} - -void -gal_a11y_e_cell_type_add_action_interface (GType type) -{ - static const GInterfaceInfo atk_action_info = - { - (GInterfaceInitFunc) gal_a11y_e_cell_atk_action_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - g_type_add_interface_static (type, ATK_TYPE_ACTION, - &atk_action_info); -} - -gboolean -gal_a11y_e_cell_add_state (GalA11yECell *cell, - AtkStateType state_type, - gboolean emit_signal) -{ - if (!atk_state_set_contains_state (cell->state_set, state_type)) { - gboolean rc; - - rc = atk_state_set_add_state (cell->state_set, state_type); - /* - * The signal should only be generated if the value changed, - * not when the cell is set up. So states that are set - * initially should pass FALSE as the emit_signal argument. - */ - - if (emit_signal) { - atk_object_notify_state_change (ATK_OBJECT (cell), state_type, TRUE); - /* If state_type is ATK_STATE_VISIBLE, additional - notification */ - if (state_type == ATK_STATE_VISIBLE) - g_signal_emit_by_name (cell, "visible_data_changed"); - } - - return rc; - } - else - return FALSE; -} - -gboolean -gal_a11y_e_cell_remove_state (GalA11yECell *cell, - AtkStateType state_type, - gboolean emit_signal) -{ - if (atk_state_set_contains_state (cell->state_set, state_type)) { - gboolean rc; - - rc = atk_state_set_remove_state (cell->state_set, state_type); - /* - * The signal should only be generated if the value changed, - * not when the cell is set up. So states that are set - * initially should pass FALSE as the emit_signal argument. - */ - - if (emit_signal) { - atk_object_notify_state_change (ATK_OBJECT (cell), state_type, FALSE); - /* If state_type is ATK_STATE_VISIBLE, additional notification */ - if (state_type == ATK_STATE_VISIBLE) - g_signal_emit_by_name (cell, "visible_data_changed"); - } - - return rc; - } - else - return FALSE; -} - -/** - * gal_a11y_e_cell_get_type: - * @void: - * - * Registers the &GalA11yECell class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &GalA11yECell class. - **/ -GType -gal_a11y_e_cell_get_type (void) -{ - static GType type = 0; - - if (!type) { - GTypeInfo info = { - sizeof (GalA11yECellClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gal_a11y_e_cell_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (GalA11yECell), - 0, - (GInstanceInitFunc) gal_a11y_e_cell_init, - NULL /* value_cell */ - }; - - static const GInterfaceInfo atk_component_info = { - (GInterfaceInitFunc) gal_a11y_e_cell_atk_component_iface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - type = g_type_register_static (PARENT_TYPE, "GalA11yECell", &info, 0); - g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); - } - - return type; -} - -AtkObject * -gal_a11y_e_cell_new (ETableItem *item, - ECellView *cell_view, - AtkObject *parent, - gint model_col, - gint view_col, - gint row) -{ - AtkObject *a11y; - - a11y = g_object_new (gal_a11y_e_cell_get_type (), NULL); - - gal_a11y_e_cell_construct (a11y, - item, - cell_view, - parent, - model_col, - view_col, - row); - return a11y; -} - -void -gal_a11y_e_cell_construct (AtkObject *object, - ETableItem *item, - ECellView *cell_view, - AtkObject *parent, - gint model_col, - gint view_col, - gint row) -{ - GalA11yECell *a11y = GAL_A11Y_E_CELL (object); - a11y->item = item; - a11y->cell_view = cell_view; - a11y->parent = parent; - a11y->model_col = model_col; - a11y->view_col = view_col; - a11y->row = row; - ATK_OBJECT (a11y) ->role = ATK_ROLE_TABLE_CELL; - - if (item) - g_object_ref (G_OBJECT (item)); - -#if 0 - if (parent) - g_object_ref (parent); - - if (cell_view) - g_object_ref (G_OBJECT (cell_view)); - - -#endif -} diff --git a/widgets/table/a11y/gal-a11y-e-cell.h b/widgets/table/a11y/gal-a11y-e-cell.h deleted file mode 100644 index c61e5e2d22..0000000000 --- a/widgets/table/a11y/gal-a11y-e-cell.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Christopher James Lahey - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __GAL_A11Y_E_CELL_H__ -#define __GAL_A11Y_E_CELL_H__ - -#include -#include
-#include
- -#define GAL_A11Y_TYPE_E_CELL (gal_a11y_e_cell_get_type ()) -#define GAL_A11Y_E_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL, GalA11yECell)) -#define GAL_A11Y_E_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL, GalA11yECellClass)) -#define GAL_A11Y_IS_E_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL)) -#define GAL_A11Y_IS_E_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL)) - -typedef struct _GalA11yECell GalA11yECell; -typedef struct _GalA11yECellClass GalA11yECellClass; -typedef struct _GalA11yECellPrivate GalA11yECellPrivate; -typedef struct _ActionInfo ActionInfo; -typedef void (*ACTION_FUNC) (GalA11yECell *cell); - - -/* This struct should actually be larger as this isn't what we derive from. - * The GalA11yECellPrivate comes right after the parent class structure. - **/ -struct _GalA11yECell { - AtkObject object; - - ETableItem *item; - ECellView *cell_view; - AtkObject *parent; - gint model_col; - gint view_col; - gint row; - AtkStateSet *state_set; - GList *action_list; - gint action_idle_handler; - ACTION_FUNC action_func; -}; - -struct _GalA11yECellClass { - AtkObjectClass parent_class; -}; - -struct _ActionInfo { - gchar *name; - gchar *description; - gchar *keybinding; - ACTION_FUNC do_action_func; -}; - - - -/* Standard Glib function */ -GType gal_a11y_e_cell_get_type (void); -AtkObject *gal_a11y_e_cell_new (ETableItem *item, - ECellView *cell_view, - AtkObject *parent, - gint model_col, - gint view_col, - gint row); -void gal_a11y_e_cell_construct (AtkObject *object, - ETableItem *item, - ECellView *cell_view, - AtkObject *parent, - gint model_col, - gint view_col, - gint row); - -void gal_a11y_e_cell_type_add_action_interface (GType type); - -gboolean gal_a11y_e_cell_add_action (GalA11yECell *cell, - const gchar *action_name, - const gchar *action_description, - const gchar *action_keybinding, - ACTION_FUNC action_func); - -gboolean gal_a11y_e_cell_remove_action (GalA11yECell *cell, - gint action_id); - -gboolean gal_a11y_e_cell_remove_action_by_name (GalA11yECell *cell, - const gchar *action_name); - -gboolean gal_a11y_e_cell_add_state (GalA11yECell *cell, - AtkStateType state_type, - gboolean emit_signal); - -gboolean gal_a11y_e_cell_remove_state (GalA11yECell *cell, - AtkStateType state_type, - gboolean emit_signal); - - -#endif /* ! __GAL_A11Y_E_CELL_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-table-click-to-add-factory.c b/widgets/table/a11y/gal-a11y-e-table-click-to-add-factory.c deleted file mode 100644 index 0ebb3c4621..0000000000 --- a/widgets/table/a11y/gal-a11y-e-table-click-to-add-factory.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Yuedong Du - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include - -#include - -#include "table/e-table.h" -#include "table/e-table-click-to-add.h" - -#include "gal-a11y-e-table.h" -#include "gal-a11y-e-table-click-to-add.h" -#include "gal-a11y-e-table-click-to-add-factory.h" - -#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETableClickToAddFactoryClass)) -static AtkObjectFactoryClass *parent_class; -#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY) - -/* Static functions */ - -static GType -gal_a11y_e_table_click_to_add_factory_get_accessible_type (void) -{ - return GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD; -} - -static AtkObject* -gal_a11y_e_table_click_to_add_factory_create_accessible (GObject *obj) -{ - AtkObject * atk_object; - - g_return_val_if_fail (E_IS_TABLE_CLICK_TO_ADD(obj), NULL); - - atk_object = gal_a11y_e_table_click_to_add_new (obj); - - return atk_object; -} - -static void -gal_a11y_e_table_click_to_add_factory_class_init (GalA11yETableClickToAddFactoryClass *klass) -{ - AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass); - - parent_class = g_type_class_ref (PARENT_TYPE); - - factory_class->create_accessible = gal_a11y_e_table_click_to_add_factory_create_accessible; - factory_class->get_accessible_type = gal_a11y_e_table_click_to_add_factory_get_accessible_type; -} - -static void -gal_a11y_e_table_click_to_add_factory_init (GalA11yETableClickToAddFactory *factory) -{ -} - -/** - * gal_a11y_e_table_factory_get_type: - * @void: - * - * Registers the &GalA11yETableFactory class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &GalA11yETableFactory class. - **/ -GType -gal_a11y_e_table_click_to_add_factory_get_type (void) -{ - static GType type = 0; - - if (!type) { - GTypeInfo info = { - sizeof (GalA11yETableClickToAddFactoryClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gal_a11y_e_table_click_to_add_factory_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (GalA11yETableClickToAddFactory), - 0, - (GInstanceInitFunc) gal_a11y_e_table_click_to_add_factory_init, - NULL /* value_table */ - }; - - type = g_type_register_static (PARENT_TYPE, "GalA11yETableClickToAddFactory", &info, 0); - } - - return type; -} diff --git a/widgets/table/a11y/gal-a11y-e-table-click-to-add-factory.h b/widgets/table/a11y/gal-a11y-e-table-click-to-add-factory.h deleted file mode 100644 index 9f249f0178..0000000000 --- a/widgets/table/a11y/gal-a11y-e-table-click-to-add-factory.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Yuedong Du - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __GAL_A11Y_E_TABLE_CLICK_TO_ADD_FACTORY_H__ -#define __GAL_A11Y_E_TABLE_CLICK_TO_ADD_FACTORY_H__ - -#include -#include - -#define GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY (gal_a11y_e_table_item_factory_get_type ()) -#define GAL_A11Y_E_TABLE_CLICK_TO_ADD_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY, GalA11yETableClickToAddFactory)) -#define GAL_A11Y_E_TABLE_CLICK_TO_ADD_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY, GalA11yETableClickToAddFactoryClass)) -#define GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY)) -#define GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY)) - -typedef struct _GalA11yETableClickToAddFactory GalA11yETableClickToAddFactory; -typedef struct _GalA11yETableClickToAddFactoryClass GalA11yETableClickToAddFactoryClass; - -struct _GalA11yETableClickToAddFactory { - AtkObject object; -}; - -struct _GalA11yETableClickToAddFactoryClass { - AtkObjectClass parent_class; -}; - - -/* Standard Glib function */ -GType gal_a11y_e_table_click_to_add_factory_get_type (void); - -#endif diff --git a/widgets/table/a11y/gal-a11y-e-table-click-to-add.c b/widgets/table/a11y/gal-a11y-e-table-click-to-add.c deleted file mode 100644 index 8a8fe56796..0000000000 --- a/widgets/table/a11y/gal-a11y-e-table-click-to-add.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Yuedong Du - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include - -#include - -#include "a11y/gal-a11y-util.h" -#include "table/e-table-click-to-add.h" -#include "table/e-table-group.h" -#include "table/e-table-group-leaf.h" -#include - -#include "gal-a11y-e-table-click-to-add.h" -#include "gal-a11y-e-table-click-to-add-factory.h" - -static AtkObjectClass *parent_class; -static GType parent_type; -static gint priv_offset; -#define GET_PRIVATE(object) ((GalA11yETableClickToAddPrivate *) (((gchar *) object) + priv_offset)) -#define PARENT_TYPE (parent_type) - -struct _GalA11yETableClickToAddPrivate { - gpointer rect; - gpointer row; -}; - - -static gint -etcta_get_n_actions (AtkAction *action) -{ - return 1; -} - -static G_CONST_RETURN gchar * -etcta_get_description (AtkAction *action, - gint i) -{ - if (i == 0) - return _("click to add"); - - return NULL; -} - -static G_CONST_RETURN gchar * -etcta_action_get_name (AtkAction *action, gint i) -{ - if (i == 0) - return _("click"); - - return NULL; -} - - -static gboolean -idle_do_action (gpointer data) -{ - GdkEventButton event; - ETableClickToAdd * etcta; - gint finished; - - g_return_val_if_fail ( data!= NULL, FALSE); - - etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (data))); - g_return_val_if_fail (etcta, FALSE); - - event.x = 0; - event.y = 0; - - event.type = GDK_BUTTON_PRESS; - event.window = GTK_LAYOUT(GNOME_CANVAS_ITEM(etcta)->canvas)->bin_window; - event.button = 1; - event.send_event = TRUE; - event.time = GDK_CURRENT_TIME; - event.axes = NULL; - - g_signal_emit_by_name (etcta, "event", &event, &finished); - - return FALSE; -} - -static gboolean -etcta_do_action (AtkAction * action, gint i) -{ - g_return_val_if_fail (i == 0, FALSE); - - g_idle_add (idle_do_action, action); - - return TRUE; -} - -static void -atk_action_interface_init (AtkActionIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->do_action = etcta_do_action; - iface->get_n_actions = etcta_get_n_actions; - iface->get_description = etcta_get_description; - iface->get_name = etcta_action_get_name; -} - - -static G_CONST_RETURN gchar * -etcta_get_name (AtkObject *obj) -{ - ETableClickToAdd * etcta; - - g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD (obj), NULL); - - etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(obj))); - if (etcta && etcta->message != NULL) - return etcta->message; - - return _("click to add"); -} - -static gint -etcta_get_n_children (AtkObject *accessible) -{ - return 1; -} - -static AtkObject* -etcta_ref_child (AtkObject *accessible, - gint i) -{ - AtkObject * atk_obj = NULL; - ETableClickToAdd * etcta; - - if ( i != 0 ) - return NULL; - - etcta = E_TABLE_CLICK_TO_ADD(atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible))); - - g_return_val_if_fail (etcta, NULL); - - if (etcta->rect) { - atk_obj = atk_gobject_accessible_for_object (G_OBJECT(etcta->rect)); - } else if (etcta->row) { - atk_obj = atk_gobject_accessible_for_object (G_OBJECT(etcta->row)); - } - - g_object_ref (atk_obj); - - return atk_obj; -} - -static AtkStateSet * -etcta_ref_state_set (AtkObject *accessible) -{ - AtkStateSet * state_set = NULL; - - state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (accessible); - if (state_set != NULL) { - atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE); - atk_state_set_add_state (state_set, ATK_STATE_SHOWING); - } - - return state_set; -} - -static void -etcta_class_init (GalA11yETableClickToAddClass *klass) -{ - AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass); - - parent_class = g_type_class_ref (PARENT_TYPE); - - atk_object_class->get_name = etcta_get_name; - atk_object_class->get_n_children = etcta_get_n_children; - atk_object_class->ref_child = etcta_ref_child; - atk_object_class->ref_state_set = etcta_ref_state_set; -} - -static void -etcta_init (GalA11yETableClickToAdd *a11y) -{ -} - -/** - * gal_a11y_e_table_click_to_add_get_type: - * @void: - * - * Registers the &GalA11yETableClickToAdd class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &GalA11yETableClickToAdd class. - **/ -GType -gal_a11y_e_table_click_to_add_get_type (void) -{ - static GType type = 0; - - if (!type) { - AtkObjectFactory *factory; - - GTypeInfo info = { - sizeof (GalA11yETableClickToAddClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) etcta_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (GalA11yETableClickToAdd), - 0, - (GInstanceInitFunc) etcta_init, - NULL /* value_table */ - }; - - static const GInterfaceInfo atk_action_info = { - (GInterfaceInitFunc) atk_action_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - factory = atk_registry_get_factory (atk_get_default_registry (), GNOME_TYPE_CANVAS_ITEM); - - parent_type = atk_object_factory_get_accessible_type (factory); - type = gal_a11y_type_register_static_with_private (PARENT_TYPE, - "GalA11yETableClickToAdd", &info, 0, - sizeof(GalA11yETableClickToAddPrivate), &priv_offset); - - g_type_add_interface_static (type, ATK_TYPE_ACTION, &atk_action_info); - - } - - return type; -} - -static gboolean -etcta_event (GnomeCanvasItem *item, GdkEvent *e, gpointer data) -{ - ETableClickToAdd *etcta = E_TABLE_CLICK_TO_ADD (item); - GalA11yETableClickToAdd *a11y; - GalA11yETableClickToAddPrivate *priv; - - g_return_val_if_fail (item, TRUE); - - g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD(data), FALSE); - a11y = GAL_A11Y_E_TABLE_CLICK_TO_ADD (data); - - priv = GET_PRIVATE (a11y); - - /* rect replaced by row. */ - if (etcta->rect == NULL && priv->rect != NULL) { - g_signal_emit_by_name (a11y, "children_changed::remove", 0, NULL, NULL); - - } - /* row inserted, and/or replaced by a new row. */ - if (etcta->row != NULL && priv->row == NULL) { - g_signal_emit_by_name (a11y, "children_changed::add", 0, NULL, NULL); - } else if (etcta->row != NULL && priv->row != NULL && etcta->row != priv->row) { - g_signal_emit_by_name (a11y, "children_changed::remove", 0, NULL, NULL); - g_signal_emit_by_name (a11y, "children_changed::add", 0, NULL, NULL); - } - - - priv->rect = etcta->rect; - priv->row = etcta->row; - - return FALSE; -} - -static void -etcta_selection_cursor_changed (ESelectionModel *esm, gint row, gint col, - GalA11yETableClickToAdd *a11y) -{ - ETableClickToAdd *etcta; - AtkObject *row_a11y; - - etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(a11y))); - - if (etcta == NULL || etcta->row == NULL) - return; - - row_a11y = atk_gobject_accessible_for_object (G_OBJECT(etcta->row)); - if (row_a11y) { - AtkObject *cell_a11y = g_object_get_data (G_OBJECT(row_a11y), "gail-focus-object"); - if (cell_a11y) { - atk_focus_tracker_notify (cell_a11y); - } - } -} - -AtkObject * -gal_a11y_e_table_click_to_add_new (GObject *widget) -{ - GalA11yETableClickToAdd *a11y; - ETableClickToAdd * etcta; - GalA11yETableClickToAddPrivate *priv; - - g_return_val_if_fail (widget != NULL, NULL); - - a11y = g_object_new (gal_a11y_e_table_click_to_add_get_type (), NULL); - priv = GET_PRIVATE (a11y); - - etcta = E_TABLE_CLICK_TO_ADD(widget); - - - atk_object_initialize (ATK_OBJECT (a11y), etcta); - - priv->rect = etcta->rect; - priv->row = etcta->row; - - - g_signal_connect_after (G_OBJECT(widget), "event", - G_CALLBACK (etcta_event), a11y); - - g_signal_connect (etcta->selection, "cursor_changed", - G_CALLBACK (etcta_selection_cursor_changed), a11y); - - return ATK_OBJECT (a11y); -} - -void -gal_a11y_e_table_click_to_add_init (void) -{ - if (atk_get_root ()) - atk_registry_set_factory_type (atk_get_default_registry (), - E_TABLE_CLICK_TO_ADD_TYPE, - gal_a11y_e_table_click_to_add_factory_get_type ()); - -} - diff --git a/widgets/table/a11y/gal-a11y-e-table-click-to-add.h b/widgets/table/a11y/gal-a11y-e-table-click-to-add.h deleted file mode 100644 index 17d6940d08..0000000000 --- a/widgets/table/a11y/gal-a11y-e-table-click-to-add.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __GAL_A11Y_E_TABLE_CLICK_TO_ADD_H__ -#define __GAL_A11Y_E_TABLE_CLICK_TO_ADD_H__ - -#include -#include
-#include - -#define GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD (gal_a11y_e_table_click_to_add_get_type ()) -#define GAL_A11Y_E_TABLE_CLICK_TO_ADD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD, GalA11yETableClickToAdd)) -#define GAL_A11Y_E_TABLE_CLICK_TO_ADD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD, GalA11yETableClickToAddClass)) -#define GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD)) -#define GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD)) - -typedef struct _GalA11yETableClickToAdd GalA11yETableClickToAdd; -typedef struct _GalA11yETableClickToAddClass GalA11yETableClickToAddClass; -typedef struct _GalA11yETableClickToAddPrivate GalA11yETableClickToAddPrivate; - -/* This struct should actually be larger as this isn't what we derive from. - * The GalA11yETableClickToAddPrivate comes right after the parent class structure. - **/ -struct _GalA11yETableClickToAdd { - AtkGObjectAccessible parent; -}; - -struct _GalA11yETableClickToAddClass { - AtkGObjectAccessibleClass parent_class; -}; - -/* Standard Glib function */ -GType gal_a11y_e_table_click_to_add_get_type (void); -AtkObject *gal_a11y_e_table_click_to_add_new (GObject *widget); - -void gal_a11y_e_table_click_to_add_init (void); -#endif /* ! __GAL_A11Y_E_TABLE_CLICK_TO_ADD_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-table-column-header.c b/widgets/table/a11y/gal-a11y-e-table-column-header.c deleted file mode 100644 index 41e6ab0fca..0000000000 --- a/widgets/table/a11y/gal-a11y-e-table-column-header.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Li Yuan - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include -#include -#include -#include -#include "table/e-table-header-item.h" -#include "a11y/gal-a11y-util.h" -#include "gal-a11y-e-table-column-header.h" - -static GObjectClass *parent_class; -static gint priv_offset; - -#define GET_PRIVATE(object) ((GalA11yETableColumnHeaderPrivate *) (((gchar *) object) + priv_offset)) -#define PARENT_TYPE (atk_gobject_accessible_get_type ()) - -struct _GalA11yETableColumnHeaderPrivate { - ETableItem *item; - AtkObject *parent; - AtkStateSet *state_set; -}; - -static void -etch_init (GalA11yETableColumnHeader *a11y) -{ - GET_PRIVATE (a11y)->item = NULL; - GET_PRIVATE (a11y)->parent = NULL; - GET_PRIVATE (a11y)->state_set = NULL; -} - -static AtkStateSet * -gal_a11y_e_table_column_header_ref_state_set (AtkObject *accessible) -{ - GalA11yETableColumnHeaderPrivate *priv = GET_PRIVATE (accessible); - - g_return_val_if_fail (priv->state_set, NULL); - - g_object_ref(priv->state_set); - - return priv->state_set; -} - -static void -gal_a11y_e_table_column_header_real_initialize (AtkObject *obj, gpointer data) -{ - ATK_OBJECT_CLASS (parent_class)->initialize (obj, data); -} - -static void -gal_a11y_e_table_column_header_dispose (GObject *object) -{ - GalA11yETableColumnHeader *a11y = GAL_A11Y_E_TABLE_COLUMN_HEADER (object); - GalA11yETableColumnHeaderPrivate *priv = GET_PRIVATE (a11y); - - if (priv->state_set) { - g_object_unref (priv->state_set); - priv->state_set = NULL; - } - - if (parent_class->dispose) - parent_class->dispose (object); - -} - -static void -etch_class_init (GalA11yETableColumnHeaderClass *klass) -{ - AtkObjectClass *class = ATK_OBJECT_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - parent_class = g_type_class_ref (PARENT_TYPE); - - object_class->dispose = gal_a11y_e_table_column_header_dispose; - - class->ref_state_set = gal_a11y_e_table_column_header_ref_state_set; - class->initialize = gal_a11y_e_table_column_header_real_initialize; -} - -inline static GObject * -etch_a11y_get_gobject (AtkGObjectAccessible *accessible) -{ - return atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible)); -} - -static gboolean -gal_a11y_e_table_column_header_do_action (AtkAction *action, - gint i) -{ - gboolean return_value = TRUE; - GtkWidget *widget; - GalA11yETableColumnHeader *a11y; - ETableHeaderItem *ethi; - ETableItem *item; - ETableCol *col; - - switch (i) { - case 0: - a11y = GAL_A11Y_E_TABLE_COLUMN_HEADER (action); - col = E_TABLE_COL (etch_a11y_get_gobject (ATK_GOBJECT_ACCESSIBLE (a11y))); - item = GET_PRIVATE (a11y)->item; - widget = gtk_widget_get_parent (GTK_WIDGET (item->parent.canvas)); - if (E_IS_TREE (widget)) { - ethi = E_TABLE_HEADER_ITEM (e_tree_get_header_item (E_TREE (widget))); - } - else if (E_IS_TABLE (widget)) - ethi = E_TABLE_HEADER_ITEM (E_TABLE (widget)->header_item); - else - break; - ethi_change_sort_state (ethi, col); - default: - return_value = FALSE; - break; - } - return return_value; -} - -static gint -gal_a11y_e_table_column_header_get_n_actions (AtkAction *action) -{ - return 1; -} - -static G_CONST_RETURN gchar * -gal_a11y_e_table_column_header_action_get_name (AtkAction *action, - gint i) -{ - G_CONST_RETURN gchar *return_value; - - switch (i) { - case 0: - return_value = _("sort"); - break; - default: - return_value = NULL; - break; - } - return return_value; -} - -static void -atk_action_interface_init (AtkActionIface *iface) -{ - g_return_if_fail (iface != NULL); - - iface->do_action = gal_a11y_e_table_column_header_do_action; - iface->get_n_actions = gal_a11y_e_table_column_header_get_n_actions; - iface->get_name = gal_a11y_e_table_column_header_action_get_name; -} - -GType -gal_a11y_e_table_column_header_get_type (void) -{ - static GType type = 0; - - if (!type) { - GTypeInfo info = { - sizeof (GalA11yETableColumnHeaderClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) etch_class_init, - (GClassFinalizeFunc) NULL, - NULL, - sizeof (GalA11yETableColumnHeader), - 0, - (GInstanceInitFunc) etch_init, - NULL - }; - static const GInterfaceInfo atk_action_info = { - (GInterfaceInitFunc) atk_action_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yETableColumnHeader", &info, 0, - sizeof (GalA11yETableColumnHeaderPrivate), &priv_offset); - - g_type_add_interface_static (type, ATK_TYPE_ACTION, &atk_action_info); - } - - return type; -} - -AtkObject * -gal_a11y_e_table_column_header_new (ETableCol *ecol, ETableItem *item) -{ - GalA11yETableColumnHeader *a11y; - AtkObject *accessible; - - g_return_val_if_fail (E_IS_TABLE_COL (ecol), NULL); - - a11y = g_object_new (gal_a11y_e_table_column_header_get_type(), NULL); - accessible = ATK_OBJECT (a11y); - atk_object_initialize (accessible, ecol); - - GET_PRIVATE (a11y)->item = item; - GET_PRIVATE (a11y)->state_set = atk_state_set_new (); - - atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_VISIBLE); - atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_SHOWING); - atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_SENSITIVE); - atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_ENABLED); - - if (ecol->text) - atk_object_set_name (accessible, ecol->text); - atk_object_set_role (accessible, ATK_ROLE_TABLE_COLUMN_HEADER); - - return ATK_OBJECT (a11y); -} diff --git a/widgets/table/a11y/gal-a11y-e-table-column-header.h b/widgets/table/a11y/gal-a11y-e-table-column-header.h deleted file mode 100644 index d0b1ff5aeb..0000000000 --- a/widgets/table/a11y/gal-a11y-e-table-column-header.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Li Yuan - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - - -#ifndef __GAL_A11Y_E_TABLE_COLUMN_HEADER_H__ -#define __GAL_A11Y_E_TABLE_COLUMN_HEADER_H__ - -#include -#include - -#define GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER (gal_a11y_e_table_column_header_get_type ()) -#define GAL_A11Y_E_TABLE_COLUMN_HEADER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER, GalA11yETableColumnHeader)) -#define GAL_A11Y_E_TABLE_COLUMN_HEADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER, GalA11yETableColumnHeaderClass)) -#define GAL_A11Y_IS_E_TABLE_COLUMN_HEADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER)) -#define GAL_A11Y_IS_E_TABLE_COLUMN_HEADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER)) - -typedef struct _GalA11yETableColumnHeader GalA11yETableColumnHeader; -typedef struct _GalA11yETableColumnHeaderClass GalA11yETableColumnHeaderClass; -typedef struct _GalA11yETableColumnHeaderPrivate GalA11yETableColumnHeaderPrivate; - -struct _GalA11yETableColumnHeader { - AtkGObjectAccessible parent; -}; - -struct _GalA11yETableColumnHeaderClass { - AtkGObjectAccessibleClass parent_class; -}; - - -/* Standard Glib function */ -GType gal_a11y_e_table_column_header_get_type (void); -AtkObject *gal_a11y_e_table_column_header_new (ETableCol *etc, ETableItem *item); -void gal_a11y_e_table_column_header_init (void); - -#endif /* ! __GAL_A11Y_E_TABLE_COLUMN_HEADER_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-table-factory.c b/widgets/table/a11y/gal-a11y-e-table-factory.c deleted file mode 100644 index f459f3b67c..0000000000 --- a/widgets/table/a11y/gal-a11y-e-table-factory.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Christopher James Lahey - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include - -#include "gal-a11y-e-table.h" -#include "gal-a11y-e-table-factory.h" - -#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETableFactoryClass)) -static AtkObjectFactoryClass *parent_class; -#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY) - -/* Static functions */ - -static GType -gal_a11y_e_table_factory_get_accessible_type (void) -{ - return GAL_A11Y_TYPE_E_TABLE; -} - -static AtkObject* -gal_a11y_e_table_factory_create_accessible (GObject *obj) -{ - AtkObject *accessible; - - accessible = gal_a11y_e_table_new (obj); - - return accessible; -} - -static void -gal_a11y_e_table_factory_class_init (GalA11yETableFactoryClass *klass) -{ - AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass); - - parent_class = g_type_class_ref (PARENT_TYPE); - - factory_class->create_accessible = gal_a11y_e_table_factory_create_accessible; - factory_class->get_accessible_type = gal_a11y_e_table_factory_get_accessible_type; -} - -static void -gal_a11y_e_table_factory_init (GalA11yETableFactory *factory) -{ -} - -/** - * gal_a11y_e_table_factory_get_type: - * @void: - * - * Registers the &GalA11yETableFactory class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &GalA11yETableFactory class. - **/ -GType -gal_a11y_e_table_factory_get_type (void) -{ - static GType type = 0; - - if (!type) { - GTypeInfo info = { - sizeof (GalA11yETableFactoryClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gal_a11y_e_table_factory_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (GalA11yETableFactory), - 0, - (GInstanceInitFunc) gal_a11y_e_table_factory_init, - NULL /* value_table */ - }; - - type = g_type_register_static (PARENT_TYPE, "GalA11yETableFactory", &info, 0); - } - - return type; -} diff --git a/widgets/table/a11y/gal-a11y-e-table-factory.h b/widgets/table/a11y/gal-a11y-e-table-factory.h deleted file mode 100644 index 3439cf0bdc..0000000000 --- a/widgets/table/a11y/gal-a11y-e-table-factory.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Christopher James Lahey - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __GAL_A11Y_E_TABLE_FACTORY_H__ -#define __GAL_A11Y_E_TABLE_FACTORY_H__ - -#include -#include - -#define GAL_A11Y_TYPE_E_TABLE_FACTORY (gal_a11y_e_table_factory_get_type ()) -#define GAL_A11Y_E_TABLE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_FACTORY, GalA11yETableFactory)) -#define GAL_A11Y_E_TABLE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_FACTORY, GalA11yETableFactoryClass)) -#define GAL_A11Y_IS_E_TABLE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_FACTORY)) -#define GAL_A11Y_IS_E_TABLE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_FACTORY)) - -typedef struct _GalA11yETableFactory GalA11yETableFactory; -typedef struct _GalA11yETableFactoryClass GalA11yETableFactoryClass; - -struct _GalA11yETableFactory { - AtkObject object; -}; - -struct _GalA11yETableFactoryClass { - AtkObjectClass parent_class; -}; - - -/* Standard Glib function */ -GType gal_a11y_e_table_factory_get_type (void); - -#endif /* ! __GAL_A11Y_E_TABLE_FACTORY_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-table-item-factory.c b/widgets/table/a11y/gal-a11y-e-table-item-factory.c deleted file mode 100644 index fa14652788..0000000000 --- a/widgets/table/a11y/gal-a11y-e-table-item-factory.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Yuedong Du - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include - -#include - -#include "table/e-table.h" -#include "table/e-tree.h" - -#include "gal-a11y-e-table.h" -#include "gal-a11y-e-table-item.h" -#include "gal-a11y-e-table-item-factory.h" - -#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETableItemFactoryClass)) -static AtkObjectFactoryClass *parent_class; -#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY) - -/* Static functions */ - -static GType -gal_a11y_e_table_item_factory_get_accessible_type (void) -{ - return GAL_A11Y_TYPE_E_TABLE_ITEM; -} - -static AtkObject* -gal_a11y_e_table_item_factory_create_accessible (GObject *obj) -{ - AtkObject *accessible; - - g_return_val_if_fail (E_IS_TABLE_ITEM(obj), NULL); - accessible = gal_a11y_e_table_item_new (E_TABLE_ITEM (obj)); - - return accessible; -} - -static void -gal_a11y_e_table_item_factory_class_init (GalA11yETableItemFactoryClass *klass) -{ - AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass); - - parent_class = g_type_class_ref (PARENT_TYPE); - - factory_class->create_accessible = gal_a11y_e_table_item_factory_create_accessible; - factory_class->get_accessible_type = gal_a11y_e_table_item_factory_get_accessible_type; -} - -static void -gal_a11y_e_table_item_factory_init (GalA11yETableItemFactory *factory) -{ -} - -/** - * gal_a11y_e_table_factory_get_type: - * @void: - * - * Registers the &GalA11yETableFactory class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &GalA11yETableFactory class. - **/ -GType -gal_a11y_e_table_item_factory_get_type (void) -{ - static GType type = 0; - - if (!type) { - GTypeInfo info = { - sizeof (GalA11yETableItemFactoryClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gal_a11y_e_table_item_factory_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (GalA11yETableItemFactory), - 0, - (GInstanceInitFunc) gal_a11y_e_table_item_factory_init, - NULL /* value_table */ - }; - - type = g_type_register_static (PARENT_TYPE, "GalA11yETableItemFactory", &info, 0); - } - - return type; -} diff --git a/widgets/table/a11y/gal-a11y-e-table-item-factory.h b/widgets/table/a11y/gal-a11y-e-table-item-factory.h deleted file mode 100644 index f27c491a4d..0000000000 --- a/widgets/table/a11y/gal-a11y-e-table-item-factory.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Yuedong Du - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __GAL_A11Y_E_TABLE_ITEM_FACTORY_H__ -#define __GAL_A11Y_E_TABLE_ITEM_FACTORY_H__ - -#include -#include - -#define GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY (gal_a11y_e_table_item_factory_get_type ()) -#define GAL_A11Y_E_TABLE_ITEM_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY, GalA11yETableItemFactory)) -#define GAL_A11Y_E_TABLE_ITEM_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY, GalA11yETableItemFactoryClass)) -#define GAL_A11Y_IS_E_TABLE_ITEM_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY)) -#define GAL_A11Y_IS_E_TABLE_ITEM_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY)) - -typedef struct _GalA11yETableItemFactory GalA11yETableItemFactory; -typedef struct _GalA11yETableItemFactoryClass GalA11yETableItemFactoryClass; - -struct _GalA11yETableItemFactory { - AtkObject object; -}; - -struct _GalA11yETableItemFactoryClass { - AtkObjectClass parent_class; -}; - - -/* Standard Glib function */ -GType gal_a11y_e_table_item_factory_get_type (void); - -#endif /* ! __GAL_A11Y_E_TABLE_FACTORY_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-table-item.c b/widgets/table/a11y/gal-a11y-e-table-item.c deleted file mode 100644 index 561b9a84d6..0000000000 --- a/widgets/table/a11y/gal-a11y-e-table-item.c +++ /dev/null @@ -1,1327 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Christopher James Lahey - * Bolian Yin - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include - -#include - -#include - -#include "a11y/gal-a11y-util.h" -#include "table/e-table-click-to-add.h" -#include "table/e-table-subset.h" -#include "table/e-table.h" -#include "table/e-tree.h" -#include "misc/e-canvas.h" -#include "misc/e-selection-model.h" - -#include "gal-a11y-e-table-item.h" -#include "gal-a11y-e-table-item-factory.h" -#include "gal-a11y-e-table-click-to-add.h" -#include "gal-a11y-e-cell-registry.h" -#include "gal-a11y-e-cell.h" -#include "gal-a11y-e-table-column-header.h" - -#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yETableItemClass)) -static GObjectClass *parent_class; -static AtkComponentIface *component_parent_iface; -static GType parent_type; -static gint priv_offset; -static GQuark quark_accessible_object = 0; -#define GET_PRIVATE(object) ((GalA11yETableItemPrivate *) (((gchar *) object) + priv_offset)) -#define PARENT_TYPE (parent_type) - -struct _GalA11yETableItemPrivate { - gint cols; - gint rows; - gint selection_change_id; - gint cursor_change_id; - ETableCol ** columns; - ESelectionModel *selection; - AtkStateSet *state_set; - GtkWidget *widget; -}; - -static gboolean gal_a11y_e_table_item_ref_selection (GalA11yETableItem *a11y, - ESelectionModel *selection); -static gboolean gal_a11y_e_table_item_unref_selection (GalA11yETableItem *a11y); - -static AtkObject* eti_ref_at (AtkTable *table, gint row, gint column); - -static void -item_destroyed (GtkObject *item, gpointer user_data) -{ - GalA11yETableItem *a11y = GAL_A11Y_E_TABLE_ITEM (user_data); - GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y); - - atk_state_set_add_state (priv->state_set, ATK_STATE_DEFUNCT); - atk_object_notify_state_change (ATK_OBJECT (a11y), ATK_STATE_DEFUNCT, TRUE); - - if (priv->selection) - gal_a11y_e_table_item_unref_selection (a11y); - -} - -static AtkStateSet * -eti_ref_state_set (AtkObject *accessible) -{ - GalA11yETableItemPrivate *priv = GET_PRIVATE (accessible); - - g_object_ref(priv->state_set); - - return priv->state_set; -} - -inline static gint -view_to_model_row(ETableItem *eti, gint row) -{ - if (eti->uses_source_model) { - ETableSubset *etss = E_TABLE_SUBSET(eti->table_model); - if (row >= 0 && row < etss->n_map) { - eti->row_guess = row; - return etss->map_table[row]; - } else - return -1; - } else - return row; -} - -inline static gint -view_to_model_col(ETableItem *eti, gint col) -{ - ETableCol *ecol = e_table_header_get_column (eti->header, col); - return ecol ? ecol->col_idx : -1; -} - -inline static gint -model_to_view_row(ETableItem *eti, gint row) -{ - gint i; - if (row == -1) - return -1; - if (eti->uses_source_model) { - ETableSubset *etss = E_TABLE_SUBSET(eti->table_model); - if (eti->row_guess >= 0 && eti->row_guess < etss->n_map) { - if (etss->map_table[eti->row_guess] == row) { - return eti->row_guess; - } - } - for (i = 0; i < etss->n_map; i++) { - if (etss->map_table[i] == row) - return i; - } - return -1; - } else - return row; -} - -inline static gint -model_to_view_col(ETableItem *eti, gint col) -{ - gint i; - if (col == -1) - return -1; - for (i = 0; i < eti->cols; i++) { - ETableCol *ecol = e_table_header_get_column (eti->header, i); - if (ecol->col_idx == col) - return i; - } - return -1; -} - -inline static GObject * -eti_a11y_get_gobject (AtkObject *accessible) -{ - return atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible)); -} - -static void -eti_a11y_reset_focus_object (GalA11yETableItem *a11y, ETableItem *item, gboolean notify) -{ - ESelectionModel * esm; - gint cursor_row, cursor_col, view_row, view_col; - AtkObject *cell, *old_cell; - - esm = item->selection; - g_return_if_fail (esm); - - cursor_row = e_selection_model_cursor_row (esm); - cursor_col = e_selection_model_cursor_col (esm); - - view_row = model_to_view_row (item, cursor_row); - view_col = model_to_view_col (item, cursor_col); - - if (view_row == -1) - view_row = 0; - if (view_col == -1) - view_col = 0; - - old_cell = (AtkObject *)g_object_get_data (G_OBJECT (a11y), "gail-focus-object"); - if (old_cell && GAL_A11Y_IS_E_CELL (old_cell)) - gal_a11y_e_cell_remove_state (GAL_A11Y_E_CELL (old_cell), ATK_STATE_FOCUSED, FALSE); - if (old_cell) - g_object_unref (old_cell); - - cell = eti_ref_at (ATK_TABLE (a11y), view_row, view_col); - - if (cell != NULL) { - g_object_set_data (G_OBJECT (a11y), "gail-focus-object", cell); - gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (cell), ATK_STATE_FOCUSED, FALSE); - } else - g_object_set_data (G_OBJECT (a11y), "gail-focus-object", NULL); - - if (notify && cell) - atk_focus_tracker_notify (cell); -} - -static void -eti_dispose (GObject *object) -{ - GalA11yETableItem *a11y = GAL_A11Y_E_TABLE_ITEM (object); - GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y); - - if (priv->columns) { - g_free(priv->columns); - priv->columns = NULL; - } - - if (parent_class->dispose) - parent_class->dispose (object); -} - -/* Static functions */ -static gint -eti_get_n_children (AtkObject *accessible) -{ - g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (accessible), 0); - if (!eti_a11y_get_gobject (accessible)) - return 0; - - return atk_table_get_n_columns (ATK_TABLE (accessible)) * - (atk_table_get_n_rows (ATK_TABLE (accessible)) + 1); -} - -static AtkObject* -eti_ref_child (AtkObject *accessible, gint index) -{ - ETableItem *item; - gint col, row; - - g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (accessible), NULL); - item = E_TABLE_ITEM (eti_a11y_get_gobject (accessible)); - if (!item) - return NULL; - - if (index < item->cols) { - ETableCol *ecol; - AtkObject *child; - - ecol = e_table_header_get_column (item->header, index); - child = gal_a11y_e_table_column_header_new (ecol, item); - return child; - } - index -= item->cols; - - col = index % item->cols; - row = index / item->cols; - - return eti_ref_at (ATK_TABLE (accessible), row, col); -} - -static void -eti_get_extents (AtkComponent *component, - gint *x, - gint *y, - gint *width, - gint *height, - AtkCoordType coord_type) -{ - ETableItem *item; - AtkObject *parent; - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (component))); - if (!item) - return; - - parent = ATK_OBJECT (component)->accessible_parent; - if (parent && ATK_IS_COMPONENT (parent)) - atk_component_get_extents (ATK_COMPONENT (parent), x, y, - width, height, - coord_type); - - if (parent && GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD (parent)) { - ETableClickToAdd *etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (parent))); - if (etcta) { - *width = etcta->width; - *height = etcta->height; - } - } -} - -static AtkObject* -eti_ref_accessible_at_point (AtkComponent *component, - gint x, - gint y, - AtkCoordType coord_type) -{ - gint row = -1; - gint col = -1; - gint x_origin, y_origin; - ETableItem *item; - GtkWidget *tableOrTree; - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (component))); - if (!item) - return NULL; - - atk_component_get_position (component, - &x_origin, - &y_origin, - coord_type); - x -= x_origin; - y -= y_origin; - - tableOrTree = gtk_widget_get_parent (GTK_WIDGET (item->parent.canvas)); - - if (E_IS_TREE(tableOrTree)) - e_tree_get_cell_at (E_TREE (tableOrTree), x, y, &row, &col); - else - e_table_get_cell_at (E_TABLE (tableOrTree), x, y, &row, &col); - - if (row != -1 && col != -1) { - return eti_ref_at (ATK_TABLE (component), row, col); - } else { - return NULL; - } -} - - -static void -cell_destroyed (gpointer data) -{ - GalA11yECell * cell; - - g_return_if_fail (GAL_A11Y_IS_E_CELL (data)); - cell = GAL_A11Y_E_CELL (data); - - g_return_if_fail (cell->item && G_IS_OBJECT (cell->item)); - - if (cell->item) { - g_object_unref (cell->item); - cell->item = NULL; - } - -} - -/* atk table */ -static AtkObject* -eti_ref_at (AtkTable *table, gint row, gint column) -{ - ETableItem *item; - AtkObject* ret; - GalA11yETableItemPrivate *priv = GET_PRIVATE (table); - - if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) - return NULL; - - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); - if (!item) - return NULL; - - if (column >= 0 && - column < item->cols && - row >= 0 && - row < item->rows && - item->cell_views_realized) { - ECellView *cell_view = item->cell_views[column]; - ETableCol *ecol = e_table_header_get_column (item->header, column); - ret = gal_a11y_e_cell_registry_get_object (NULL, - item, - cell_view, - ATK_OBJECT (table), - ecol->col_idx, - column, - row); - if (ATK_IS_OBJECT (ret)) { - g_object_weak_ref (G_OBJECT (ret), - (GWeakNotify) cell_destroyed, - ret); - /* if current cell is focused, add FOCUSED state */ - if (e_selection_model_cursor_row (item->selection) == GAL_A11Y_E_CELL (ret)->row && - e_selection_model_cursor_col (item->selection) == GAL_A11Y_E_CELL (ret)->model_col) - gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (ret), ATK_STATE_FOCUSED, FALSE); - } else - ret = NULL; - - return ret; - } - - return NULL; -} - -static gint -eti_get_index_at (AtkTable *table, gint row, gint column) -{ - ETableItem *item; - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); - if (!item) - return -1; - - return column + (row + 1) * item->cols; -} - -static gint -eti_get_column_at_index (AtkTable *table, gint index) -{ - ETableItem *item; - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); - if (!item) - return -1; - - return index % item->cols; -} - -static gint -eti_get_row_at_index (AtkTable *table, gint index) -{ - ETableItem *item; - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); - if (!item) - return -1; - - return index / item->cols - 1; -} - -static gint -eti_get_n_columns (AtkTable *table) -{ - ETableItem *item; - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); - if (!item) - return -1; - - return item->cols; -} - -static gint -eti_get_n_rows (AtkTable *table) -{ - ETableItem *item; - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); - if (!item) - return -1; - - return item->rows; -} - -static gint -eti_get_column_extent_at (AtkTable *table, - gint row, - gint column) -{ - ETableItem *item; - gint width; - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); - if (!item) - return -1; - - e_table_item_get_cell_geometry (item, - &row, - &column, - NULL, - NULL, - &width, - NULL); - - return width; -} - -static gint -eti_get_row_extent_at (AtkTable *table, - gint row, - gint column) -{ - ETableItem *item; - gint height; - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); - if (!item) - return -1; - - e_table_item_get_cell_geometry (item, - &row, - &column, - NULL, - NULL, - NULL, - &height); - - return height; -} - -static AtkObject * -eti_get_caption (AtkTable *table) -{ - /* Unimplemented */ - return NULL; -} - -static G_CONST_RETURN gchar * -eti_get_column_description (AtkTable *table, - gint column) -{ - ETableItem *item; - ETableCol *ecol; - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); - if (!item) - return NULL; - - ecol = e_table_header_get_column (item->header, column); - - return ecol->text; -} - -static AtkObject * -eti_get_column_header (AtkTable *table, gint column) -{ - ETableItem *item; - ETableCol *ecol; - AtkObject *atk_obj = NULL; - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); - if (!item) - return NULL; - - ecol = e_table_header_get_column (item->header, column); - if (ecol) { - atk_obj = gal_a11y_e_table_column_header_new (ecol, item); - } - - return atk_obj; -} - -static G_CONST_RETURN gchar * -eti_get_row_description (AtkTable *table, - gint row) -{ - /* Unimplemented */ - return NULL; -} - -static AtkObject * -eti_get_row_header (AtkTable *table, - gint row) -{ - /* Unimplemented */ - return NULL; -} - -static AtkObject * -eti_get_summary (AtkTable *table) -{ - /* Unimplemented */ - return NULL; -} - -static gboolean -table_is_row_selected (AtkTable *table, gint row) -{ - ETableItem *item; - GalA11yETableItemPrivate *priv = GET_PRIVATE (table); - - if (row < 0) - return FALSE; - - if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) - return FALSE; - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); - if (!item) - return FALSE; - - return e_selection_model_is_row_selected(item->selection, view_to_model_row (item, row)); -} - -static gboolean -table_is_selected (AtkTable *table, gint row, gint column) -{ - return table_is_row_selected (table, row); -} - -static gint -table_get_selected_rows (AtkTable *table, gint **rows_selected) -{ - ETableItem *item; - gint n_selected, row, index_selected; - GalA11yETableItemPrivate *priv = GET_PRIVATE (table); - - if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) - return 0; - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); - if (!item) - return 0; - - n_selected = e_selection_model_selected_count (item->selection); - if (rows_selected) { - *rows_selected = (gint *) g_malloc (n_selected * sizeof (gint)); - - index_selected = 0; - for (row = 0; row < item->rows && index_selected < n_selected; ++row) { - if (atk_table_is_row_selected (table, row)) { - (*rows_selected)[index_selected] = row; - ++index_selected; - } - } - } - return n_selected; -} - -static gboolean -table_add_row_selection (AtkTable *table, gint row) -{ - ETableItem *item; - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); - if (!item) - return FALSE; - - if (table_is_row_selected (table, row)) - return TRUE; - e_selection_model_toggle_single_row (item->selection, - view_to_model_row (item, row)); - - return TRUE; -} - -static gboolean -table_remove_row_selection (AtkTable *table, gint row) -{ - ETableItem *item; - GalA11yETableItemPrivate *priv = GET_PRIVATE (table); - - if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) - return FALSE; - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); - if (!item) - return FALSE; - - if (!atk_table_is_row_selected (table, row)) - return TRUE; - e_selection_model_toggle_single_row (item->selection, view_to_model_row (item, row)); - return TRUE; -} - -static void -eti_atk_table_iface_init (AtkTableIface *iface) -{ - iface->ref_at = eti_ref_at; - iface->get_index_at = eti_get_index_at; - iface->get_column_at_index = eti_get_column_at_index; - iface->get_row_at_index = eti_get_row_at_index; - iface->get_n_columns = eti_get_n_columns; - iface->get_n_rows = eti_get_n_rows; - iface->get_column_extent_at = eti_get_column_extent_at; - iface->get_row_extent_at = eti_get_row_extent_at; - iface->get_caption = eti_get_caption; - iface->get_column_description = eti_get_column_description; - iface->get_column_header = eti_get_column_header; - iface->get_row_description = eti_get_row_description; - iface->get_row_header = eti_get_row_header; - iface->get_summary = eti_get_summary; - - iface->is_row_selected = table_is_row_selected; - iface->is_selected = table_is_selected; - iface->get_selected_rows = table_get_selected_rows; - iface->add_row_selection = table_add_row_selection; - iface->remove_row_selection = table_remove_row_selection; -} - -static void -eti_atk_component_iface_init (AtkComponentIface *iface) -{ - component_parent_iface = g_type_interface_peek_parent (iface); - - iface->ref_accessible_at_point = eti_ref_accessible_at_point; - iface->get_extents = eti_get_extents; -} - -static void -eti_rows_inserted (ETableModel * model, gint row, gint count, - AtkObject * table_item) -{ - gint n_cols,n_rows,i,j; - GalA11yETableItem * item_a11y; - gint old_nrows; - - g_return_if_fail (table_item); - item_a11y = GAL_A11Y_E_TABLE_ITEM (table_item); - - n_cols = atk_table_get_n_columns (ATK_TABLE(table_item)); - n_rows = atk_table_get_n_rows (ATK_TABLE(table_item)); - - old_nrows = GET_PRIVATE(item_a11y)->rows; - - g_return_if_fail (n_cols > 0 && n_rows > 0); - g_return_if_fail (old_nrows == n_rows - count); - - GET_PRIVATE(table_item)->rows = n_rows; - - g_signal_emit_by_name (table_item, "row-inserted", row, - count, NULL); - - for (i = row; i < (row + count); i ++) { - for (j = 0; j < n_cols; j ++) { - g_signal_emit_by_name (table_item, - "children_changed::add", - ( ((i + 1)*n_cols) + j), NULL, NULL); - } - } - - g_signal_emit_by_name (table_item, "visible-data-changed"); -} - -static void -eti_rows_deleted (ETableModel * model, gint row, gint count, - AtkObject * table_item) -{ - gint i,j, n_rows, n_cols, old_nrows; - ETableItem *item = E_TABLE_ITEM (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (table_item))); - - n_rows = atk_table_get_n_rows (ATK_TABLE(table_item)); - n_cols = atk_table_get_n_columns (ATK_TABLE(table_item)); - - old_nrows = GET_PRIVATE(table_item)->rows; - - g_return_if_fail ( row+count <= old_nrows); - g_return_if_fail (old_nrows == n_rows + count); - GET_PRIVATE(table_item)->rows = n_rows; - - g_signal_emit_by_name (table_item, "row-deleted", row, - count, NULL); - - for (i = row; i < (row + count); i ++) { - for (j = 0; j < n_cols; j ++) { - g_signal_emit_by_name (table_item, - "children_changed::remove", - ( ((i + 1)*n_cols) + j), NULL, NULL); - } - } - g_signal_emit_by_name (table_item, "visible-data-changed"); - eti_a11y_reset_focus_object ((GalA11yETableItem *)table_item, item, TRUE); -} - -static void -eti_tree_model_node_changed_cb (ETreeModel *model, ETreePath node, ETableItem *eti) -{ - AtkObject *atk_obj; - GalA11yETableItem *a11y; - - g_return_if_fail (E_IS_TABLE_ITEM (eti)); - - atk_obj = atk_gobject_accessible_for_object (G_OBJECT (eti)); - a11y = GAL_A11Y_E_TABLE_ITEM (atk_obj); - - /* we can't figure out which rows are changed, so just send out a signal ... */ - if (GET_PRIVATE (a11y)->rows > 0) - g_signal_emit_by_name (a11y, "visible-data-changed"); -} - -enum { - ETI_HEADER_UNCHANGED = 0, - ETI_HEADER_REORDERED, - ETI_HEADER_NEW_ADDED, - ETI_HEADER_REMOVED -}; - -/* - * 1. Check what actually happened: column reorder, remove or add - * 2. Update cache - * 3. Emit signals - */ -static void -eti_header_structure_changed (ETableHeader *eth, AtkObject *a11y) -{ - - gboolean reorder_found=FALSE, added_found=FALSE, removed_found=FALSE; - GalA11yETableItem * a11y_item; - ETableCol ** cols, **prev_cols; - GalA11yETableItemPrivate *priv; - gint *state = NULL, *prev_state = NULL, *reorder = NULL; - gint i,j,n_rows,n_cols, prev_n_cols; - - a11y_item = GAL_A11Y_E_TABLE_ITEM (a11y); - priv = GET_PRIVATE (a11y_item); - - /* Assume rows do not changed. */ - n_rows = priv->rows; - - prev_n_cols = priv->cols; - prev_cols = priv->columns; - - cols = e_table_header_get_columns (eth); - n_cols = eth->col_count; - - g_return_if_fail (cols && prev_cols && n_cols > 0); - - /* Init to ETI_HEADER_UNCHANGED. */ - state = g_malloc0 (sizeof (gint) * n_cols); - prev_state = g_malloc0 (sizeof (gint) * prev_n_cols); - reorder = g_malloc0 (sizeof (gint) * n_cols); - - /* Compare with previously saved column headers. */ - for ( i = 0; i < n_cols && cols[i]; i ++ ) { - for ( j = 0; j < prev_n_cols && prev_cols[j]; j ++ ) { - if ( prev_cols [j] == cols[i] && i != j ) { - - reorder_found = TRUE; - state [i] = ETI_HEADER_REORDERED; - reorder [i] = j; - - break; - } else if (prev_cols[j] == cols[i]) { - /* OK, this column is not changed. */ - break; - } - } - - /* cols[i] is new added column. */ - if ( j == prev_n_cols ) { - added_found = TRUE; - state[i] = ETI_HEADER_NEW_ADDED; - } - } - - /* Now try to find if there are removed columns. */ - for (i = 0; i < prev_n_cols && prev_cols[i]; i ++) { - for (j = 0; j < n_cols && cols[j]; j ++) - if ( prev_cols [j] == cols[i] ) - break; - - /* Removed columns found. */ - if ( j == n_cols ) { - removed_found = TRUE; - prev_state[j] = ETI_HEADER_REMOVED; - } - } - - /* If nothing interesting just return. */ - if (!reorder_found && !added_found && !removed_found) - return; - - /* Emit signals */ - if (reorder_found) - g_signal_emit_by_name (G_OBJECT(a11y_item), "column_reordered"); - - - if (removed_found) { - for (i = 0; i < prev_n_cols; i ++ ) { - if (prev_state[i] == ETI_HEADER_REMOVED) { - g_signal_emit_by_name (G_OBJECT(a11y_item), "column-deleted", i, 1); - for (j = 0; j < n_rows; j ++) - g_signal_emit_by_name (G_OBJECT(a11y_item), "children_changed::remove", ((j+1)*prev_n_cols+i), NULL, NULL); - } - } - } - - if (added_found) { - for ( i = 0; i < n_cols; i ++ ) { - if (state[i] == ETI_HEADER_NEW_ADDED) { - g_signal_emit_by_name (G_OBJECT(a11y_item), "column-inserted", i, 1); - for (j = 0; j < n_rows; j ++) - g_signal_emit_by_name (G_OBJECT(a11y_item), "children_changed::add", ((j+1)*n_cols+i), NULL, NULL); - } - } - } - - priv->cols = n_cols; - - g_free (state); - g_free (reorder); - g_free (prev_state); - - g_free (priv->columns); - priv->columns = cols; -} - - -static void -eti_real_initialize (AtkObject *obj, - gpointer data) -{ - ETableItem * eti; - ETableModel * model; - - ATK_OBJECT_CLASS (parent_class)->initialize (obj, data); - eti = E_TABLE_ITEM (data); - - model = eti->table_model; - - g_signal_connect (model, "model-rows-inserted", - G_CALLBACK (eti_rows_inserted), - obj); - g_signal_connect (model, "model-rows-deleted", - G_CALLBACK (eti_rows_deleted), - obj); - g_signal_connect (G_OBJECT (eti->header), "structure_change", - G_CALLBACK (eti_header_structure_changed), obj); - -} - -static void -eti_class_init (GalA11yETableItemClass *klass) -{ - AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - quark_accessible_object = g_quark_from_static_string ("gtk-accessible-object"); - - parent_class = g_type_class_ref (PARENT_TYPE); - - object_class->dispose = eti_dispose; - - atk_object_class->get_n_children = eti_get_n_children; - atk_object_class->ref_child = eti_ref_child; - atk_object_class->initialize = eti_real_initialize; - atk_object_class->ref_state_set = eti_ref_state_set; -} - -static void -eti_init (GalA11yETableItem *a11y) -{ - GalA11yETableItemPrivate *priv; - - priv = GET_PRIVATE (a11y); - - priv->selection_change_id = 0; - priv->cursor_change_id = 0; - priv->selection = NULL; -} - -/* atk selection */ - -static void atk_selection_interface_init (AtkSelectionIface *iface); -static gboolean selection_add_selection (AtkSelection *selection, - gint i); -static gboolean selection_clear_selection (AtkSelection *selection); -static AtkObject* selection_ref_selection (AtkSelection *selection, - gint i); -static gint selection_get_selection_count (AtkSelection *selection); -static gboolean selection_is_child_selected (AtkSelection *selection, - gint i); - -/* callbacks */ -static void eti_a11y_selection_model_removed_cb (ETableItem *eti, - ESelectionModel *selection, - gpointer data); -static void eti_a11y_selection_model_added_cb (ETableItem *eti, - ESelectionModel *selection, - gpointer data); -static void eti_a11y_selection_changed_cb (ESelectionModel *selection, - GalA11yETableItem *a11y); -static void eti_a11y_cursor_changed_cb (ESelectionModel *selection, - gint row, gint col, - GalA11yETableItem *a11y); - -/** - * gal_a11y_e_table_item_get_type: - * @void: - * - * Registers the &GalA11yETableItem class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &GalA11yETableItem class. - **/ -GType -gal_a11y_e_table_item_get_type (void) -{ - static GType type = 0; - - if (!type) { - AtkObjectFactory *factory; - - GTypeInfo info = { - sizeof (GalA11yETableItemClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) eti_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (GalA11yETableItem), - 0, - (GInstanceInitFunc) eti_init, - NULL /* value_table_item */ - }; - - static const GInterfaceInfo atk_component_info = { - (GInterfaceInitFunc) eti_atk_component_iface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - static const GInterfaceInfo atk_table_info = { - (GInterfaceInitFunc) eti_atk_table_iface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - static const GInterfaceInfo atk_selection_info = { - (GInterfaceInitFunc) atk_selection_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - - factory = atk_registry_get_factory (atk_get_default_registry (), GNOME_TYPE_CANVAS_ITEM); - parent_type = atk_object_factory_get_accessible_type (factory); - - type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yETableItem", &info, 0, - sizeof (GalA11yETableItemPrivate), &priv_offset); - - g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); - g_type_add_interface_static (type, ATK_TYPE_TABLE, &atk_table_info); - g_type_add_interface_static (type, ATK_TYPE_SELECTION, &atk_selection_info); - } - - return type; -} - -AtkObject * -gal_a11y_e_table_item_new (ETableItem *item) -{ - GalA11yETableItem *a11y; - AtkObject *accessible; - ESelectionModel * esm; - AtkObject *parent; - const gchar *name; - - g_return_val_if_fail (item && item->cols >= 0 && item->rows >= 0, NULL); - a11y = g_object_new (gal_a11y_e_table_item_get_type (), NULL); - - atk_object_initialize (ATK_OBJECT (a11y), item); - - GET_PRIVATE (a11y)->state_set = atk_state_set_new (); - - atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_TRANSIENT); - atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_ENABLED); - atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_SENSITIVE); - atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_SHOWING); - atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_VISIBLE); - - - accessible = ATK_OBJECT(a11y); - - /* Initialize cell data. */ - GET_PRIVATE (a11y)->cols = item->cols; - GET_PRIVATE (a11y)->rows = item->rows; - - GET_PRIVATE (a11y)->columns = e_table_header_get_columns (item->header); - if ( GET_PRIVATE (a11y)->columns == NULL) - return NULL; - - if (item) { - g_signal_connect (G_OBJECT(item), "selection_model_removed", - G_CALLBACK (eti_a11y_selection_model_removed_cb), NULL); - g_signal_connect (G_OBJECT(item), "selection_model_added", - G_CALLBACK (eti_a11y_selection_model_added_cb), NULL); - if (item->selection) - gal_a11y_e_table_item_ref_selection (a11y, - item->selection); - - /* find the TableItem's parent: table or tree */ - GET_PRIVATE (a11y)->widget = gtk_widget_get_parent (GTK_WIDGET (item->parent.canvas)); - parent = gtk_widget_get_accessible (GET_PRIVATE (a11y)->widget); - name = atk_object_get_name (parent); - if (name) - atk_object_set_name (accessible, name); - atk_object_set_parent (accessible, parent); - - if (E_IS_TREE (GET_PRIVATE (a11y)->widget)) { - ETreeModel *model; - model = e_tree_get_model (E_TREE (GET_PRIVATE (a11y)->widget)); - g_signal_connect (G_OBJECT(model), "node_changed", - G_CALLBACK (eti_tree_model_node_changed_cb), item); - accessible->role = ATK_ROLE_TREE_TABLE; - } else if (E_IS_TABLE (GET_PRIVATE (a11y)->widget)) { - accessible->role = ATK_ROLE_TABLE; - } - } - - if (item) - g_signal_connect (G_OBJECT (item), "destroy", - G_CALLBACK (item_destroyed), - a11y); - esm = item->selection; - - if (esm != NULL) { - eti_a11y_reset_focus_object (a11y, item, FALSE); - } - - return ATK_OBJECT (a11y); -} - -static gboolean -gal_a11y_e_table_item_ref_selection (GalA11yETableItem *a11y, - ESelectionModel *selection) -{ - GalA11yETableItemPrivate *priv; - - g_return_val_if_fail (a11y && selection, FALSE); - - priv = GET_PRIVATE (a11y); - priv->selection_change_id = g_signal_connect ( - G_OBJECT(selection), "selection_changed", - G_CALLBACK (eti_a11y_selection_changed_cb), a11y); - priv->cursor_change_id = g_signal_connect ( - G_OBJECT(selection), "cursor_changed", - G_CALLBACK (eti_a11y_cursor_changed_cb), a11y); - - priv->selection = selection; - g_object_ref (selection); - - return TRUE; -} - -static gboolean -gal_a11y_e_table_item_unref_selection (GalA11yETableItem *a11y) -{ - GalA11yETableItemPrivate *priv; - - g_return_val_if_fail (a11y, FALSE); - - priv = GET_PRIVATE (a11y); - - g_return_val_if_fail (priv->selection_change_id != 0, FALSE); - g_return_val_if_fail (priv->cursor_change_id != 0, FALSE); - - - g_signal_handler_disconnect (priv->selection, - priv->selection_change_id); - g_signal_handler_disconnect (priv->selection, - priv->cursor_change_id); - priv->cursor_change_id = 0; - priv->selection_change_id = 0; - - g_object_unref (priv->selection); - priv->selection = NULL; - - return TRUE; -} - -/* callbacks */ - -static void -eti_a11y_selection_model_removed_cb (ETableItem *eti, ESelectionModel *selection, - gpointer data) -{ - AtkObject *atk_obj; - GalA11yETableItem *a11y; - - g_return_if_fail (E_IS_TABLE_ITEM (eti)); - g_return_if_fail (E_IS_SELECTION_MODEL (selection)); - - atk_obj = atk_gobject_accessible_for_object (G_OBJECT (eti)); - a11y = GAL_A11Y_E_TABLE_ITEM (atk_obj); - - if (selection == GET_PRIVATE (a11y)->selection) - gal_a11y_e_table_item_unref_selection (a11y); -} - -static void -eti_a11y_selection_model_added_cb (ETableItem *eti, ESelectionModel *selection, - gpointer data) -{ - AtkObject *atk_obj; - GalA11yETableItem *a11y; - - g_return_if_fail (E_IS_TABLE_ITEM (eti)); - g_return_if_fail (E_IS_SELECTION_MODEL (selection)); - - atk_obj = atk_gobject_accessible_for_object (G_OBJECT (eti)); - a11y = GAL_A11Y_E_TABLE_ITEM (atk_obj); - - if (GET_PRIVATE (a11y)->selection) - gal_a11y_e_table_item_unref_selection (a11y); - gal_a11y_e_table_item_ref_selection (a11y, selection); -} - -static void -eti_a11y_selection_changed_cb (ESelectionModel *selection, GalA11yETableItem *a11y) -{ - GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y); - - if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) - return; - - g_return_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (a11y)); - - g_signal_emit_by_name (a11y, "selection_changed"); -} - -static void -eti_a11y_cursor_changed_cb (ESelectionModel *selection, - gint row, gint col, GalA11yETableItem *a11y) -{ - ETableItem *item; - GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y); - - g_return_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (a11y)); - - if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) - return; - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (a11y))); - - g_return_if_fail (item); - - if (row == -1 && col == -1) - return; - eti_a11y_reset_focus_object (a11y, item, TRUE); -} - -/* atk selection */ - -static void atk_selection_interface_init (AtkSelectionIface *iface) -{ - g_return_if_fail (iface != NULL); - iface->add_selection = selection_add_selection; - iface->clear_selection = selection_clear_selection; - iface->ref_selection = selection_ref_selection; - iface->get_selection_count = selection_get_selection_count; - iface->is_child_selected = selection_is_child_selected; -} - -static gboolean -selection_add_selection (AtkSelection *selection, gint index) -{ - AtkTable *table; - gint row, col, cursor_row, cursor_col, model_row, model_col; - ETableItem *item; - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (selection))); - if (!item) - return FALSE; - - table = ATK_TABLE (selection); - - row = atk_table_get_row_at_index (table, index); - col = atk_table_get_column_at_index (table, index); - - model_row = view_to_model_row (item, row); - model_col = view_to_model_col (item, col); - - cursor_row = e_selection_model_cursor_row (item->selection); - cursor_col = e_selection_model_cursor_col (item->selection); - - /* check whether is selected already */ - if (model_row == cursor_row && model_col == cursor_col) - return TRUE; - - if (model_row != cursor_row) { - /* we need to make the item get focus */ - e_canvas_item_grab_focus (GNOME_CANVAS_ITEM (item), TRUE); - - /* FIXME, currently we only support single row selection */ - atk_selection_clear_selection (selection); - atk_table_add_row_selection (table, row); - } - - e_selection_model_change_cursor (item->selection, - model_row, - model_col); - e_selection_model_cursor_changed (item->selection, - model_row, - model_col); - e_selection_model_cursor_activated (item->selection, - model_row, - model_col); - return TRUE; -} - -static gboolean -selection_clear_selection (AtkSelection *selection) -{ - ETableItem *item; - - item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (selection))); - if (!item) - return FALSE; - - e_selection_model_clear (item->selection); - return TRUE; -} - -static AtkObject * -selection_ref_selection (AtkSelection *selection, gint index) -{ - AtkTable *table; - gint row, col; - - table = ATK_TABLE (selection); - row = atk_table_get_row_at_index (table, index); - col = atk_table_get_column_at_index (table, index); - if (!atk_table_is_row_selected (table, row)) - return NULL; - - return eti_ref_at (table, row, col); -} - -static gint -selection_get_selection_count (AtkSelection *selection) -{ - AtkTable *table; - gint n_selected; - - table = ATK_TABLE (selection); - n_selected = atk_table_get_selected_rows (table, NULL); - if (n_selected > 0) - n_selected *= atk_table_get_n_columns (table); - return n_selected; -} - -static gboolean -selection_is_child_selected (AtkSelection *selection, gint i) -{ - gint row; - - row = atk_table_get_row_at_index (ATK_TABLE (selection), i); - return atk_table_is_row_selected (ATK_TABLE (selection), row); -} - -void -gal_a11y_e_table_item_init (void) -{ - if (atk_get_root ()) - atk_registry_set_factory_type (atk_get_default_registry (), - E_TABLE_ITEM_TYPE, - gal_a11y_e_table_item_factory_get_type ()); -} - diff --git a/widgets/table/a11y/gal-a11y-e-table-item.h b/widgets/table/a11y/gal-a11y-e-table-item.h deleted file mode 100644 index 27d6a8244b..0000000000 --- a/widgets/table/a11y/gal-a11y-e-table-item.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Christopher James Lahey - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __GAL_A11Y_E_TABLE_ITEM_H__ -#define __GAL_A11Y_E_TABLE_ITEM_H__ - -#include -#include
-#include - -#define GAL_A11Y_TYPE_E_TABLE_ITEM (gal_a11y_e_table_item_get_type ()) -#define GAL_A11Y_E_TABLE_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_ITEM, GalA11yETableItem)) -#define GAL_A11Y_E_TABLE_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_ITEM, GalA11yETableItemClass)) -#define GAL_A11Y_IS_E_TABLE_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_ITEM)) -#define GAL_A11Y_IS_E_TABLE_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_ITEM)) - -typedef struct _GalA11yETableItem GalA11yETableItem; -typedef struct _GalA11yETableItemClass GalA11yETableItemClass; -typedef struct _GalA11yETableItemPrivate GalA11yETableItemPrivate; - -/* This struct should actually be larger as this isn't what we derive from. - * The GalA11yETableItemPrivate comes right after the parent class structure. - **/ -struct _GalA11yETableItem { - AtkGObjectAccessible parent; -}; - -struct _GalA11yETableItemClass { - AtkGObjectAccessibleClass parent_class; -}; - - -/* Standard Glib function */ -GType gal_a11y_e_table_item_get_type (void); -AtkObject *gal_a11y_e_table_item_new (ETableItem *item); - -void gal_a11y_e_table_item_init (void); - -#endif /* ! __GAL_A11Y_E_TABLE_ITEM_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-table.c b/widgets/table/a11y/gal-a11y-e-table.c deleted file mode 100644 index bf75227af4..0000000000 --- a/widgets/table/a11y/gal-a11y-e-table.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Christopher James Lahey - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include - -#include "a11y/gal-a11y-util.h" -#include "table/e-table.h" -#include "table/e-table-click-to-add.h" -#include "table/e-table-group.h" -#include "table/e-table-group-container.h" -#include "table/e-table-group-leaf.h" - -#include "gal-a11y-e-table.h" -#include "gal-a11y-e-table-factory.h" -#include "gal-a11y-e-table-item.h" - -#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yETableClass)) -static AtkObjectClass *parent_class; -static GType parent_type; -static gint priv_offset; -#define GET_PRIVATE(object) ((GalA11yETablePrivate *) (((gchar *) object) + priv_offset)) -#define PARENT_TYPE (parent_type) - -struct _GalA11yETablePrivate { - AtkObject *child_item; -}; - -/* Static functions */ -static ETableItem * -find_first_table_item (ETableGroup *group) -{ - GnomeCanvasGroup *cgroup; - GList *l; - - cgroup = GNOME_CANVAS_GROUP (group); - - for (l = cgroup->item_list; l; l = l->next) { - GnomeCanvasItem *i; - - i = GNOME_CANVAS_ITEM (l->data); - - if (E_IS_TABLE_GROUP (i)) - return find_first_table_item (E_TABLE_GROUP (i)); - else if (E_IS_TABLE_ITEM (i)) { - return E_TABLE_ITEM (i); - } - } - - return NULL; -} - -static AtkObject* -eti_get_accessible (ETableItem *eti, AtkObject *parent) -{ - AtkObject *a11y = NULL; - - g_return_val_if_fail (eti, NULL); - - a11y = atk_gobject_accessible_for_object (G_OBJECT (eti)); - g_return_val_if_fail (a11y, NULL); - - return a11y; -} - -static gboolean -init_child_item (GalA11yETable *a11y) -{ - ETable *table; - - if (!a11y || !GTK_IS_ACCESSIBLE (a11y)) - return FALSE; - - table = E_TABLE (GTK_ACCESSIBLE (a11y)->widget); - if (table && GTK_WIDGET_MAPPED (GTK_WIDGET (table)) && table->group && E_IS_TABLE_GROUP_CONTAINER(table->group)) { - ETableGroupContainer *etgc = (ETableGroupContainer *)table->group; - GList *list; - - for (list = etgc->children; list; list = g_list_next (list)) { - ETableGroupContainerChildNode *child_node = list->data; - ETableGroup *child = child_node->child; - ETableItem *eti = find_first_table_item (child); - - eti_get_accessible (eti, ATK_OBJECT (a11y)); - } - } - g_object_unref (a11y); - g_object_unref (table); - - return FALSE; -} - -static AtkObject* -et_ref_accessible_at_point (AtkComponent *component, - gint x, - gint y, - AtkCoordType coord_type) -{ - GalA11yETable *a11y = GAL_A11Y_E_TABLE (component); - if (GET_PRIVATE (a11y)->child_item) - g_object_ref (GET_PRIVATE (a11y)->child_item); - return GET_PRIVATE (a11y)->child_item; -} - -static gint -et_get_n_children (AtkObject *accessible) -{ - GalA11yETable *a11y = GAL_A11Y_E_TABLE (accessible); - ETable * et; - gint n = 0; - - et = E_TABLE(GTK_ACCESSIBLE (a11y)->widget); - - if (et->group) { - if (E_IS_TABLE_GROUP_LEAF (et->group)) - n = 1; - else if (E_IS_TABLE_GROUP_CONTAINER (et->group)) { - ETableGroupContainer *etgc = (ETableGroupContainer *)et->group; - n = g_list_length (etgc->children); - } - } - - if (et && et->use_click_to_add && et->click_to_add) { - n++; - } - return n; -} - -static AtkObject* -et_ref_child (AtkObject *accessible, - gint i) -{ - GalA11yETable *a11y = GAL_A11Y_E_TABLE (accessible); - ETable * et; - gint child_no; - - et = E_TABLE(GTK_ACCESSIBLE (a11y)->widget); - - child_no = et_get_n_children (accessible); - if (i == 0 || i < child_no - 1) { - if (E_IS_TABLE_GROUP_LEAF (et->group)) { - ETableItem *eti = find_first_table_item (et->group); - AtkObject *aeti = eti_get_accessible (eti, accessible); - if (aeti) - g_object_ref (aeti); - return aeti; - - } else if (E_IS_TABLE_GROUP_CONTAINER (et->group)) { - ETableGroupContainer *etgc = (ETableGroupContainer *) et->group; - ETableGroupContainerChildNode *child_node = g_list_nth_data (etgc->children, i); - if (child_node) { - ETableGroup *child = child_node->child; - ETableItem * eti = find_first_table_item (child); - AtkObject *aeti = eti_get_accessible (eti, accessible); - if (aeti) - g_object_ref (aeti); - return aeti; - } - } - } else if (i == child_no -1) { - ETableClickToAdd * etcta; - - if (et && et->use_click_to_add && et->click_to_add) { - etcta = E_TABLE_CLICK_TO_ADD(et->click_to_add); - accessible = atk_gobject_accessible_for_object (G_OBJECT(etcta)); - if (accessible) - g_object_ref (accessible); - return accessible; - } - } - - return NULL; -} - -static AtkLayer -et_get_layer (AtkComponent *component) -{ - return ATK_LAYER_WIDGET; -} - -static void -et_class_init (GalA11yETableClass *klass) -{ - AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass); - - parent_class = g_type_class_ref (PARENT_TYPE); - - atk_object_class->get_n_children = et_get_n_children; - atk_object_class->ref_child = et_ref_child; -} - -static void -et_atk_component_iface_init (AtkComponentIface *iface) -{ - iface->ref_accessible_at_point = et_ref_accessible_at_point; - iface->get_layer = et_get_layer; -} - -static void -et_init (GalA11yETable *a11y) -{ - GalA11yETablePrivate *priv; - - priv = GET_PRIVATE (a11y); - - priv->child_item = NULL; -} - -/** - * gal_a11y_e_table_get_type: - * @void: - * - * Registers the &GalA11yETable class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &GalA11yETable class. - **/ -GType -gal_a11y_e_table_get_type (void) -{ - static GType type = 0; - - if (!type) { - AtkObjectFactory *factory; - - GTypeInfo info = { - sizeof (GalA11yETableClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) et_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (GalA11yETable), - 0, - (GInstanceInitFunc) et_init, - NULL /* value_table */ - }; - - static const GInterfaceInfo atk_component_info = { - (GInterfaceInitFunc) et_atk_component_iface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - factory = atk_registry_get_factory (atk_get_default_registry (), GTK_TYPE_WIDGET); - parent_type = atk_object_factory_get_accessible_type (factory); - - type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yETable", &info, 0, - sizeof (GalA11yETablePrivate), &priv_offset); - g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); - } - - return type; -} - -AtkObject * -gal_a11y_e_table_new (GObject *widget) -{ - GalA11yETable *a11y; - ETable *table; - - table = E_TABLE (widget); - - a11y = g_object_new (gal_a11y_e_table_get_type (), NULL); - - GTK_ACCESSIBLE (a11y)->widget = GTK_WIDGET (widget); - - /* we need to init all the children for multiple table items */ - if (table && GTK_WIDGET_MAPPED (GTK_WIDGET (table)) && table->group && E_IS_TABLE_GROUP_CONTAINER (table->group)) { - /* Ref it here so that it is still valid in the idle function */ - /* It will be unrefed in the idle function */ - g_object_ref (a11y); - g_object_ref (widget); - - g_idle_add ((GSourceFunc)init_child_item, a11y); - } - - return ATK_OBJECT (a11y); -} - -void -gal_a11y_e_table_init (void) -{ - if (atk_get_root ()) - atk_registry_set_factory_type (atk_get_default_registry (), - E_TABLE_TYPE, - gal_a11y_e_table_factory_get_type ()); - -} - diff --git a/widgets/table/a11y/gal-a11y-e-table.h b/widgets/table/a11y/gal-a11y-e-table.h deleted file mode 100644 index d8f972df81..0000000000 --- a/widgets/table/a11y/gal-a11y-e-table.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Christopher James Lahey - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __GAL_A11Y_E_TABLE_H__ -#define __GAL_A11Y_E_TABLE_H__ - -#include -#include -#include - -#define GAL_A11Y_TYPE_E_TABLE (gal_a11y_e_table_get_type ()) -#define GAL_A11Y_E_TABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE, GalA11yETable)) -#define GAL_A11Y_E_TABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE, GalA11yETableClass)) -#define GAL_A11Y_IS_E_TABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE)) -#define GAL_A11Y_IS_E_TABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE)) - -typedef struct _GalA11yETable GalA11yETable; -typedef struct _GalA11yETableClass GalA11yETableClass; -typedef struct _GalA11yETablePrivate GalA11yETablePrivate; - -/* This struct should actually be larger as this isn't what we derive from. - * The GalA11yETablePrivate comes right after the parent class structure. - **/ -struct _GalA11yETable { - GtkAccessible object; -}; - -struct _GalA11yETableClass { - GtkAccessibleClass parent_class; -}; - - -/* Standard Glib function */ -GType gal_a11y_e_table_get_type (void); -AtkObject *gal_a11y_e_table_new (GObject *table); - -void gal_a11y_e_table_init (void); - -#endif /* ! __GAL_A11Y_E_TABLE_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-tree-factory.c b/widgets/table/a11y/gal-a11y-e-tree-factory.c deleted file mode 100644 index 8dc06e2936..0000000000 --- a/widgets/table/a11y/gal-a11y-e-tree-factory.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Yuedong Du - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include - -#include "gal-a11y-e-tree.h" -#include "gal-a11y-e-tree-factory.h" - -#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETreeFactoryClass)) -static AtkObjectFactoryClass *parent_class; -#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY) - -/* Static functions */ - -static GType -gal_a11y_e_tree_factory_get_accessible_type (void) -{ - return GAL_A11Y_TYPE_E_TREE; -} - -static AtkObject* -gal_a11y_e_tree_factory_create_accessible (GObject *obj) -{ - AtkObject *accessible; - - accessible = gal_a11y_e_tree_new (obj); - - return accessible; -} - -static void -gal_a11y_e_tree_factory_class_init (GalA11yETreeFactoryClass *klass) -{ - AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass); - - parent_class = g_type_class_ref (PARENT_TYPE); - - factory_class->create_accessible = gal_a11y_e_tree_factory_create_accessible; - factory_class->get_accessible_type = gal_a11y_e_tree_factory_get_accessible_type; -} - -static void -gal_a11y_e_tree_factory_init (GalA11yETreeFactory *factory) -{ -} - -/** - * gal_a11y_e_tree_factory_get_type: - * @void: - * - * Registers the &GalA11yETreeFactory class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &GalA11yETreeFactory class. - **/ -GType -gal_a11y_e_tree_factory_get_type (void) -{ - static GType type = 0; - - if (!type) { - GTypeInfo info = { - sizeof (GalA11yETreeFactoryClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gal_a11y_e_tree_factory_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (GalA11yETreeFactory), - 0, - (GInstanceInitFunc) gal_a11y_e_tree_factory_init, - NULL /* value_tree */ - }; - - type = g_type_register_static (PARENT_TYPE, "GalA11yETreeFactory", &info, 0); - } - - return type; -} diff --git a/widgets/table/a11y/gal-a11y-e-tree-factory.h b/widgets/table/a11y/gal-a11y-e-tree-factory.h deleted file mode 100644 index 3d97c7a3b1..0000000000 --- a/widgets/table/a11y/gal-a11y-e-tree-factory.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Yuedong Du - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __GAL_A11Y_E_TREE_FACTORY_H__ -#define __GAL_A11Y_E_TREE_FACTORY_H__ - -#include -#include - -#define GAL_A11Y_TYPE_E_TREE_FACTORY (gal_a11y_e_table_factory_get_type ()) -#define GAL_A11Y_E_TREE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TREE_FACTORY, GalA11yETreeFactory)) -#define GAL_A11Y_E_TREE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TREE_FACTORY, GalA11yETreeFactoryClass)) -#define GAL_A11Y_IS_E_TREE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TREE_FACTORY)) -#define GAL_A11Y_IS_E_TREE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TREE_FACTORY)) - -typedef struct _GalA11yETreeFactory GalA11yETreeFactory; -typedef struct _GalA11yETreeFactoryClass GalA11yETreeFactoryClass; - -struct _GalA11yETreeFactory { - AtkObject object; -}; - -struct _GalA11yETreeFactoryClass { - AtkObjectClass parent_class; -}; - - -/* Standard Glib function */ -GType gal_a11y_e_tree_factory_get_type (void); - -#endif /* ! __GAL_A11Y_E_TREE_FACTORY_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-tree.c b/widgets/table/a11y/gal-a11y-e-tree.c deleted file mode 100644 index 879b517aab..0000000000 --- a/widgets/table/a11y/gal-a11y-e-tree.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Yuedong Du - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include - -#include "a11y/gal-a11y-util.h" -#include "table/e-table-item.h" -#include "table/e-tree.h" - -#include "gal-a11y-e-table-item.h" -#include "gal-a11y-e-tree.h" -#include "gal-a11y-e-tree-factory.h" - -#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yETreeClass)) -static AtkObjectClass *parent_class; -static GType parent_type; -static gint priv_offset; -#define GET_PRIVATE(object) ((GalA11yETreePrivate *) (((gchar *) object) + priv_offset)) -#define PARENT_TYPE (parent_type) - -struct _GalA11yETreePrivate { - AtkObject *child_item; -}; - -/* Static functions */ - -static void -init_child_item (GalA11yETree *a11y) -{ - GalA11yETreePrivate *priv = GET_PRIVATE (a11y); - ETree *tree = E_TREE (GTK_ACCESSIBLE (a11y)->widget); - ETableItem * eti; - - g_return_if_fail (tree); - eti = e_tree_get_item (tree); - if (priv->child_item == NULL) { - priv->child_item = atk_gobject_accessible_for_object (G_OBJECT (eti)); - } -} - -static AtkObject* -et_ref_accessible_at_point (AtkComponent *component, - gint x, - gint y, - AtkCoordType coord_type) -{ - GalA11yETree *a11y = GAL_A11Y_E_TREE (component); - init_child_item (a11y); - return GET_PRIVATE (a11y)->child_item; -} - -static gint -et_get_n_children (AtkObject *accessible) -{ - return 1; -} - -static AtkObject* -et_ref_child (AtkObject *accessible, - gint i) -{ - GalA11yETree *a11y = GAL_A11Y_E_TREE (accessible); - if (i != 0) - return NULL; - init_child_item (a11y); - g_object_ref (GET_PRIVATE (a11y)->child_item); - return GET_PRIVATE (a11y)->child_item; -} - -static AtkLayer -et_get_layer (AtkComponent *component) -{ - return ATK_LAYER_WIDGET; -} - -static void -et_class_init (GalA11yETreeClass *klass) -{ - AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass); - - parent_class = g_type_class_ref (PARENT_TYPE); - - atk_object_class->get_n_children = et_get_n_children; - atk_object_class->ref_child = et_ref_child; -} - -static void -et_atk_component_iface_init (AtkComponentIface *iface) -{ - iface->ref_accessible_at_point = et_ref_accessible_at_point; - iface->get_layer = et_get_layer; -} - -static void -et_init (GalA11yETree *a11y) -{ - GalA11yETreePrivate *priv; - - priv = GET_PRIVATE (a11y); - - priv->child_item = NULL; -} - -/** - * gal_a11y_e_tree_get_type: - * @void: - * - * Registers the &GalA11yETree class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &GalA11yETree class. - **/ -GType -gal_a11y_e_tree_get_type (void) -{ - static GType type = 0; - - if (!type) { - AtkObjectFactory *factory; - - GTypeInfo info = { - sizeof (GalA11yETreeClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) et_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (GalA11yETree), - 0, - (GInstanceInitFunc) et_init, - NULL /* value_tree */ - }; - - static const GInterfaceInfo atk_component_info = { - (GInterfaceInitFunc) et_atk_component_iface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - factory = atk_registry_get_factory (atk_get_default_registry (), GTK_TYPE_WIDGET); - parent_type = atk_object_factory_get_accessible_type (factory); - - type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yETree", &info, 0, - sizeof (GalA11yETreePrivate), &priv_offset); - g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); - } - - return type; -} - -AtkObject * -gal_a11y_e_tree_new (GObject *widget) -{ - GalA11yETree *a11y; - - a11y = g_object_new (gal_a11y_e_tree_get_type (), NULL); - - GTK_ACCESSIBLE (a11y)->widget = GTK_WIDGET (widget); - - return ATK_OBJECT (a11y); -} - -void -gal_a11y_e_tree_init (void) -{ - if (atk_get_root ()) - atk_registry_set_factory_type (atk_get_default_registry (), - E_TREE_TYPE, - gal_a11y_e_tree_factory_get_type ()); - -} - diff --git a/widgets/table/a11y/gal-a11y-e-tree.h b/widgets/table/a11y/gal-a11y-e-tree.h deleted file mode 100644 index d2aa8a0d2a..0000000000 --- a/widgets/table/a11y/gal-a11y-e-tree.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Yuedong Du - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __GAL_A11Y_E_TREE_H__ -#define __GAL_A11Y_E_TREE_H__ - -#include -#include -#include - -#define GAL_A11Y_TYPE_E_TREE (gal_a11y_e_tree_get_type ()) -#define GAL_A11Y_E_TREE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TREE, GalA11yETree)) -#define GAL_A11Y_E_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TREE, GalA11yETreeClass)) -#define GAL_A11Y_IS_E_TREE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TREE)) -#define GAL_A11Y_IS_E_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TREE)) - -typedef struct _GalA11yETree GalA11yETree; -typedef struct _GalA11yETreeClass GalA11yETreeClass; -typedef struct _GalA11yETreePrivate GalA11yETreePrivate; - -/* This struct should actually be larger as this isn't what we derive from. - * The GalA11yETablePrivate comes right after the parent class structure. - **/ -struct _GalA11yETree { - GtkAccessible object; -}; - -struct _GalA11yETreeClass { - GtkAccessibleClass parent_class; -}; - - -/* Standard Glib function */ -GType gal_a11y_e_tree_get_type (void); -AtkObject *gal_a11y_e_tree_new (GObject *tree); - -void gal_a11y_e_tree_init (void); - -#endif /* ! __GAL_A11Y_E_TREE_H__ */ diff --git a/widgets/table/e-cell-popup.c b/widgets/table/e-cell-popup.c index 26897709c2..298f67db82 100644 --- a/widgets/table/e-cell-popup.c +++ b/widgets/table/e-cell-popup.c @@ -33,8 +33,8 @@ #include -#include "a11y/gal-a11y-e-cell-popup.h" -#include "a11y/gal-a11y-e-cell-registry.h" +#include "gal-a11y-e-cell-popup.h" +#include "gal-a11y-e-cell-registry.h" #include "e-util/e-util.h" #include "e-cell-popup.h" diff --git a/widgets/table/e-cell-text.c b/widgets/table/e-cell-text.c index c1d5dc88bb..78065025f3 100644 --- a/widgets/table/e-cell-text.c +++ b/widgets/table/e-cell-text.c @@ -45,8 +45,8 @@ #include #include -#include "a11y/gal-a11y-e-cell-registry.h" -#include "a11y/gal-a11y-e-cell-text.h" +#include "gal-a11y-e-cell-registry.h" +#include "gal-a11y-e-cell-text.h" #include "text/e-text.h" #include #include "e-util/e-text-event-processor.h" diff --git a/widgets/table/e-cell-toggle.c b/widgets/table/e-cell-toggle.c index baad2027d5..02a7425e41 100644 --- a/widgets/table/e-cell-toggle.c +++ b/widgets/table/e-cell-toggle.c @@ -28,8 +28,8 @@ #include #include -#include "a11y/gal-a11y-e-cell-toggle.h" -#include "a11y/gal-a11y-e-cell-registry.h" +#include "gal-a11y-e-cell-toggle.h" +#include "gal-a11y-e-cell-registry.h" #include "e-util/e-util.h" #include "misc/e-hsv-utils.h" diff --git a/widgets/table/e-cell-tree.c b/widgets/table/e-cell-tree.c index c3ecca939b..2156aa9917 100644 --- a/widgets/table/e-cell-tree.c +++ b/widgets/table/e-cell-tree.c @@ -38,8 +38,8 @@ #include #include -#include "a11y/gal-a11y-e-cell-registry.h" -#include "a11y/gal-a11y-e-cell-tree.h" +#include "gal-a11y-e-cell-registry.h" +#include "gal-a11y-e-cell-tree.h" #include "e-util/e-util.h" #include "e-cell-tree.h" diff --git a/widgets/table/e-cell-vbox.c b/widgets/table/e-cell-vbox.c index 30bb9027a9..210cc84139 100644 --- a/widgets/table/e-cell-vbox.c +++ b/widgets/table/e-cell-vbox.c @@ -29,8 +29,8 @@ #include -#include "a11y/gal-a11y-e-cell-registry.h" -#include "a11y/gal-a11y-e-cell-vbox.h" +#include "gal-a11y-e-cell-registry.h" +#include "gal-a11y-e-cell-vbox.h" #include "e-util/e-util.h" #include "e-cell-vbox.h" diff --git a/widgets/table/e-table-click-to-add.c b/widgets/table/e-table-click-to-add.c index 99a290dea2..d2d1534611 100644 --- a/widgets/table/e-table-click-to-add.c +++ b/widgets/table/e-table-click-to-add.c @@ -29,7 +29,7 @@ #include #include -#include "a11y/gal-a11y-e-table-click-to-add.h" +#include "gal-a11y-e-table-click-to-add.h" #include "text/e-text.h" #include #include "e-util/e-util.h" diff --git a/widgets/table/e-table-item.c b/widgets/table/e-table-item.c index c5cfa1878f..7448a355f7 100644 --- a/widgets/table/e-table-item.c +++ b/widgets/table/e-table-item.c @@ -36,8 +36,8 @@ #include #include -#include "a11y/gal-a11y-e-table-item-factory.h" -#include "a11y/gal-a11y-e-table-item.h" +#include "gal-a11y-e-table-item-factory.h" +#include "gal-a11y-e-table-item.h" #include #include "e-util/e-util.h" #include "misc/e-canvas.h" diff --git a/widgets/table/e-table.c b/widgets/table/e-table.c index 7f756d95a4..bf18fbb224 100644 --- a/widgets/table/e-table.c +++ b/widgets/table/e-table.c @@ -36,7 +36,7 @@ #include #include -#include "a11y/gal-a11y-e-table.h" +#include "gal-a11y-e-table.h" #include #include "e-util/e-util.h" #include "misc/e-canvas.h" diff --git a/widgets/table/e-tree.c b/widgets/table/e-tree.c index 8124a59c64..dd07b2b536 100644 --- a/widgets/table/e-tree.c +++ b/widgets/table/e-tree.c @@ -30,7 +30,7 @@ #include #include -#include "a11y/gal-a11y-e-tree.h" +#include "gal-a11y-e-tree.h" #include #include "e-util/e-util.h" #include "misc/e-canvas.h" diff --git a/widgets/table/gal-a11y-e-cell-popup.c b/widgets/table/gal-a11y-e-cell-popup.c new file mode 100644 index 0000000000..141ce172a4 --- /dev/null +++ b/widgets/table/gal-a11y-e-cell-popup.c @@ -0,0 +1,144 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Yang Wu + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include + +#include +#include + +#include "a11y/gal-a11y-util.h" +#include "table/e-cell-popup.h" +#include + +#include "gal-a11y-e-cell-popup.h" +#include "gal-a11y-e-cell-registry.h" + +static AtkObjectClass *parent_class = NULL; +#define PARENT_TYPE (gal_a11y_e_cell_get_type ()) + +static void gal_a11y_e_cell_popup_class_init (GalA11yECellPopupClass *klass); +static void popup_cell_action (GalA11yECell *cell); + +/** + * gal_a11y_e_cell_popup_get_type: + * @void: + * + * Registers the &GalA11yECellPopup class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yECellPopup class. + **/ +GType +gal_a11y_e_cell_popup_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yECellPopupClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gal_a11y_e_cell_popup_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yECellPopup), + 0, + (GInstanceInitFunc) NULL, + NULL /* value_cell_popup */ + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yECellPopup", &info, 0); + gal_a11y_e_cell_type_add_action_interface (type); + } + + return type; +} + +static void +gal_a11y_e_cell_popup_class_init (GalA11yECellPopupClass *klass) +{ + parent_class = g_type_class_ref (PARENT_TYPE); +} + +AtkObject * +gal_a11y_e_cell_popup_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + gint model_col, + gint view_col, + gint row) +{ + AtkObject *a11y; + GalA11yECell *cell; + ECellPopup *popupcell; + ECellView* child_view = NULL; + + popupcell= E_CELL_POPUP(cell_view->ecell); + + if (popupcell && popupcell->popup_cell_view) + child_view = popupcell->popup_cell_view->child_view; + + if (child_view && child_view->ecell) { + a11y = gal_a11y_e_cell_registry_get_object (NULL, + item, + child_view, + parent, + model_col, + view_col, + row); + } else { + a11y = g_object_new (GAL_A11Y_TYPE_E_CELL_POPUP, NULL); + gal_a11y_e_cell_construct (a11y, + item, + cell_view, + parent, + model_col, + view_col, + row); + } + g_return_val_if_fail (a11y != NULL, NULL); + cell = GAL_A11Y_E_CELL(a11y); + gal_a11y_e_cell_add_action (cell, + _("popup"), /* action name*/ + _("popup a child"), /* action description */ + "Down", /* action keybinding */ + popup_cell_action); + + a11y->role = ATK_ROLE_TABLE_CELL; + return a11y; +} + +static void +popup_cell_action (GalA11yECell *cell) +{ + gint finished; + GdkEvent event; + + event.key.type = GDK_KEY_PRESS; + event.key.window = GTK_LAYOUT(GNOME_CANVAS_ITEM(cell->item)->canvas)->bin_window;; + event.key.send_event = TRUE; + event.key.time = GDK_CURRENT_TIME; + event.key.state = GDK_MOD1_MASK; + event.key.keyval = GDK_Down; + + g_signal_emit_by_name (cell->item, "event", &event, &finished); +} diff --git a/widgets/table/gal-a11y-e-cell-popup.h b/widgets/table/gal-a11y-e-cell-popup.h new file mode 100644 index 0000000000..641d345308 --- /dev/null +++ b/widgets/table/gal-a11y-e-cell-popup.h @@ -0,0 +1,62 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Yang Wu + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_CELL_POPUP_H__ +#define __GAL_A11Y_E_CELL_POPUP_H__ + +#include +#include
+#include
+#include + +#define GAL_A11Y_TYPE_E_CELL_POPUP (gal_a11y_e_cell_popup_get_type ()) +#define GAL_A11Y_E_CELL_POPUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_POPUP, GalA11yECellPopup)) +#define GAL_A11Y_E_CELL_POPUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL_POPUP, GalA11yECellPopupClass)) +#define GAL_A11Y_IS_E_CELL_POPUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_POPUP)) +#define GAL_A11Y_IS_E_CELL_POPUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_POPUP)) + +typedef struct _GalA11yECellPopup GalA11yECellPopup; +typedef struct _GalA11yECellPopupClass GalA11yECellPopupClass; + +/* This struct should actually be larger as this isn't what we derive from. + * The GalA11yECellPopupPrivate comes right after the parent class structure. + **/ +struct _GalA11yECellPopup { + GalA11yECell object; +}; + +struct _GalA11yECellPopupClass { + GalA11yECellClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_cell_popup_get_type (void); +AtkObject *gal_a11y_e_cell_popup_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + gint model_col, + gint view_col, + gint row); + +#endif /* ! __GAL_A11Y_E_CELL_POPUP_H__ */ diff --git a/widgets/table/gal-a11y-e-cell-registry.c b/widgets/table/gal-a11y-e-cell-registry.c new file mode 100644 index 0000000000..9dc9598608 --- /dev/null +++ b/widgets/table/gal-a11y-e-cell-registry.c @@ -0,0 +1,149 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Christopher James Lahey + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include + +#include "gal-a11y-e-cell.h" +#include "gal-a11y-e-cell-registry.h" + +static GObjectClass *parent_class; +static GalA11yECellRegistry *default_registry; +#define PARENT_TYPE (G_TYPE_OBJECT) + +struct _GalA11yECellRegistryPrivate { + GHashTable *table; +}; + +/* Static functions */ + +static void +gal_a11y_e_cell_registry_finalize (GObject *obj) +{ + GalA11yECellRegistry *registry = GAL_A11Y_E_CELL_REGISTRY (obj); + + g_hash_table_destroy (registry->priv->table); + g_free (registry->priv); + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +gal_a11y_e_cell_registry_class_init (GalA11yECellRegistryClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + object_class->finalize = gal_a11y_e_cell_registry_finalize; +} + +static void +gal_a11y_e_cell_registry_init (GalA11yECellRegistry *registry) +{ + registry->priv = g_new (GalA11yECellRegistryPrivate, 1); + registry->priv->table = g_hash_table_new (NULL, NULL); +} + +/** + * gal_a11y_e_cell_registry_get_type: + * @void: + * + * Registers the &GalA11yECellRegistry class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yECellRegistry class. + **/ +GType +gal_a11y_e_cell_registry_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yECellRegistryClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gal_a11y_e_cell_registry_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yECellRegistry), + 0, + (GInstanceInitFunc) gal_a11y_e_cell_registry_init, + NULL /* value_cell */ + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yECellRegistry", &info, 0); + } + + return type; +} + +static void +init_default_registry (void) +{ + if (default_registry == NULL) { + default_registry = g_object_new (gal_a11y_e_cell_registry_get_type(), NULL); + } +} + + +AtkObject * +gal_a11y_e_cell_registry_get_object (GalA11yECellRegistry *registry, + ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + gint model_col, + gint view_col, + gint row) +{ + GalA11yECellRegistryFunc func = NULL; + GType type; + + if (registry == NULL) { + init_default_registry (); + registry = default_registry; + } + + type = GTK_OBJECT_TYPE (cell_view->ecell); + while (func == NULL && type != 0) { + func = g_hash_table_lookup (registry->priv->table, GINT_TO_POINTER (type)); + type = g_type_parent (type); + } + + if (func) + return func (item, cell_view, parent, model_col, view_col, row); + else + return gal_a11y_e_cell_new (item, cell_view, parent, model_col, view_col, row); +} + +void +gal_a11y_e_cell_registry_add_cell_type (GalA11yECellRegistry *registry, + GType type, + GalA11yECellRegistryFunc func) +{ + if (registry == NULL) { + init_default_registry (); + registry = default_registry; + } + + g_hash_table_insert (registry->priv->table, GINT_TO_POINTER (type), func); +} diff --git a/widgets/table/gal-a11y-e-cell-registry.h b/widgets/table/gal-a11y-e-cell-registry.h new file mode 100644 index 0000000000..0620fd1b9c --- /dev/null +++ b/widgets/table/gal-a11y-e-cell-registry.h @@ -0,0 +1,72 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Christopher James Lahey + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_CELL_REGISTRY_H__ +#define __GAL_A11Y_E_CELL_REGISTRY_H__ + +#include +#include +#include
+#include
+ +#define GAL_A11Y_TYPE_E_CELL_REGISTRY (gal_a11y_e_cell_registry_get_type ()) +#define GAL_A11Y_E_CELL_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_REGISTRY, GalA11yECellRegistry)) +#define GAL_A11Y_E_CELL_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL_REGISTRY, GalA11yECellRegistryClass)) +#define GAL_A11Y_IS_E_CELL_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_REGISTRY)) +#define GAL_A11Y_IS_E_CELL_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_REGISTRY)) + +typedef struct _GalA11yECellRegistry GalA11yECellRegistry; +typedef struct _GalA11yECellRegistryClass GalA11yECellRegistryClass; +typedef struct _GalA11yECellRegistryPrivate GalA11yECellRegistryPrivate; + +typedef AtkObject *(*GalA11yECellRegistryFunc) (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + gint model_col, + gint view_col, + gint row); + +struct _GalA11yECellRegistry { + GObject object; + + GalA11yECellRegistryPrivate *priv; +}; + +struct _GalA11yECellRegistryClass { + GObjectClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_cell_registry_get_type (void); +AtkObject *gal_a11y_e_cell_registry_get_object (GalA11yECellRegistry *registry, + ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + gint model_col, + gint view_col, + gint row); +void gal_a11y_e_cell_registry_add_cell_type (GalA11yECellRegistry *registry, + GType type, + GalA11yECellRegistryFunc func); + +#endif /* ! __GAL_A11Y_E_CELL_REGISTRY_H__ */ diff --git a/widgets/table/gal-a11y-e-cell-text.c b/widgets/table/gal-a11y-e-cell-text.c new file mode 100644 index 0000000000..77823b0a7c --- /dev/null +++ b/widgets/table/gal-a11y-e-cell-text.c @@ -0,0 +1,737 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Christopher James Lahey + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include + +#include + +#include + +#include "a11y/gal-a11y-util.h" +#include "table/e-cell-text.h" +#include + +#include "gal-a11y-e-cell-text.h" + +#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yECellTextClass)) +static AtkObjectClass *parent_class; +#define PARENT_TYPE (gal_a11y_e_cell_get_type ()) + +/* Static functions */ +static void +ect_dispose (GObject *object) +{ + GObjectClass *g_class; + GalA11yECell *gaec = GAL_A11Y_E_CELL (object); + GalA11yECellText *gaet = GAL_A11Y_E_CELL_TEXT (object); + + if (gaet->inserted_id != 0) { + ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell); + + if (ect) { + g_signal_handler_disconnect (ect, gaet->inserted_id); + g_signal_handler_disconnect (ect, gaet->deleted_id); + } + + gaet->inserted_id = 0; + gaet->deleted_id = 0; + } + + g_class = (GObjectClass *)parent_class; + if (g_class->dispose) + g_class->dispose (object); + +} + +static gboolean +ect_check (gpointer a11y) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (a11y); + ETableItem *item = gaec->item; + + g_return_val_if_fail ((gaec->item != NULL), FALSE); + g_return_val_if_fail ((gaec->cell_view != NULL), FALSE); + g_return_val_if_fail ((gaec->cell_view->ecell != NULL), FALSE); + + if (atk_state_set_contains_state (gaec->state_set, ATK_STATE_DEFUNCT)) + return FALSE; + + if (gaec->row < 0 || gaec->row >= item->rows + || gaec->view_col <0 || gaec->view_col >= item->cols + || gaec->model_col <0 || gaec->model_col >= e_table_model_column_count (item->table_model)) + return FALSE; + + if (!E_IS_CELL_TEXT (gaec->cell_view->ecell)) + return FALSE; + + return TRUE; +} + +static G_CONST_RETURN gchar * +ect_get_name (AtkObject * a11y) +{ + GalA11yECell *gaec; + gchar *name; + + if (!ect_check (a11y)) + return NULL; + + gaec = GAL_A11Y_E_CELL (a11y); + name = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); + if (name != NULL) { + ATK_OBJECT_CLASS (parent_class)->set_name (a11y, name); + g_free (name); + } + + if (a11y->name != NULL && strcmp (a11y->name, "")) { + return a11y->name; + } else { + return parent_class->get_name (a11y); + } +} + +static gchar * +ect_get_text (AtkText *text, + gint start_offset, + gint end_offset) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + gchar *full_text; + gchar *ret_val; + + if (!ect_check (text)) + return NULL; + + full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); + + if (end_offset == -1) + end_offset = strlen (full_text); + else + end_offset = g_utf8_offset_to_pointer (full_text, end_offset) - full_text; + + start_offset = g_utf8_offset_to_pointer (full_text, start_offset) - full_text; + + ret_val = g_strndup (full_text + start_offset, end_offset - start_offset); + + g_free (full_text); + + return ret_val; +} + +static gchar * +ect_get_text_after_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset) +{ + /* Unimplemented */ + return NULL; +} + +static gchar * +ect_get_text_at_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset) +{ + /* Unimplemented */ + return NULL; +} + +static gunichar +ect_get_character_at_offset (AtkText *text, + gint offset) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + gunichar ret_val; + gchar *at_offset; + gchar *full_text; + + if (!ect_check (text)) + return -1; + + full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); + at_offset = g_utf8_offset_to_pointer (full_text, offset); + ret_val = g_utf8_get_char_validated (at_offset, -1); + g_free (full_text); + + return ret_val; +} + + +static gchar * +ect_get_text_before_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset) +{ + /* Unimplemented */ + return NULL; +} + + +static gint +ect_get_caret_offset (AtkText *text) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + gint start, end; + + if (!ect_check (text)) + return -1; + + if (e_cell_text_get_selection (gaec->cell_view, + gaec->view_col, gaec->row, + &start, &end)) { + gchar *full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); + end = g_utf8_pointer_to_offset (full_text, full_text + end); + g_free (full_text); + + return end; + } + else + return -1; +} + +static AtkAttributeSet* +ect_get_run_attributes (AtkText *text, + gint offset, + gint *start_offset, + gint *end_offset) +{ + /* Unimplemented */ + return NULL; +} + + +static AtkAttributeSet* +ect_get_default_attributes (AtkText *text) +{ + /* Unimplemented */ + return NULL; +} + + +static void +ect_get_character_extents (AtkText *text, + gint offset, + gint *x, + gint *y, + gint *width, + gint *height, + AtkCoordType coords) +{ + /* Unimplemented */ +} + + +static gint +ect_get_character_count (AtkText *text) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + gint ret_val; + gchar *full_text; + + if (!ect_check (text)) + return -1; + + full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); + + ret_val = g_utf8_strlen (full_text, -1); + g_free (full_text); + return ret_val; +} + + +static gint +ect_get_offset_at_point (AtkText *text, + gint x, + gint y, + AtkCoordType coords) +{ + /* Unimplemented */ + return 0; +} + + +static gint +ect_get_n_selections (AtkText *text) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + gint selection_start, selection_end; + + if (!ect_check (text)) + return 0; + + if (e_cell_text_get_selection (gaec->cell_view, + gaec->view_col, gaec->row, + &selection_start, + &selection_end) + && selection_start != selection_end) + return 1; + return 0; +} + + +static gchar * +ect_get_selection (AtkText *text, + gint selection_num, + gint *start_offset, + gint *end_offset) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + gchar *ret_val; + gint selection_start, selection_end; + + if (selection_num == 0 + && e_cell_text_get_selection (gaec->cell_view, + gaec->view_col, gaec->row, + &selection_start, + &selection_end) + && selection_start != selection_end) { + gint real_start, real_end, len; + gchar *full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); + len = strlen (full_text); + real_start = MIN (selection_start, selection_end); + real_end = MAX (selection_start, selection_end); + real_start = MIN (MAX (0, real_start), len); + real_end = MIN (MAX (0, real_end), len); + + ret_val = g_strndup (full_text + real_start, real_end - real_start); + + real_start = g_utf8_pointer_to_offset (full_text, full_text + real_start); + real_end = g_utf8_pointer_to_offset (full_text, full_text + real_end); + + if (start_offset) + *start_offset = real_start; + if (end_offset) + *end_offset = real_end; + g_free (full_text); + } else { + if (start_offset) + *start_offset = 0; + if (end_offset) + *end_offset = 0; + ret_val = NULL; + } + + return ret_val; +} + + +static gboolean +ect_add_selection (AtkText *text, + gint start_offset, + gint end_offset) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + + if (start_offset != end_offset) { + gint real_start, real_end, len; + gchar *full_text = + e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); + + len = g_utf8_strlen (full_text, -1); + if (end_offset == -1) + end_offset = len; + + real_start = MIN (start_offset, end_offset); + real_end = MAX (start_offset, end_offset); + + real_start = MIN (MAX (0, real_start), len); + real_end = MIN (MAX (0, real_end), len); + + real_start = g_utf8_offset_to_pointer (full_text, real_start) - full_text; + real_end = g_utf8_offset_to_pointer (full_text, real_end) - full_text; + g_free (full_text); + + if (e_cell_text_set_selection (gaec->cell_view, + gaec->view_col, gaec->row, + real_start, real_end)) { + g_signal_emit_by_name (ATK_OBJECT(text), "text_selection_changed"); + return TRUE; + } + } + + return FALSE; +} + + +static gboolean +ect_remove_selection (AtkText *text, + gint selection_num) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + gint selection_start, selection_end; + + if (selection_num == 0 + && e_cell_text_get_selection (gaec->cell_view, + gaec->view_col, gaec->row, + &selection_start, + &selection_end) + && selection_start != selection_end + && e_cell_text_set_selection (gaec->cell_view, + gaec->view_col, gaec->row, + selection_end, selection_end)) { + g_signal_emit_by_name (ATK_OBJECT(text), "text_selection_changed"); + return TRUE; + } + else + return FALSE; +} + + +static gboolean +ect_set_selection (AtkText *text, + gint selection_num, + gint start_offset, + gint end_offset) +{ + if (selection_num == 0) { + atk_text_add_selection (text, start_offset, end_offset); + return TRUE; + } + else + return FALSE; +} + + +static gboolean +ect_set_caret_offset (AtkText *text, + gint offset) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + gchar *full_text; + gint len; + + full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); + + len = g_utf8_strlen (full_text, -1); + if (offset == -1) + offset = len; + else + offset = MIN (MAX (0, offset), len); + + offset = g_utf8_offset_to_pointer (full_text, offset) - full_text; + + g_free (full_text); + + return e_cell_text_set_selection (gaec->cell_view, + gaec->view_col, gaec->row, + offset, offset); +} + +static gboolean +ect_set_run_attributes (AtkEditableText *text, + AtkAttributeSet *attrib_set, + gint start_offset, + gint end_offset) +{ + /* Unimplemented */ + return FALSE; +} + +static void +ect_set_text_contents (AtkEditableText *text, + const gchar *string) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell); + + e_cell_text_set_value (ect, gaec->item->table_model, gaec->model_col, gaec->row, string); + e_table_item_enter_edit (gaec->item, gaec->view_col, gaec->row); +} + +static void +ect_insert_text (AtkEditableText *text, + const gchar *string, + gint length, + gint *position) +{ + /* Utf8 unimplemented */ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell); + + gchar *full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); + gchar *result = g_strdup_printf ("%.*s%.*s%s", *position, full_text, length, string, full_text + *position); + + e_cell_text_set_value (ect, gaec->item->table_model, gaec->model_col, gaec->row, result); + + *position += length; + + g_free (result); + g_free (full_text); +} + +static void +ect_copy_text (AtkEditableText *text, + gint start_pos, + gint end_pos) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + if (start_pos != end_pos + && atk_text_set_selection (ATK_TEXT (text), 0, start_pos, end_pos)) + e_cell_text_copy_clipboard (gaec->cell_view, + gaec->view_col, gaec->row); +} + +static void +ect_delete_text (AtkEditableText *text, + gint start_pos, + gint end_pos) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + if (start_pos != end_pos + && atk_text_set_selection (ATK_TEXT (text), 0, start_pos, end_pos)) + e_cell_text_delete_selection (gaec->cell_view, + gaec->view_col, gaec->row); +} + +static void +ect_cut_text (AtkEditableText *text, + gint start_pos, + gint end_pos) +{ + ect_copy_text (text, start_pos, end_pos); + ect_delete_text (text, start_pos, end_pos); +} + +static void +ect_paste_text (AtkEditableText *text, + gint position) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + + e_table_item_enter_edit (gaec->item, gaec->view_col, gaec->row); + + if (atk_text_set_caret_offset (ATK_TEXT (text), position)) + e_cell_text_paste_clipboard (gaec->cell_view, + gaec->view_col, gaec->row); +} + +static void +ect_do_action_edit (AtkAction *action) +{ + GalA11yECell *a11y = GAL_A11Y_E_CELL (action); + ETableModel *e_table_model = a11y->item->table_model; + + if (e_table_model_is_cell_editable(e_table_model, a11y->model_col, a11y->row)) { + e_table_item_enter_edit (a11y->item, a11y->view_col, a11y->row); + } +} + +/* text signal handlers */ +static void +ect_text_inserted_cb (ECellText *text, ECellView *cell_view, gint pos, gint len, gint row, gint model_col, gpointer data) +{ + GalA11yECellText *gaet; + GalA11yECell *gaec; + + if (!ect_check (data)) + return; + gaet = GAL_A11Y_E_CELL_TEXT (data); + gaec = GAL_A11Y_E_CELL (data); + + if (cell_view == gaec->cell_view && row == gaec->row && model_col == gaec->model_col) { + g_signal_emit_by_name (gaet, "text_changed::insert", pos, len); + + } +} + +static void +ect_text_deleted_cb (ECellText *text, ECellView *cell_view, gint pos, gint len, gint row, gint model_col, gpointer data) +{ + GalA11yECellText *gaet; + GalA11yECell *gaec; + if (!ect_check (data)) + return; + gaet = GAL_A11Y_E_CELL_TEXT (data); + gaec = GAL_A11Y_E_CELL (data); + if (cell_view == gaec->cell_view && row == gaec->row && model_col == gaec->model_col) { + g_signal_emit_by_name (gaet, "text_changed::delete", pos, len); + } +} + +static void +ect_atk_text_iface_init (AtkTextIface *iface) +{ + iface->get_text = ect_get_text; + iface->get_text_after_offset = ect_get_text_after_offset; + iface->get_text_at_offset = ect_get_text_at_offset; + iface->get_character_at_offset = ect_get_character_at_offset; + iface->get_text_before_offset = ect_get_text_before_offset; + iface->get_caret_offset = ect_get_caret_offset; + iface->get_run_attributes = ect_get_run_attributes; + iface->get_default_attributes = ect_get_default_attributes; + iface->get_character_extents = ect_get_character_extents; + iface->get_character_count = ect_get_character_count; + iface->get_offset_at_point = ect_get_offset_at_point; + iface->get_n_selections = ect_get_n_selections; + iface->get_selection = ect_get_selection; + iface->add_selection = ect_add_selection; + iface->remove_selection = ect_remove_selection; + iface->set_selection = ect_set_selection; + iface->set_caret_offset = ect_set_caret_offset; +} + +static void +ect_atk_editable_text_iface_init (AtkEditableTextIface *iface) +{ + iface->set_run_attributes = ect_set_run_attributes; + iface->set_text_contents = ect_set_text_contents; + iface->insert_text = ect_insert_text; + iface->copy_text = ect_copy_text; + iface->cut_text = ect_cut_text; + iface->delete_text = ect_delete_text; + iface->paste_text = ect_paste_text; +} + +static void +ect_class_init (GalA11yECellTextClass *klass) +{ + AtkObjectClass *a11y = ATK_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + a11y->get_name = ect_get_name; + object_class->dispose = ect_dispose; +} + +static void +ect_action_init (GalA11yECellText *a11y) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (a11y); + ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell); + if (ect->editable && e_table_model_is_cell_editable (gaec->cell_view->e_table_model, gaec->model_col, gaec->row)) + gal_a11y_e_cell_add_action (gaec, + _("edit"), + _("begin editing this cell"), + NULL, + (ACTION_FUNC) ect_do_action_edit); +} + +/** + * gal_a11y_e_cell_text_get_type: + * @void: + * + * Registers the &GalA11yECellText class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yECellText class. + **/ +GType +gal_a11y_e_cell_text_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yECellTextClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ect_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yECellText), + 0, + (GInstanceInitFunc) NULL, + NULL /* value_cell_text */ + }; + + static const GInterfaceInfo atk_text_info = { + (GInterfaceInitFunc) ect_atk_text_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + static const GInterfaceInfo atk_editable_text_info = { + (GInterfaceInitFunc) ect_atk_editable_text_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yECellText", &info, 0); + g_type_add_interface_static (type, ATK_TYPE_TEXT, &atk_text_info); + g_type_add_interface_static (type, ATK_TYPE_EDITABLE_TEXT, &atk_editable_text_info); + gal_a11y_e_cell_type_add_action_interface (type); + } + + return type; +} + +static void +cell_text_destroyed (gpointer data) +{ + g_return_if_fail (GAL_A11Y_IS_E_CELL_TEXT (data)); + + g_object_unref (data); +} + +AtkObject * +gal_a11y_e_cell_text_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + gint model_col, + gint view_col, + gint row) +{ + AtkObject *a11y; + GalA11yECell *gaec; + GalA11yECellText *gaet; + ECellText *ect; + + a11y = g_object_new (gal_a11y_e_cell_text_get_type (), NULL); + + gal_a11y_e_cell_construct (a11y, + item, + cell_view, + parent, + model_col, + view_col, + row); + gaet = GAL_A11Y_E_CELL_TEXT (a11y); + + /* will be unrefed in cell_text_destroyed */ + g_object_ref (a11y); + + gaet->inserted_id = g_signal_connect (E_CELL_TEXT (((ECellView *)cell_view)->ecell), + "text_inserted", G_CALLBACK (ect_text_inserted_cb), a11y); + gaet->deleted_id = g_signal_connect (E_CELL_TEXT (((ECellView *)cell_view)->ecell), + "text_deleted", G_CALLBACK (ect_text_deleted_cb), a11y); + + g_object_weak_ref (G_OBJECT (((ECellView *)cell_view)->ecell), + (GWeakNotify) cell_text_destroyed, + a11y); + + ect_action_init (gaet); + + ect = E_CELL_TEXT (cell_view->ecell); + gaec = GAL_A11Y_E_CELL (a11y); + if (ect->editable && e_table_model_is_cell_editable (gaec->cell_view->e_table_model, gaec->model_col, gaec->row)) + gal_a11y_e_cell_add_state (gaec, ATK_STATE_EDITABLE, FALSE); + else + gal_a11y_e_cell_remove_state (gaec, ATK_STATE_EDITABLE, FALSE); + + return a11y; +} diff --git a/widgets/table/gal-a11y-e-cell-text.h b/widgets/table/gal-a11y-e-cell-text.h new file mode 100644 index 0000000000..bb400b38e3 --- /dev/null +++ b/widgets/table/gal-a11y-e-cell-text.h @@ -0,0 +1,64 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Christopher James Lahey + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_CELL_TEXT_H__ +#define __GAL_A11Y_E_CELL_TEXT_H__ + +#include +#include
+#include
+#include
+ +#define GAL_A11Y_TYPE_E_CELL_TEXT (gal_a11y_e_cell_text_get_type ()) +#define GAL_A11Y_E_CELL_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_TEXT, GalA11yECellText)) +#define GAL_A11Y_E_CELL_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL_TEXT, GalA11yECellTextClass)) +#define GAL_A11Y_IS_E_CELL_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_TEXT)) +#define GAL_A11Y_IS_E_CELL_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_TEXT)) + +typedef struct _GalA11yECellText GalA11yECellText; +typedef struct _GalA11yECellTextClass GalA11yECellTextClass; +typedef struct _GalA11yECellTextPrivate GalA11yECellTextPrivate; + +/* This struct should actually be larger as this isn't what we derive from. + * The GalA11yECellTextPrivate comes right after the parent class structure. + **/ +struct _GalA11yECellText { + GalA11yECell object; + gint inserted_id; + gint deleted_id; +}; + +struct _GalA11yECellTextClass { + GalA11yECellClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_cell_text_get_type (void); +AtkObject *gal_a11y_e_cell_text_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + gint model_col, + gint view_col, + gint row); + +#endif /* ! __GAL_A11Y_E_CELL_TEXT_H__ */ diff --git a/widgets/table/gal-a11y-e-cell-toggle.c b/widgets/table/gal-a11y-e-cell-toggle.c new file mode 100644 index 0000000000..df687f4005 --- /dev/null +++ b/widgets/table/gal-a11y-e-cell-toggle.c @@ -0,0 +1,191 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include + +#include "table/e-cell-toggle.h" +#include "table/e-table-model.h" +#include + +#include "gal-a11y-e-cell-toggle.h" + +#define PARENT_TYPE (gal_a11y_e_cell_get_type ()) +static GObjectClass *parent_class; + +static void gal_a11y_e_cell_toggle_class_init (GalA11yECellToggleClass *klass); + +static void +gal_a11y_e_cell_toggle_dispose (GObject *object) +{ + GalA11yECellToggle *a11y = GAL_A11Y_E_CELL_TOGGLE (object); + + ETableModel *e_table_model = GAL_A11Y_E_CELL (a11y)->item->table_model; + + if (e_table_model && a11y->model_id > 0) { + g_signal_handler_disconnect (e_table_model, a11y->model_id); + a11y->model_id = 0; + } + + if (parent_class->dispose) + parent_class->dispose (object); +} + +GType +gal_a11y_e_cell_toggle_get_type (void) +{ + static GType type = 0; + + if (!type) + { + static const GTypeInfo tinfo = + { + sizeof (GalA11yECellToggleClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) gal_a11y_e_cell_toggle_class_init, /* class init */ + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (GalA11yECellToggle), /* instance size */ + 0, /* nb preallocs */ + NULL, /* instance init */ + NULL /* value table */ + }; + + + type = g_type_register_static (GAL_A11Y_TYPE_E_CELL, + "GalA11yECellToggle", &tinfo, 0); + gal_a11y_e_cell_type_add_action_interface (type); + + } + return type; +} + + +static void +gal_a11y_e_cell_toggle_class_init (GalA11yECellToggleClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = gal_a11y_e_cell_toggle_dispose; + parent_class = g_type_class_ref (PARENT_TYPE); +} + +static void +toggle_cell_action (GalA11yECell *cell) +{ + gint finished; + GdkEventButton event; + gint x, y, width, height; + gint row, col; + + row = cell->row; + col = cell->view_col; + + e_table_item_get_cell_geometry (cell->item, &row, &col, + &x, &y, &width, &height); + + event.x = x + width / 2 + (gint)(GNOME_CANVAS_ITEM (cell->item)->x1); + event.y = y + height / 2 + (gint)(GNOME_CANVAS_ITEM (cell->item)->y1); + + event.type = GDK_BUTTON_PRESS; + event.window = GTK_LAYOUT(GNOME_CANVAS_ITEM(cell->item)->canvas)->bin_window; + event.button = 1; + event.send_event = TRUE; + event.time = GDK_CURRENT_TIME; + event.axes = NULL; + + g_signal_emit_by_name (cell->item, "event", &event, &finished); +} + +static void +model_change_cb (ETableModel *etm, + gint col, + gint row, + GalA11yECell *cell) +{ + gint value; + + if (col == cell->model_col && row == cell->row) { + + value = GPOINTER_TO_INT ( + e_table_model_value_at (cell->cell_view->e_table_model, + cell->model_col, cell->row)); + /* Cheat gnopernicus, or it will ignore the state change signal */ + atk_focus_tracker_notify (ATK_OBJECT (cell)); + + if (value) + gal_a11y_e_cell_add_state (cell, ATK_STATE_CHECKED, TRUE); + else + gal_a11y_e_cell_remove_state (cell, ATK_STATE_CHECKED, TRUE); + } +} + + +AtkObject* +gal_a11y_e_cell_toggle_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + gint model_col, + gint view_col, + gint row) +{ + AtkObject *a11y; + GalA11yECell *cell; + GalA11yECellToggle *toggle_cell; + gint value; + + a11y = ATK_OBJECT(g_object_new (GAL_A11Y_TYPE_E_CELL_TOGGLE, NULL)); + + g_return_val_if_fail (a11y != NULL, NULL); + + cell = GAL_A11Y_E_CELL(a11y); + toggle_cell = GAL_A11Y_E_CELL_TOGGLE(a11y); + a11y->role = ATK_ROLE_TABLE_CELL; + + gal_a11y_e_cell_construct (a11y, + item, + cell_view, + parent, + model_col, + view_col, + row); + + gal_a11y_e_cell_add_action (cell, + _("toggle"), /* action name*/ + _("toggle the cell"), /* action description */ + NULL, /* action keybinding */ + toggle_cell_action); + + toggle_cell->model_id = g_signal_connect (item->table_model, + "model_cell_changed", + (GCallback) model_change_cb, + a11y); + + value = GPOINTER_TO_INT ( + e_table_model_value_at (cell->cell_view->e_table_model, + cell->model_col, cell->row)); + if (value) + gal_a11y_e_cell_add_state (cell, ATK_STATE_CHECKED, FALSE); + else + gal_a11y_e_cell_remove_state (cell, ATK_STATE_CHECKED, FALSE); + + return a11y; +} diff --git a/widgets/table/gal-a11y-e-cell-toggle.h b/widgets/table/gal-a11y-e-cell-toggle.h new file mode 100644 index 0000000000..8e9b4def08 --- /dev/null +++ b/widgets/table/gal-a11y-e-cell-toggle.h @@ -0,0 +1,64 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_CELL_TOGGLE_H__ +#define __GAL_A11Y_E_CELL_TOGGLE_H__ + +#include +#include "gal-a11y-e-cell.h" +#include "gal-a11y-e-cell-toggle.h" + +G_BEGIN_DECLS + +#define GAL_A11Y_TYPE_E_CELL_TOGGLE (gal_a11y_e_cell_toggle_get_type ()) +#define GAL_A11Y_E_CELL_TOGGLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_TOGGLE, GalA11yECellToggle)) +#define GAL_A11Y_E_CELL_TOGGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_E_CELL_TOGGLE, GalA11yECellToggleClass)) +#define GAL_A11Y_IS_E_CELL_TOGGLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_TOGGLE)) +#define GAL_A11Y_IS_E_CELL_TOGGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_TOGGLE)) +#define GAL_A11Y_E_CELL_TOGGLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAL_A11Y_TYPE_E_CELL_TOGGLE, GalA11yECellToggleClass)) + +typedef struct _GalA11yECellToggle GalA11yECellToggle; +typedef struct _GalA11yECellToggleClass GalA11yECellToggleClass; + +struct _GalA11yECellToggle +{ + GalA11yECell parent; + gint model_id; +}; + +GType gal_a11y_e_cell_toggle_get_type (void); + +struct _GalA11yECellToggleClass +{ + GalA11yECellClass parent_class; +}; + +AtkObject *gal_a11y_e_cell_toggle_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + gint model_col, + gint view_col, + gint row); + +G_END_DECLS + + +#endif /* __GAL_A11Y_E_CELL_TOGGLE_H__ */ diff --git a/widgets/table/gal-a11y-e-cell-tree.c b/widgets/table/gal-a11y-e-cell-tree.c new file mode 100644 index 0000000000..aaf490c726 --- /dev/null +++ b/widgets/table/gal-a11y-e-cell-tree.c @@ -0,0 +1,260 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Tim Wo + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include + +#include + +#include "a11y/gal-a11y-util.h" +#include "table/e-cell-tree.h" +#include "table/e-table.h" +#include "table/e-tree-table-adapter.h" +#include + +#include "gal-a11y-e-cell-tree.h" +#include "gal-a11y-e-cell-registry.h" + +#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yECellTreeClass)) +static AtkObjectClass *a11y_parent_class; +#define A11Y_PARENT_TYPE (gal_a11y_e_cell_get_type ()) + +#define d(x) + +static void +ectr_model_row_changed_cb (ETableModel *etm, + gint row, + GalA11yECell *a11y) +{ + ETreePath node; + ETreeModel *tree_model; + ETreeTableAdapter *tree_table_adapter; + + g_return_if_fail (a11y); + if (a11y->row != row) + return; + + node = e_table_model_value_at (etm, -1, a11y->row); + tree_model = e_table_model_value_at (etm, -2, a11y->row); + tree_table_adapter = e_table_model_value_at (etm, -3, a11y->row); + + if (e_tree_model_node_is_expandable (tree_model, node)) { + gboolean is_exp = e_tree_table_adapter_node_is_expanded (tree_table_adapter, node); + if (is_exp) + gal_a11y_e_cell_add_state (a11y, ATK_STATE_EXPANDED, TRUE); + else + gal_a11y_e_cell_remove_state (a11y, ATK_STATE_EXPANDED, TRUE); + } +} + +static void +kill_view_cb(ECellView *subcell_view, + gpointer psubcell_a11ies) +{ + GList *node; + GList *subcell_a11ies = (GList *) psubcell_a11ies; + GalA11yECell *subcell; + + for (node = subcell_a11ies; node != NULL; node = g_list_next (node)) + { + subcell = GAL_A11Y_E_CELL(node->data); + if (subcell && subcell->cell_view == subcell_view) + { + d(fprintf(stderr, "subcell_view %p deleted before the a11y object %p\n", subcell_view, subcell)); + subcell->cell_view = NULL; + } + } +} + +static void +ectr_subcell_weak_ref (GalA11yECellTree *a11y, + GalA11yECell *subcell_a11y) +{ + ECellView *subcell_view = subcell_a11y ? subcell_a11y->cell_view : NULL; + if (subcell_a11y && subcell_view && subcell_view->kill_view_cb_data) + subcell_view->kill_view_cb_data = g_list_remove(subcell_view->kill_view_cb_data, subcell_a11y); + + g_signal_handler_disconnect (GAL_A11Y_E_CELL (a11y)->item->table_model, + a11y->model_row_changed_id); + g_object_unref (a11y); +} + +static void +ectr_do_action_expand (AtkAction *action) +{ + GalA11yECell *a11y; + ETableModel *table_model; + ETreePath node; + ETreeModel *tree_model; + ETreeTableAdapter *tree_table_adapter; + + a11y = GAL_A11Y_E_CELL (action); + table_model = a11y->item->table_model; + node = e_table_model_value_at (table_model, -1, a11y->row); + tree_model = e_table_model_value_at (table_model, -2, a11y->row); + tree_table_adapter = e_table_model_value_at (table_model, -3, a11y->row); + + if (e_tree_model_node_is_expandable (tree_model, node)) { + e_tree_table_adapter_node_set_expanded (tree_table_adapter, + node, + TRUE); + gal_a11y_e_cell_add_state (a11y, ATK_STATE_EXPANDED, TRUE); + } +} + +static void +ectr_do_action_collapse (AtkAction *action) +{ + GalA11yECell *a11y; + ETableModel *table_model; + ETreePath node; + ETreeModel *tree_model; + ETreeTableAdapter *tree_table_adapter; + + a11y = GAL_A11Y_E_CELL (action); + table_model = a11y->item->table_model; + node = e_table_model_value_at (table_model, -1, a11y->row); + tree_model = e_table_model_value_at (table_model, -2, a11y->row); + tree_table_adapter = e_table_model_value_at (table_model, -3, a11y->row); + + if (e_tree_model_node_is_expandable (tree_model, node)) { + e_tree_table_adapter_node_set_expanded (tree_table_adapter, + node, + FALSE); + gal_a11y_e_cell_remove_state (a11y, ATK_STATE_EXPANDED, TRUE); + } +} + +static void +ectr_class_init (GalA11yECellTreeClass *klass) +{ + a11y_parent_class = g_type_class_ref (A11Y_PARENT_TYPE); +} + +static void +ectr_init (GalA11yECellTree *a11y) +{ +} + +GType +gal_a11y_e_cell_tree_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yECellTreeClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ectr_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yECellTree), + 0, + (GInstanceInitFunc) ectr_init, + NULL /* value_cell_text */ + }; + + type = g_type_register_static (A11Y_PARENT_TYPE, "GalA11yECellTree", &info, 0); + gal_a11y_e_cell_type_add_action_interface (type); + } + + return type; +} + +AtkObject * +gal_a11y_e_cell_tree_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + gint model_col, + gint view_col, + gint row) +{ + AtkObject *subcell_a11y; + GalA11yECellTree *a11y; + + ETreePath node; + ETreeModel *tree_model; + ETreeTableAdapter *tree_table_adapter; + + ECellView *subcell_view; + subcell_view = e_cell_tree_view_get_subcell_view (cell_view); + + if (subcell_view->ecell) { + subcell_a11y = gal_a11y_e_cell_registry_get_object (NULL, + item, + subcell_view, + parent, + model_col, + view_col, + row); + gal_a11y_e_cell_add_action (GAL_A11Y_E_CELL (subcell_a11y), + _("expand"), + _("expands the row in the ETree containing this cell"), + NULL, + (ACTION_FUNC)ectr_do_action_expand); + + gal_a11y_e_cell_add_action (GAL_A11Y_E_CELL (subcell_a11y), + _("collapse"), + _("collapses the row in the ETree containing this cell"), + NULL, + (ACTION_FUNC)ectr_do_action_collapse); + + /* init AtkStates for the cell's a11y object */ + node = e_table_model_value_at (item->table_model, -1, row); + tree_model = e_table_model_value_at (item->table_model, -2, row); + tree_table_adapter = e_table_model_value_at (item->table_model, -3, row); + if (e_tree_model_node_is_expandable (tree_model, node)) { + gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (subcell_a11y), ATK_STATE_EXPANDABLE, FALSE); + if (e_tree_table_adapter_node_is_expanded (tree_table_adapter, node)) + gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (subcell_a11y), ATK_STATE_EXPANDED, FALSE); + } + } + else + subcell_a11y = NULL; + + /* create a companion a11y object, this object has type GalA11yECellTree + and it connects to some signals to determine whether a tree cell is + expanded or collapsed */ + a11y = g_object_new (gal_a11y_e_cell_tree_get_type (), NULL); + gal_a11y_e_cell_construct (ATK_OBJECT (a11y), + item, + cell_view, + parent, + model_col, + view_col, + row); + a11y->model_row_changed_id = + g_signal_connect (item->table_model, "model_row_changed", + G_CALLBACK (ectr_model_row_changed_cb), + subcell_a11y); + + if (subcell_a11y && subcell_view) + { + subcell_view->kill_view_cb = kill_view_cb; + if (!g_list_find(subcell_view->kill_view_cb_data, subcell_a11y)) + subcell_view->kill_view_cb_data = g_list_append(subcell_view->kill_view_cb_data, subcell_a11y); + } + + g_object_weak_ref (G_OBJECT (subcell_a11y), (GWeakNotify) ectr_subcell_weak_ref, a11y); + + return subcell_a11y; +} diff --git a/widgets/table/gal-a11y-e-cell-tree.h b/widgets/table/gal-a11y-e-cell-tree.h new file mode 100644 index 0000000000..497590b351 --- /dev/null +++ b/widgets/table/gal-a11y-e-cell-tree.h @@ -0,0 +1,64 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Tim Wo + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_CELL_TREE_H__ +#define __GAL_A11Y_E_CELL_TREE_H__ + +#include +#include
+#include
+#include "gal-a11y-e-cell.h" + +#define GAL_A11Y_TYPE_E_CELL_TREE (gal_a11y_e_cell_tree_get_type ()) +#define GAL_A11Y_E_CELL_TREE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_TREE, GalA11yECellTree)) +#define GAL_A11Y_E_CELL_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL_TREE, GalA11yECellTreeClass)) +#define GAL_A11Y_IS_E_CELL_TREE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_TREE)) +#define GAL_A11Y_IS_E_CELL_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_TREE)) + +typedef struct _GalA11yECellTree GalA11yECellTree; +typedef struct _GalA11yECellTreeClass GalA11yECellTreeClass; +typedef struct _GalA11yECellTreePrivate GalA11yECellTreePrivate; + +/* This struct should actually be larger as this isn't what we derive from. + * The GalA11yECellTreePrivate comes right after the parent class structure. + **/ +struct _GalA11yECellTree { + GalA11yECell object; + + gint model_row_changed_id; +}; + +struct _GalA11yECellTreeClass { + GalA11yECellClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_cell_tree_get_type (void); +AtkObject *gal_a11y_e_cell_tree_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + gint model_col, + gint view_col, + gint row); + +#endif /* ! __GAL_A11Y_E_CELL_TREE_H__ */ diff --git a/widgets/table/gal-a11y-e-cell-vbox.c b/widgets/table/gal-a11y-e-cell-vbox.c new file mode 100644 index 0000000000..b3f92a695a --- /dev/null +++ b/widgets/table/gal-a11y-e-cell-vbox.c @@ -0,0 +1,225 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Eric Zhao + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * Copyright (C) 2004 Sun Microsystem, Inc. + * + */ + +#include + +#include + +#include "table/e-cell-vbox.h" + +#include "gal-a11y-e-cell-registry.h" +#include "gal-a11y-e-cell-vbox.h" + +static GObjectClass *parent_class; +static AtkComponentIface *component_parent_iface; +#define PARENT_TYPE (gal_a11y_e_cell_get_type ()) + +static gint +ecv_get_n_children (AtkObject *a11y) +{ + g_return_val_if_fail (GAL_A11Y_IS_E_CELL_VBOX (a11y), 0); + + return GAL_A11Y_E_CELL_VBOX (a11y)->a11y_subcell_count; +} + +static void +subcell_destroyed (gpointer data) +{ + GalA11yECell *cell; + AtkObject *parent; + GalA11yECellVbox *gaev; + + g_return_if_fail (GAL_A11Y_IS_E_CELL (data)); + cell = GAL_A11Y_E_CELL (data); + + parent = atk_object_get_parent (ATK_OBJECT (cell)); + g_return_if_fail (GAL_A11Y_IS_E_CELL_VBOX (parent)); + gaev = GAL_A11Y_E_CELL_VBOX (parent); + + if (cell->view_col < gaev->a11y_subcell_count) + gaev->a11y_subcells[cell->view_col] = NULL; +} + +static AtkObject* +ecv_ref_child (AtkObject *a11y, gint i) +{ + GalA11yECellVbox *gaev = GAL_A11Y_E_CELL_VBOX (a11y); + GalA11yECell *gaec = GAL_A11Y_E_CELL (a11y); + ECellVboxView *ecvv = (ECellVboxView *) (gaec->cell_view); + AtkObject *ret; + if (i < gaev->a11y_subcell_count) { + if (gaev->a11y_subcells[i] == NULL) { + ECellView *subcell_view; + gint model_col, row; + row = gaec->row; + model_col = ecvv->model_cols[i]; + subcell_view = ecvv->subcell_views[i]; + ret = gal_a11y_e_cell_registry_get_object (NULL, + gaec->item, + subcell_view, + a11y, + model_col, + gaec->view_col, /* FIXME should the view column use a fake one or the same as its parent? */ + row); + gaev->a11y_subcells[i] = ret; + g_object_ref (ret); + g_object_weak_ref (G_OBJECT (ret), + (GWeakNotify) subcell_destroyed, + ret); + } else { + ret = (AtkObject *) gaev->a11y_subcells[i]; + if (ATK_IS_OBJECT (ret)) + g_object_ref (ret); + else + ret = NULL; + } + } else { + ret = NULL; + } + + return ret; +} + +static void +ecv_dispose (GObject *object) +{ + GalA11yECellVbox *gaev = GAL_A11Y_E_CELL_VBOX (object); + if (gaev->a11y_subcells) + g_free (gaev->a11y_subcells); + + if (parent_class->dispose) + parent_class->dispose (object); +} + +/* AtkComponet interface */ +static AtkObject* +ecv_ref_accessible_at_point (AtkComponent *component, + gint x, + gint y, + AtkCoordType coord_type) +{ + gint x0, y0, width, height; + gint subcell_height, i; + + GalA11yECell *gaec = GAL_A11Y_E_CELL (component); + ECellVboxView *ecvv = (ECellVboxView *) (gaec->cell_view); + + atk_component_get_extents (component, &x0, &y0, &width, &height, coord_type); + x -= x0; + y -= y0; + if (x < 0 || x > width || y < 0 || y > height) + return NULL; + + for (i = 0; i < ecvv->subcell_view_count; i++) { + subcell_height = e_cell_height (ecvv->subcell_views[i], ecvv->model_cols[i], gaec->view_col, gaec->row); + if ( 0 <= y && y <= subcell_height) { + return ecv_ref_child ((AtkObject *)component, i); + } else + y -= subcell_height; + } + + return NULL; +} + +static void +ecv_class_init (GalA11yECellVboxClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + AtkObjectClass *a11y_class = ATK_OBJECT_CLASS (klass); + parent_class = g_type_class_ref (PARENT_TYPE); + + object_class->dispose = ecv_dispose; + + a11y_class->get_n_children = ecv_get_n_children; + a11y_class->ref_child = ecv_ref_child; +} + +static void +ecv_init (GalA11yECellVbox *a11y) +{ +} + +static void +ecv_atk_component_iface_init (AtkComponentIface *iface) +{ + component_parent_iface = g_type_interface_peek_parent (iface); + + iface->ref_accessible_at_point = ecv_ref_accessible_at_point; +} + +GType +gal_a11y_e_cell_vbox_get_type (void) +{ + static GType type = 0; + if (!type) { + GTypeInfo info = { + sizeof (GalA11yECellVboxClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ecv_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yECellVbox), + 0, + (GInstanceInitFunc) ecv_init, + NULL /* value_cell */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) ecv_atk_component_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yECellVbox", &info, 0); + gal_a11y_e_cell_type_add_action_interface (type); + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); + } + + return type; +} + +AtkObject *gal_a11y_e_cell_vbox_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + gint model_col, + gint view_col, + gint row) +{ + AtkObject *a11y; + GalA11yECell *gaec; + GalA11yECellVbox *gaev; + ECellVboxView *ecvv; + + a11y = g_object_new (gal_a11y_e_cell_vbox_get_type (), NULL); + + gal_a11y_e_cell_construct (a11y, item, cell_view, parent, model_col, view_col, row); + + gaec = GAL_A11Y_E_CELL (a11y); + gaev = GAL_A11Y_E_CELL_VBOX (a11y); + ecvv = (ECellVboxView *) (gaec->cell_view); + gaev->a11y_subcell_count = ecvv->subcell_view_count; + gaev->a11y_subcells = g_malloc0 (sizeof(AtkObject *)*gaev->a11y_subcell_count); + return a11y; +} diff --git a/widgets/table/gal-a11y-e-cell-vbox.h b/widgets/table/gal-a11y-e-cell-vbox.h new file mode 100644 index 0000000000..657cb5d9a5 --- /dev/null +++ b/widgets/table/gal-a11y-e-cell-vbox.h @@ -0,0 +1,63 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Eric Zhao + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * Copyright (C) 2004 Sun Microsystem, Inc. + * + */ + +#ifndef __GAL_A11Y_E_CELL_VBOX_H__ +#define __GAL_A11Y_E_CELL_VBOX_H__ + +#include "gal-a11y-e-cell.h" + +G_BEGIN_DECLS + +#define GAL_A11Y_TYPE_E_CELL_VBOX (gal_a11y_e_cell_vbox_get_type ()) +#define GAL_A11Y_E_CELL_VBOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_VBOX, GalA11yECellVbox)) +#define GAL_A11Y_E_CELL_VBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_E_CELL_VBOX, GalA11yECellVboxClass)) +#define GAL_A11Y_IS_E_CELL_VBOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_VBOX)) +#define GAL_A11Y_IS_E_CELL_VBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_VBOX)) +#define GAL_A11Y_E_CELL_VBOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAL_A11Y_TYPE_E_CELL_VBOX, GalA11yECellVboxClass)) + +typedef struct _GalA11yECellVbox GalA11yECellVbox; +typedef struct _GalA11yECellVboxClass GalA11yECellVboxClass; + +struct _GalA11yECellVbox +{ + GalA11yECell object; + gint a11y_subcell_count; + gpointer *a11y_subcells; +}; + +struct _GalA11yECellVboxClass +{ + GalA11yECellClass parent_class; +}; + +GType gal_a11y_e_cell_vbox_get_type (void); +AtkObject *gal_a11y_e_cell_vbox_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + gint model_col, + gint view_col, + gint row); + +G_END_DECLS +#endif /* __GAL_A11Y_E_CELL_VBOX_H__ */ diff --git a/widgets/table/gal-a11y-e-cell.c b/widgets/table/gal-a11y-e-cell.c new file mode 100644 index 0000000000..e09b5456d9 --- /dev/null +++ b/widgets/table/gal-a11y-e-cell.c @@ -0,0 +1,644 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Christopher James Lahey + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include + +#include + +#include + +#include "a11y/gal-a11y-util.h" +#include "table/e-table.h" +#include "table/e-tree.h" +#include + +#include "gal-a11y-e-cell.h" +#include "gal-a11y-e-cell-vbox.h" +#include "gal-a11y-e-table-item.h" + +#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yECellClass)) +static GObjectClass *parent_class; +#define PARENT_TYPE (atk_object_get_type ()) + + +#if 0 +static void +unref_item (gpointer user_data, GObject *obj_loc) +{ + GalA11yECell *a11y = GAL_A11Y_E_CELL (user_data); + a11y->item = NULL; + g_object_unref (a11y); +} + +static void +unref_cell (gpointer user_data, GObject *obj_loc) +{ + GalA11yECell *a11y = GAL_A11Y_E_CELL (user_data); + a11y->cell_view = NULL; + g_object_unref (a11y); +} +#endif + +static gboolean +is_valid (AtkObject *cell) +{ + GalA11yECell *a11y = GAL_A11Y_E_CELL (cell); + GalA11yETableItem *a11yItem = GAL_A11Y_E_TABLE_ITEM (a11y->parent); + AtkStateSet *item_ss; + gboolean ret = TRUE; + + item_ss = atk_object_ref_state_set (ATK_OBJECT (a11yItem)); + if (atk_state_set_contains_state (item_ss, ATK_STATE_DEFUNCT)) + ret = FALSE; + + g_object_unref (item_ss); + + if (ret && atk_state_set_contains_state (a11y->state_set, ATK_STATE_DEFUNCT)) + ret = FALSE; + + return ret; +} + +static void +gal_a11y_e_cell_dispose (GObject *object) +{ + GalA11yECell *a11y = GAL_A11Y_E_CELL (object); + +#if 0 + if (a11y->item) + g_object_unref (G_OBJECT (a11y->item)); /*, unref_item, a11y); */ + if (a11y->cell_view) + g_object_unref (G_OBJECT (a11y->cell_view)); /*, unref_cell, a11y); */ + if (a11y->parent) + g_object_unref (a11y->parent); +#endif + + if (a11y->state_set) { + g_object_unref (a11y->state_set); + a11y->state_set = NULL; + } + + if (parent_class->dispose) + parent_class->dispose (object); + +} + +/* Static functions */ +static G_CONST_RETURN gchar * +gal_a11y_e_cell_get_name (AtkObject * a11y) +{ + GalA11yECell *cell = GAL_A11Y_E_CELL (a11y); + ETableCol *ecol; + + if (a11y->name != NULL && strcmp (a11y->name, "")) + return a11y->name; + + if (cell->item != NULL) { + ecol = e_table_header_get_column (cell->item->header, cell->view_col); + if (ecol != NULL) + return ecol->text; + } + + return _("Table Cell"); +} + +static AtkStateSet * +gal_a11y_e_cell_ref_state_set (AtkObject *accessible) +{ + GalA11yECell *cell = GAL_A11Y_E_CELL (accessible); + + g_return_val_if_fail (cell->state_set, NULL); + + g_object_ref(cell->state_set); + + return cell->state_set; +} + +static AtkObject* +gal_a11y_e_cell_get_parent (AtkObject *accessible) +{ + GalA11yECell *a11y = GAL_A11Y_E_CELL (accessible); + return a11y->parent; +} + +static gint +gal_a11y_e_cell_get_index_in_parent (AtkObject *accessible) +{ + GalA11yECell *a11y = GAL_A11Y_E_CELL (accessible); + + if (!is_valid (accessible)) + return -1; + + return (a11y->row + 1) * a11y->item->cols + a11y->view_col; +} + + +/* Component IFace */ +static void +gal_a11y_e_cell_get_extents (AtkComponent *component, + gint *x, + gint *y, + gint *width, + gint *height, + AtkCoordType coord_type) +{ + GalA11yECell *a11y = GAL_A11Y_E_CELL (component); + GtkWidget *tableOrTree; + gint row; + gint col; + gint xval; + gint yval; + + row = a11y->row; + col = a11y->view_col; + + tableOrTree = gtk_widget_get_parent (GTK_WIDGET (a11y->item->parent.canvas)); + if (E_IS_TREE (tableOrTree)) { + e_tree_get_cell_geometry (E_TREE (tableOrTree), + row, col, &xval, &yval, + width, height); + } else { + e_table_get_cell_geometry (E_TABLE (tableOrTree), + row, col, &xval, &yval, + width, height); + } + + atk_component_get_position (ATK_COMPONENT (a11y->parent), + x, y, coord_type); + if (x && *x != G_MININT) + *x += xval; + if (y && *y != G_MININT) + *y += yval; +} + +static gboolean +gal_a11y_e_cell_grab_focus (AtkComponent *component) +{ + GalA11yECell *a11y; + gint index; + GtkWidget *toplevel; + GalA11yETableItem *a11yTableItem; + + a11y = GAL_A11Y_E_CELL (component); + + /* for e_cell_vbox's children, we just grab the e_cell_vbox */ + if (GAL_A11Y_IS_E_CELL_VBOX (a11y->parent)) { + return atk_component_grab_focus (ATK_COMPONENT (a11y->parent)); + } + + a11yTableItem = GAL_A11Y_E_TABLE_ITEM (a11y->parent); + index = atk_object_get_index_in_parent (ATK_OBJECT (a11y)); + + atk_selection_clear_selection (ATK_SELECTION (a11yTableItem)); + atk_selection_add_selection (ATK_SELECTION (a11yTableItem), index); + + gtk_widget_grab_focus (GTK_WIDGET (GNOME_CANVAS_ITEM (a11y->item)->canvas)); + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (GNOME_CANVAS_ITEM (a11y->item)->canvas)); + if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel)) + gtk_window_present (GTK_WINDOW (toplevel)); + + return TRUE; +} + +/* Table IFace */ + +static void +gal_a11y_e_cell_atk_component_iface_init (AtkComponentIface *iface) +{ + iface->get_extents = gal_a11y_e_cell_get_extents; + iface->grab_focus = gal_a11y_e_cell_grab_focus; +} + +static void +gal_a11y_e_cell_class_init (GalA11yECellClass *klass) +{ + AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + object_class->dispose = gal_a11y_e_cell_dispose; + + atk_object_class->get_parent = gal_a11y_e_cell_get_parent; + atk_object_class->get_index_in_parent = gal_a11y_e_cell_get_index_in_parent; + atk_object_class->ref_state_set = gal_a11y_e_cell_ref_state_set; + atk_object_class->get_name = gal_a11y_e_cell_get_name; +} + +static void +gal_a11y_e_cell_init (GalA11yECell *a11y) +{ + a11y->item = NULL; + a11y->cell_view = NULL; + a11y->parent = NULL; + a11y->model_col = -1; + a11y->view_col = -1; + a11y->row = -1; + + a11y->state_set = atk_state_set_new (); + atk_state_set_add_state (a11y->state_set, ATK_STATE_TRANSIENT); + atk_state_set_add_state (a11y->state_set, ATK_STATE_ENABLED); + atk_state_set_add_state (a11y->state_set, ATK_STATE_SENSITIVE); + atk_state_set_add_state (a11y->state_set, ATK_STATE_SELECTABLE); + atk_state_set_add_state (a11y->state_set, ATK_STATE_SHOWING); + atk_state_set_add_state (a11y->state_set, ATK_STATE_FOCUSABLE); + atk_state_set_add_state (a11y->state_set, ATK_STATE_VISIBLE); +} + + +static ActionInfo * +_gal_a11y_e_cell_get_action_info (GalA11yECell *cell, + gint index) +{ + GList *list_node; + + g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), NULL); + if (cell->action_list == NULL) + return NULL; + list_node = g_list_nth (cell->action_list, index); + if (!list_node) + return NULL; + return (ActionInfo *) (list_node->data); +} + +static void +_gal_a11y_e_cell_destroy_action_info (gpointer action_info, + gpointer user_data) +{ + ActionInfo *info = (ActionInfo *)action_info; + + g_return_if_fail (info != NULL); + g_free (info->name); + g_free (info->description); + g_free (info->keybinding); + g_free (info); +} + + +gboolean +gal_a11y_e_cell_add_action ( GalA11yECell * cell, + const gchar *action_name, + const gchar *action_description, + const gchar *action_keybinding, + ACTION_FUNC action_func) +{ + ActionInfo *info; + g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), FALSE); + info = g_new (ActionInfo, 1); + + if (action_name != NULL) + info->name = g_strdup (action_name); + else + info->name = NULL; + + if (action_description != NULL) + info->description = g_strdup (action_description); + else + info->description = NULL; + if (action_keybinding != NULL) + info->keybinding = g_strdup (action_keybinding); + else + info->keybinding = NULL; + info->do_action_func = action_func; + + cell->action_list = g_list_append (cell->action_list, (gpointer) info); + return TRUE; +} + +gboolean +gal_a11y_e_cell_remove_action (GalA11yECell *cell, + gint action_index) +{ + GList *list_node; + + g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), FALSE); + list_node = g_list_nth (cell->action_list, action_index); + if (!list_node) + return FALSE; + g_return_val_if_fail (list_node->data != NULL, FALSE); + _gal_a11y_e_cell_destroy_action_info (list_node->data, NULL); + cell->action_list = g_list_remove_link (cell->action_list, list_node); + + return TRUE; +} + +gboolean +gal_a11y_e_cell_remove_action_by_name (GalA11yECell *cell, + const gchar *action_name) +{ + GList *list_node; + gboolean action_found= FALSE; + + g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), FALSE); + for (list_node = cell->action_list; list_node && !action_found; + list_node = list_node->next) { + if (!g_ascii_strcasecmp (((ActionInfo *)(list_node->data))->name, action_name)) { + action_found = TRUE; + break; + } + } + + g_return_val_if_fail (action_found, FALSE); + _gal_a11y_e_cell_destroy_action_info (list_node->data, NULL); + cell->action_list = g_list_remove_link (cell->action_list, list_node); + + return TRUE; +} + +static gint +gal_a11y_e_cell_action_get_n_actions (AtkAction *action) +{ + GalA11yECell *cell = GAL_A11Y_E_CELL(action); + if (cell->action_list != NULL) + return g_list_length (cell->action_list); + else + return 0; +} + +static G_CONST_RETURN gchar * +gal_a11y_e_cell_action_get_name (AtkAction *action, + gint index) +{ + GalA11yECell *cell = GAL_A11Y_E_CELL(action); + ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); + + if (info == NULL) + return NULL; + return info->name; +} + +static G_CONST_RETURN gchar * +gal_a11y_e_cell_action_get_description (AtkAction *action, + gint index) +{ + GalA11yECell *cell = GAL_A11Y_E_CELL(action); + ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); + + if (info == NULL) + return NULL; + return info->description; +} + +static gboolean +gal_a11y_e_cell_action_set_description (AtkAction *action, + gint index, + const gchar *desc) +{ + GalA11yECell *cell = GAL_A11Y_E_CELL(action); + ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); + + if (info == NULL) + return FALSE; + g_free (info->description); + info->description = g_strdup (desc); + return TRUE; +} + +static G_CONST_RETURN gchar * +gal_a11y_e_cell_action_get_keybinding (AtkAction *action, + gint index) +{ + GalA11yECell *cell = GAL_A11Y_E_CELL(action); + ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); + if (info == NULL) + return NULL; + + return info->keybinding; +} + +static gboolean +idle_do_action (gpointer data) +{ + GalA11yECell *cell; + + cell = GAL_A11Y_E_CELL (data); + + if (!is_valid (ATK_OBJECT (cell))) + return FALSE; + + cell->action_idle_handler = 0; + cell->action_func (cell); + g_object_unref (cell); + + return FALSE; +} + +static gboolean +gal_a11y_e_cell_action_do_action (AtkAction *action, + gint index) +{ + GalA11yECell *cell = GAL_A11Y_E_CELL(action); + ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); + + if (!is_valid (ATK_OBJECT (action))) + return FALSE; + + if (info == NULL) + return FALSE; + g_return_val_if_fail (info->do_action_func, FALSE); + if (cell->action_idle_handler) + return FALSE; + cell->action_func = info->do_action_func; + g_object_ref (cell); + cell->action_idle_handler = g_idle_add (idle_do_action, cell); + + return TRUE; +} + +static void +gal_a11y_e_cell_atk_action_interface_init (AtkActionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->get_n_actions = gal_a11y_e_cell_action_get_n_actions; + iface->do_action = gal_a11y_e_cell_action_do_action; + iface->get_name = gal_a11y_e_cell_action_get_name; + iface->get_description = gal_a11y_e_cell_action_get_description; + iface->set_description = gal_a11y_e_cell_action_set_description; + iface->get_keybinding = gal_a11y_e_cell_action_get_keybinding; +} + +void +gal_a11y_e_cell_type_add_action_interface (GType type) +{ + static const GInterfaceInfo atk_action_info = + { + (GInterfaceInitFunc) gal_a11y_e_cell_atk_action_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + g_type_add_interface_static (type, ATK_TYPE_ACTION, + &atk_action_info); +} + +gboolean +gal_a11y_e_cell_add_state (GalA11yECell *cell, + AtkStateType state_type, + gboolean emit_signal) +{ + if (!atk_state_set_contains_state (cell->state_set, state_type)) { + gboolean rc; + + rc = atk_state_set_add_state (cell->state_set, state_type); + /* + * The signal should only be generated if the value changed, + * not when the cell is set up. So states that are set + * initially should pass FALSE as the emit_signal argument. + */ + + if (emit_signal) { + atk_object_notify_state_change (ATK_OBJECT (cell), state_type, TRUE); + /* If state_type is ATK_STATE_VISIBLE, additional + notification */ + if (state_type == ATK_STATE_VISIBLE) + g_signal_emit_by_name (cell, "visible_data_changed"); + } + + return rc; + } + else + return FALSE; +} + +gboolean +gal_a11y_e_cell_remove_state (GalA11yECell *cell, + AtkStateType state_type, + gboolean emit_signal) +{ + if (atk_state_set_contains_state (cell->state_set, state_type)) { + gboolean rc; + + rc = atk_state_set_remove_state (cell->state_set, state_type); + /* + * The signal should only be generated if the value changed, + * not when the cell is set up. So states that are set + * initially should pass FALSE as the emit_signal argument. + */ + + if (emit_signal) { + atk_object_notify_state_change (ATK_OBJECT (cell), state_type, FALSE); + /* If state_type is ATK_STATE_VISIBLE, additional notification */ + if (state_type == ATK_STATE_VISIBLE) + g_signal_emit_by_name (cell, "visible_data_changed"); + } + + return rc; + } + else + return FALSE; +} + +/** + * gal_a11y_e_cell_get_type: + * @void: + * + * Registers the &GalA11yECell class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yECell class. + **/ +GType +gal_a11y_e_cell_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yECellClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gal_a11y_e_cell_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yECell), + 0, + (GInstanceInitFunc) gal_a11y_e_cell_init, + NULL /* value_cell */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) gal_a11y_e_cell_atk_component_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yECell", &info, 0); + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); + } + + return type; +} + +AtkObject * +gal_a11y_e_cell_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + gint model_col, + gint view_col, + gint row) +{ + AtkObject *a11y; + + a11y = g_object_new (gal_a11y_e_cell_get_type (), NULL); + + gal_a11y_e_cell_construct (a11y, + item, + cell_view, + parent, + model_col, + view_col, + row); + return a11y; +} + +void +gal_a11y_e_cell_construct (AtkObject *object, + ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + gint model_col, + gint view_col, + gint row) +{ + GalA11yECell *a11y = GAL_A11Y_E_CELL (object); + a11y->item = item; + a11y->cell_view = cell_view; + a11y->parent = parent; + a11y->model_col = model_col; + a11y->view_col = view_col; + a11y->row = row; + ATK_OBJECT (a11y) ->role = ATK_ROLE_TABLE_CELL; + + if (item) + g_object_ref (G_OBJECT (item)); + +#if 0 + if (parent) + g_object_ref (parent); + + if (cell_view) + g_object_ref (G_OBJECT (cell_view)); + + +#endif +} diff --git a/widgets/table/gal-a11y-e-cell.h b/widgets/table/gal-a11y-e-cell.h new file mode 100644 index 0000000000..c61e5e2d22 --- /dev/null +++ b/widgets/table/gal-a11y-e-cell.h @@ -0,0 +1,113 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Christopher James Lahey + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_CELL_H__ +#define __GAL_A11Y_E_CELL_H__ + +#include +#include
+#include
+ +#define GAL_A11Y_TYPE_E_CELL (gal_a11y_e_cell_get_type ()) +#define GAL_A11Y_E_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL, GalA11yECell)) +#define GAL_A11Y_E_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL, GalA11yECellClass)) +#define GAL_A11Y_IS_E_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL)) +#define GAL_A11Y_IS_E_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL)) + +typedef struct _GalA11yECell GalA11yECell; +typedef struct _GalA11yECellClass GalA11yECellClass; +typedef struct _GalA11yECellPrivate GalA11yECellPrivate; +typedef struct _ActionInfo ActionInfo; +typedef void (*ACTION_FUNC) (GalA11yECell *cell); + + +/* This struct should actually be larger as this isn't what we derive from. + * The GalA11yECellPrivate comes right after the parent class structure. + **/ +struct _GalA11yECell { + AtkObject object; + + ETableItem *item; + ECellView *cell_view; + AtkObject *parent; + gint model_col; + gint view_col; + gint row; + AtkStateSet *state_set; + GList *action_list; + gint action_idle_handler; + ACTION_FUNC action_func; +}; + +struct _GalA11yECellClass { + AtkObjectClass parent_class; +}; + +struct _ActionInfo { + gchar *name; + gchar *description; + gchar *keybinding; + ACTION_FUNC do_action_func; +}; + + + +/* Standard Glib function */ +GType gal_a11y_e_cell_get_type (void); +AtkObject *gal_a11y_e_cell_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + gint model_col, + gint view_col, + gint row); +void gal_a11y_e_cell_construct (AtkObject *object, + ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + gint model_col, + gint view_col, + gint row); + +void gal_a11y_e_cell_type_add_action_interface (GType type); + +gboolean gal_a11y_e_cell_add_action (GalA11yECell *cell, + const gchar *action_name, + const gchar *action_description, + const gchar *action_keybinding, + ACTION_FUNC action_func); + +gboolean gal_a11y_e_cell_remove_action (GalA11yECell *cell, + gint action_id); + +gboolean gal_a11y_e_cell_remove_action_by_name (GalA11yECell *cell, + const gchar *action_name); + +gboolean gal_a11y_e_cell_add_state (GalA11yECell *cell, + AtkStateType state_type, + gboolean emit_signal); + +gboolean gal_a11y_e_cell_remove_state (GalA11yECell *cell, + AtkStateType state_type, + gboolean emit_signal); + + +#endif /* ! __GAL_A11Y_E_CELL_H__ */ diff --git a/widgets/table/gal-a11y-e-table-click-to-add-factory.c b/widgets/table/gal-a11y-e-table-click-to-add-factory.c new file mode 100644 index 0000000000..0ebb3c4621 --- /dev/null +++ b/widgets/table/gal-a11y-e-table-click-to-add-factory.c @@ -0,0 +1,106 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Yuedong Du + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include + +#include + +#include "table/e-table.h" +#include "table/e-table-click-to-add.h" + +#include "gal-a11y-e-table.h" +#include "gal-a11y-e-table-click-to-add.h" +#include "gal-a11y-e-table-click-to-add-factory.h" + +#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETableClickToAddFactoryClass)) +static AtkObjectFactoryClass *parent_class; +#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY) + +/* Static functions */ + +static GType +gal_a11y_e_table_click_to_add_factory_get_accessible_type (void) +{ + return GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD; +} + +static AtkObject* +gal_a11y_e_table_click_to_add_factory_create_accessible (GObject *obj) +{ + AtkObject * atk_object; + + g_return_val_if_fail (E_IS_TABLE_CLICK_TO_ADD(obj), NULL); + + atk_object = gal_a11y_e_table_click_to_add_new (obj); + + return atk_object; +} + +static void +gal_a11y_e_table_click_to_add_factory_class_init (GalA11yETableClickToAddFactoryClass *klass) +{ + AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + factory_class->create_accessible = gal_a11y_e_table_click_to_add_factory_create_accessible; + factory_class->get_accessible_type = gal_a11y_e_table_click_to_add_factory_get_accessible_type; +} + +static void +gal_a11y_e_table_click_to_add_factory_init (GalA11yETableClickToAddFactory *factory) +{ +} + +/** + * gal_a11y_e_table_factory_get_type: + * @void: + * + * Registers the &GalA11yETableFactory class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yETableFactory class. + **/ +GType +gal_a11y_e_table_click_to_add_factory_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yETableClickToAddFactoryClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gal_a11y_e_table_click_to_add_factory_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yETableClickToAddFactory), + 0, + (GInstanceInitFunc) gal_a11y_e_table_click_to_add_factory_init, + NULL /* value_table */ + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yETableClickToAddFactory", &info, 0); + } + + return type; +} diff --git a/widgets/table/gal-a11y-e-table-click-to-add-factory.h b/widgets/table/gal-a11y-e-table-click-to-add-factory.h new file mode 100644 index 0000000000..9f249f0178 --- /dev/null +++ b/widgets/table/gal-a11y-e-table-click-to-add-factory.h @@ -0,0 +1,50 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Yuedong Du + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TABLE_CLICK_TO_ADD_FACTORY_H__ +#define __GAL_A11Y_E_TABLE_CLICK_TO_ADD_FACTORY_H__ + +#include +#include + +#define GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY (gal_a11y_e_table_item_factory_get_type ()) +#define GAL_A11Y_E_TABLE_CLICK_TO_ADD_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY, GalA11yETableClickToAddFactory)) +#define GAL_A11Y_E_TABLE_CLICK_TO_ADD_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY, GalA11yETableClickToAddFactoryClass)) +#define GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY)) +#define GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY)) + +typedef struct _GalA11yETableClickToAddFactory GalA11yETableClickToAddFactory; +typedef struct _GalA11yETableClickToAddFactoryClass GalA11yETableClickToAddFactoryClass; + +struct _GalA11yETableClickToAddFactory { + AtkObject object; +}; + +struct _GalA11yETableClickToAddFactoryClass { + AtkObjectClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_table_click_to_add_factory_get_type (void); + +#endif diff --git a/widgets/table/gal-a11y-e-table-click-to-add.c b/widgets/table/gal-a11y-e-table-click-to-add.c new file mode 100644 index 0000000000..8a8fe56796 --- /dev/null +++ b/widgets/table/gal-a11y-e-table-click-to-add.c @@ -0,0 +1,344 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Yuedong Du + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include + +#include + +#include "a11y/gal-a11y-util.h" +#include "table/e-table-click-to-add.h" +#include "table/e-table-group.h" +#include "table/e-table-group-leaf.h" +#include + +#include "gal-a11y-e-table-click-to-add.h" +#include "gal-a11y-e-table-click-to-add-factory.h" + +static AtkObjectClass *parent_class; +static GType parent_type; +static gint priv_offset; +#define GET_PRIVATE(object) ((GalA11yETableClickToAddPrivate *) (((gchar *) object) + priv_offset)) +#define PARENT_TYPE (parent_type) + +struct _GalA11yETableClickToAddPrivate { + gpointer rect; + gpointer row; +}; + + +static gint +etcta_get_n_actions (AtkAction *action) +{ + return 1; +} + +static G_CONST_RETURN gchar * +etcta_get_description (AtkAction *action, + gint i) +{ + if (i == 0) + return _("click to add"); + + return NULL; +} + +static G_CONST_RETURN gchar * +etcta_action_get_name (AtkAction *action, gint i) +{ + if (i == 0) + return _("click"); + + return NULL; +} + + +static gboolean +idle_do_action (gpointer data) +{ + GdkEventButton event; + ETableClickToAdd * etcta; + gint finished; + + g_return_val_if_fail ( data!= NULL, FALSE); + + etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (data))); + g_return_val_if_fail (etcta, FALSE); + + event.x = 0; + event.y = 0; + + event.type = GDK_BUTTON_PRESS; + event.window = GTK_LAYOUT(GNOME_CANVAS_ITEM(etcta)->canvas)->bin_window; + event.button = 1; + event.send_event = TRUE; + event.time = GDK_CURRENT_TIME; + event.axes = NULL; + + g_signal_emit_by_name (etcta, "event", &event, &finished); + + return FALSE; +} + +static gboolean +etcta_do_action (AtkAction * action, gint i) +{ + g_return_val_if_fail (i == 0, FALSE); + + g_idle_add (idle_do_action, action); + + return TRUE; +} + +static void +atk_action_interface_init (AtkActionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->do_action = etcta_do_action; + iface->get_n_actions = etcta_get_n_actions; + iface->get_description = etcta_get_description; + iface->get_name = etcta_action_get_name; +} + + +static G_CONST_RETURN gchar * +etcta_get_name (AtkObject *obj) +{ + ETableClickToAdd * etcta; + + g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD (obj), NULL); + + etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(obj))); + if (etcta && etcta->message != NULL) + return etcta->message; + + return _("click to add"); +} + +static gint +etcta_get_n_children (AtkObject *accessible) +{ + return 1; +} + +static AtkObject* +etcta_ref_child (AtkObject *accessible, + gint i) +{ + AtkObject * atk_obj = NULL; + ETableClickToAdd * etcta; + + if ( i != 0 ) + return NULL; + + etcta = E_TABLE_CLICK_TO_ADD(atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible))); + + g_return_val_if_fail (etcta, NULL); + + if (etcta->rect) { + atk_obj = atk_gobject_accessible_for_object (G_OBJECT(etcta->rect)); + } else if (etcta->row) { + atk_obj = atk_gobject_accessible_for_object (G_OBJECT(etcta->row)); + } + + g_object_ref (atk_obj); + + return atk_obj; +} + +static AtkStateSet * +etcta_ref_state_set (AtkObject *accessible) +{ + AtkStateSet * state_set = NULL; + + state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (accessible); + if (state_set != NULL) { + atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE); + atk_state_set_add_state (state_set, ATK_STATE_SHOWING); + } + + return state_set; +} + +static void +etcta_class_init (GalA11yETableClickToAddClass *klass) +{ + AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + atk_object_class->get_name = etcta_get_name; + atk_object_class->get_n_children = etcta_get_n_children; + atk_object_class->ref_child = etcta_ref_child; + atk_object_class->ref_state_set = etcta_ref_state_set; +} + +static void +etcta_init (GalA11yETableClickToAdd *a11y) +{ +} + +/** + * gal_a11y_e_table_click_to_add_get_type: + * @void: + * + * Registers the &GalA11yETableClickToAdd class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yETableClickToAdd class. + **/ +GType +gal_a11y_e_table_click_to_add_get_type (void) +{ + static GType type = 0; + + if (!type) { + AtkObjectFactory *factory; + + GTypeInfo info = { + sizeof (GalA11yETableClickToAddClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) etcta_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yETableClickToAdd), + 0, + (GInstanceInitFunc) etcta_init, + NULL /* value_table */ + }; + + static const GInterfaceInfo atk_action_info = { + (GInterfaceInitFunc) atk_action_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + factory = atk_registry_get_factory (atk_get_default_registry (), GNOME_TYPE_CANVAS_ITEM); + + parent_type = atk_object_factory_get_accessible_type (factory); + type = gal_a11y_type_register_static_with_private (PARENT_TYPE, + "GalA11yETableClickToAdd", &info, 0, + sizeof(GalA11yETableClickToAddPrivate), &priv_offset); + + g_type_add_interface_static (type, ATK_TYPE_ACTION, &atk_action_info); + + } + + return type; +} + +static gboolean +etcta_event (GnomeCanvasItem *item, GdkEvent *e, gpointer data) +{ + ETableClickToAdd *etcta = E_TABLE_CLICK_TO_ADD (item); + GalA11yETableClickToAdd *a11y; + GalA11yETableClickToAddPrivate *priv; + + g_return_val_if_fail (item, TRUE); + + g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD(data), FALSE); + a11y = GAL_A11Y_E_TABLE_CLICK_TO_ADD (data); + + priv = GET_PRIVATE (a11y); + + /* rect replaced by row. */ + if (etcta->rect == NULL && priv->rect != NULL) { + g_signal_emit_by_name (a11y, "children_changed::remove", 0, NULL, NULL); + + } + /* row inserted, and/or replaced by a new row. */ + if (etcta->row != NULL && priv->row == NULL) { + g_signal_emit_by_name (a11y, "children_changed::add", 0, NULL, NULL); + } else if (etcta->row != NULL && priv->row != NULL && etcta->row != priv->row) { + g_signal_emit_by_name (a11y, "children_changed::remove", 0, NULL, NULL); + g_signal_emit_by_name (a11y, "children_changed::add", 0, NULL, NULL); + } + + + priv->rect = etcta->rect; + priv->row = etcta->row; + + return FALSE; +} + +static void +etcta_selection_cursor_changed (ESelectionModel *esm, gint row, gint col, + GalA11yETableClickToAdd *a11y) +{ + ETableClickToAdd *etcta; + AtkObject *row_a11y; + + etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(a11y))); + + if (etcta == NULL || etcta->row == NULL) + return; + + row_a11y = atk_gobject_accessible_for_object (G_OBJECT(etcta->row)); + if (row_a11y) { + AtkObject *cell_a11y = g_object_get_data (G_OBJECT(row_a11y), "gail-focus-object"); + if (cell_a11y) { + atk_focus_tracker_notify (cell_a11y); + } + } +} + +AtkObject * +gal_a11y_e_table_click_to_add_new (GObject *widget) +{ + GalA11yETableClickToAdd *a11y; + ETableClickToAdd * etcta; + GalA11yETableClickToAddPrivate *priv; + + g_return_val_if_fail (widget != NULL, NULL); + + a11y = g_object_new (gal_a11y_e_table_click_to_add_get_type (), NULL); + priv = GET_PRIVATE (a11y); + + etcta = E_TABLE_CLICK_TO_ADD(widget); + + + atk_object_initialize (ATK_OBJECT (a11y), etcta); + + priv->rect = etcta->rect; + priv->row = etcta->row; + + + g_signal_connect_after (G_OBJECT(widget), "event", + G_CALLBACK (etcta_event), a11y); + + g_signal_connect (etcta->selection, "cursor_changed", + G_CALLBACK (etcta_selection_cursor_changed), a11y); + + return ATK_OBJECT (a11y); +} + +void +gal_a11y_e_table_click_to_add_init (void) +{ + if (atk_get_root ()) + atk_registry_set_factory_type (atk_get_default_registry (), + E_TABLE_CLICK_TO_ADD_TYPE, + gal_a11y_e_table_click_to_add_factory_get_type ()); + +} + diff --git a/widgets/table/gal-a11y-e-table-click-to-add.h b/widgets/table/gal-a11y-e-table-click-to-add.h new file mode 100644 index 0000000000..17d6940d08 --- /dev/null +++ b/widgets/table/gal-a11y-e-table-click-to-add.h @@ -0,0 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TABLE_CLICK_TO_ADD_H__ +#define __GAL_A11Y_E_TABLE_CLICK_TO_ADD_H__ + +#include +#include
+#include + +#define GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD (gal_a11y_e_table_click_to_add_get_type ()) +#define GAL_A11Y_E_TABLE_CLICK_TO_ADD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD, GalA11yETableClickToAdd)) +#define GAL_A11Y_E_TABLE_CLICK_TO_ADD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD, GalA11yETableClickToAddClass)) +#define GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD)) +#define GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD)) + +typedef struct _GalA11yETableClickToAdd GalA11yETableClickToAdd; +typedef struct _GalA11yETableClickToAddClass GalA11yETableClickToAddClass; +typedef struct _GalA11yETableClickToAddPrivate GalA11yETableClickToAddPrivate; + +/* This struct should actually be larger as this isn't what we derive from. + * The GalA11yETableClickToAddPrivate comes right after the parent class structure. + **/ +struct _GalA11yETableClickToAdd { + AtkGObjectAccessible parent; +}; + +struct _GalA11yETableClickToAddClass { + AtkGObjectAccessibleClass parent_class; +}; + +/* Standard Glib function */ +GType gal_a11y_e_table_click_to_add_get_type (void); +AtkObject *gal_a11y_e_table_click_to_add_new (GObject *widget); + +void gal_a11y_e_table_click_to_add_init (void); +#endif /* ! __GAL_A11Y_E_TABLE_CLICK_TO_ADD_H__ */ diff --git a/widgets/table/gal-a11y-e-table-column-header.c b/widgets/table/gal-a11y-e-table-column-header.c new file mode 100644 index 0000000000..41e6ab0fca --- /dev/null +++ b/widgets/table/gal-a11y-e-table-column-header.c @@ -0,0 +1,229 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Li Yuan + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include +#include +#include +#include +#include "table/e-table-header-item.h" +#include "a11y/gal-a11y-util.h" +#include "gal-a11y-e-table-column-header.h" + +static GObjectClass *parent_class; +static gint priv_offset; + +#define GET_PRIVATE(object) ((GalA11yETableColumnHeaderPrivate *) (((gchar *) object) + priv_offset)) +#define PARENT_TYPE (atk_gobject_accessible_get_type ()) + +struct _GalA11yETableColumnHeaderPrivate { + ETableItem *item; + AtkObject *parent; + AtkStateSet *state_set; +}; + +static void +etch_init (GalA11yETableColumnHeader *a11y) +{ + GET_PRIVATE (a11y)->item = NULL; + GET_PRIVATE (a11y)->parent = NULL; + GET_PRIVATE (a11y)->state_set = NULL; +} + +static AtkStateSet * +gal_a11y_e_table_column_header_ref_state_set (AtkObject *accessible) +{ + GalA11yETableColumnHeaderPrivate *priv = GET_PRIVATE (accessible); + + g_return_val_if_fail (priv->state_set, NULL); + + g_object_ref(priv->state_set); + + return priv->state_set; +} + +static void +gal_a11y_e_table_column_header_real_initialize (AtkObject *obj, gpointer data) +{ + ATK_OBJECT_CLASS (parent_class)->initialize (obj, data); +} + +static void +gal_a11y_e_table_column_header_dispose (GObject *object) +{ + GalA11yETableColumnHeader *a11y = GAL_A11Y_E_TABLE_COLUMN_HEADER (object); + GalA11yETableColumnHeaderPrivate *priv = GET_PRIVATE (a11y); + + if (priv->state_set) { + g_object_unref (priv->state_set); + priv->state_set = NULL; + } + + if (parent_class->dispose) + parent_class->dispose (object); + +} + +static void +etch_class_init (GalA11yETableColumnHeaderClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + object_class->dispose = gal_a11y_e_table_column_header_dispose; + + class->ref_state_set = gal_a11y_e_table_column_header_ref_state_set; + class->initialize = gal_a11y_e_table_column_header_real_initialize; +} + +inline static GObject * +etch_a11y_get_gobject (AtkGObjectAccessible *accessible) +{ + return atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible)); +} + +static gboolean +gal_a11y_e_table_column_header_do_action (AtkAction *action, + gint i) +{ + gboolean return_value = TRUE; + GtkWidget *widget; + GalA11yETableColumnHeader *a11y; + ETableHeaderItem *ethi; + ETableItem *item; + ETableCol *col; + + switch (i) { + case 0: + a11y = GAL_A11Y_E_TABLE_COLUMN_HEADER (action); + col = E_TABLE_COL (etch_a11y_get_gobject (ATK_GOBJECT_ACCESSIBLE (a11y))); + item = GET_PRIVATE (a11y)->item; + widget = gtk_widget_get_parent (GTK_WIDGET (item->parent.canvas)); + if (E_IS_TREE (widget)) { + ethi = E_TABLE_HEADER_ITEM (e_tree_get_header_item (E_TREE (widget))); + } + else if (E_IS_TABLE (widget)) + ethi = E_TABLE_HEADER_ITEM (E_TABLE (widget)->header_item); + else + break; + ethi_change_sort_state (ethi, col); + default: + return_value = FALSE; + break; + } + return return_value; +} + +static gint +gal_a11y_e_table_column_header_get_n_actions (AtkAction *action) +{ + return 1; +} + +static G_CONST_RETURN gchar * +gal_a11y_e_table_column_header_action_get_name (AtkAction *action, + gint i) +{ + G_CONST_RETURN gchar *return_value; + + switch (i) { + case 0: + return_value = _("sort"); + break; + default: + return_value = NULL; + break; + } + return return_value; +} + +static void +atk_action_interface_init (AtkActionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->do_action = gal_a11y_e_table_column_header_do_action; + iface->get_n_actions = gal_a11y_e_table_column_header_get_n_actions; + iface->get_name = gal_a11y_e_table_column_header_action_get_name; +} + +GType +gal_a11y_e_table_column_header_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yETableColumnHeaderClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) etch_class_init, + (GClassFinalizeFunc) NULL, + NULL, + sizeof (GalA11yETableColumnHeader), + 0, + (GInstanceInitFunc) etch_init, + NULL + }; + static const GInterfaceInfo atk_action_info = { + (GInterfaceInitFunc) atk_action_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yETableColumnHeader", &info, 0, + sizeof (GalA11yETableColumnHeaderPrivate), &priv_offset); + + g_type_add_interface_static (type, ATK_TYPE_ACTION, &atk_action_info); + } + + return type; +} + +AtkObject * +gal_a11y_e_table_column_header_new (ETableCol *ecol, ETableItem *item) +{ + GalA11yETableColumnHeader *a11y; + AtkObject *accessible; + + g_return_val_if_fail (E_IS_TABLE_COL (ecol), NULL); + + a11y = g_object_new (gal_a11y_e_table_column_header_get_type(), NULL); + accessible = ATK_OBJECT (a11y); + atk_object_initialize (accessible, ecol); + + GET_PRIVATE (a11y)->item = item; + GET_PRIVATE (a11y)->state_set = atk_state_set_new (); + + atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_VISIBLE); + atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_SHOWING); + atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_SENSITIVE); + atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_ENABLED); + + if (ecol->text) + atk_object_set_name (accessible, ecol->text); + atk_object_set_role (accessible, ATK_ROLE_TABLE_COLUMN_HEADER); + + return ATK_OBJECT (a11y); +} diff --git a/widgets/table/gal-a11y-e-table-column-header.h b/widgets/table/gal-a11y-e-table-column-header.h new file mode 100644 index 0000000000..d0b1ff5aeb --- /dev/null +++ b/widgets/table/gal-a11y-e-table-column-header.h @@ -0,0 +1,55 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Li Yuan + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + + +#ifndef __GAL_A11Y_E_TABLE_COLUMN_HEADER_H__ +#define __GAL_A11Y_E_TABLE_COLUMN_HEADER_H__ + +#include +#include + +#define GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER (gal_a11y_e_table_column_header_get_type ()) +#define GAL_A11Y_E_TABLE_COLUMN_HEADER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER, GalA11yETableColumnHeader)) +#define GAL_A11Y_E_TABLE_COLUMN_HEADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER, GalA11yETableColumnHeaderClass)) +#define GAL_A11Y_IS_E_TABLE_COLUMN_HEADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER)) +#define GAL_A11Y_IS_E_TABLE_COLUMN_HEADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER)) + +typedef struct _GalA11yETableColumnHeader GalA11yETableColumnHeader; +typedef struct _GalA11yETableColumnHeaderClass GalA11yETableColumnHeaderClass; +typedef struct _GalA11yETableColumnHeaderPrivate GalA11yETableColumnHeaderPrivate; + +struct _GalA11yETableColumnHeader { + AtkGObjectAccessible parent; +}; + +struct _GalA11yETableColumnHeaderClass { + AtkGObjectAccessibleClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_table_column_header_get_type (void); +AtkObject *gal_a11y_e_table_column_header_new (ETableCol *etc, ETableItem *item); +void gal_a11y_e_table_column_header_init (void); + +#endif /* ! __GAL_A11Y_E_TABLE_COLUMN_HEADER_H__ */ diff --git a/widgets/table/gal-a11y-e-table-factory.c b/widgets/table/gal-a11y-e-table-factory.c new file mode 100644 index 0000000000..f459f3b67c --- /dev/null +++ b/widgets/table/gal-a11y-e-table-factory.c @@ -0,0 +1,99 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Christopher James Lahey + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include + +#include "gal-a11y-e-table.h" +#include "gal-a11y-e-table-factory.h" + +#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETableFactoryClass)) +static AtkObjectFactoryClass *parent_class; +#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY) + +/* Static functions */ + +static GType +gal_a11y_e_table_factory_get_accessible_type (void) +{ + return GAL_A11Y_TYPE_E_TABLE; +} + +static AtkObject* +gal_a11y_e_table_factory_create_accessible (GObject *obj) +{ + AtkObject *accessible; + + accessible = gal_a11y_e_table_new (obj); + + return accessible; +} + +static void +gal_a11y_e_table_factory_class_init (GalA11yETableFactoryClass *klass) +{ + AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + factory_class->create_accessible = gal_a11y_e_table_factory_create_accessible; + factory_class->get_accessible_type = gal_a11y_e_table_factory_get_accessible_type; +} + +static void +gal_a11y_e_table_factory_init (GalA11yETableFactory *factory) +{ +} + +/** + * gal_a11y_e_table_factory_get_type: + * @void: + * + * Registers the &GalA11yETableFactory class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yETableFactory class. + **/ +GType +gal_a11y_e_table_factory_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yETableFactoryClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gal_a11y_e_table_factory_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yETableFactory), + 0, + (GInstanceInitFunc) gal_a11y_e_table_factory_init, + NULL /* value_table */ + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yETableFactory", &info, 0); + } + + return type; +} diff --git a/widgets/table/gal-a11y-e-table-factory.h b/widgets/table/gal-a11y-e-table-factory.h new file mode 100644 index 0000000000..3439cf0bdc --- /dev/null +++ b/widgets/table/gal-a11y-e-table-factory.h @@ -0,0 +1,51 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Christopher James Lahey + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TABLE_FACTORY_H__ +#define __GAL_A11Y_E_TABLE_FACTORY_H__ + +#include +#include + +#define GAL_A11Y_TYPE_E_TABLE_FACTORY (gal_a11y_e_table_factory_get_type ()) +#define GAL_A11Y_E_TABLE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_FACTORY, GalA11yETableFactory)) +#define GAL_A11Y_E_TABLE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_FACTORY, GalA11yETableFactoryClass)) +#define GAL_A11Y_IS_E_TABLE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_FACTORY)) +#define GAL_A11Y_IS_E_TABLE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_FACTORY)) + +typedef struct _GalA11yETableFactory GalA11yETableFactory; +typedef struct _GalA11yETableFactoryClass GalA11yETableFactoryClass; + +struct _GalA11yETableFactory { + AtkObject object; +}; + +struct _GalA11yETableFactoryClass { + AtkObjectClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_table_factory_get_type (void); + +#endif /* ! __GAL_A11Y_E_TABLE_FACTORY_H__ */ diff --git a/widgets/table/gal-a11y-e-table-item-factory.c b/widgets/table/gal-a11y-e-table-item-factory.c new file mode 100644 index 0000000000..fa14652788 --- /dev/null +++ b/widgets/table/gal-a11y-e-table-item-factory.c @@ -0,0 +1,105 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Yuedong Du + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include + +#include + +#include "table/e-table.h" +#include "table/e-tree.h" + +#include "gal-a11y-e-table.h" +#include "gal-a11y-e-table-item.h" +#include "gal-a11y-e-table-item-factory.h" + +#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETableItemFactoryClass)) +static AtkObjectFactoryClass *parent_class; +#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY) + +/* Static functions */ + +static GType +gal_a11y_e_table_item_factory_get_accessible_type (void) +{ + return GAL_A11Y_TYPE_E_TABLE_ITEM; +} + +static AtkObject* +gal_a11y_e_table_item_factory_create_accessible (GObject *obj) +{ + AtkObject *accessible; + + g_return_val_if_fail (E_IS_TABLE_ITEM(obj), NULL); + accessible = gal_a11y_e_table_item_new (E_TABLE_ITEM (obj)); + + return accessible; +} + +static void +gal_a11y_e_table_item_factory_class_init (GalA11yETableItemFactoryClass *klass) +{ + AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + factory_class->create_accessible = gal_a11y_e_table_item_factory_create_accessible; + factory_class->get_accessible_type = gal_a11y_e_table_item_factory_get_accessible_type; +} + +static void +gal_a11y_e_table_item_factory_init (GalA11yETableItemFactory *factory) +{ +} + +/** + * gal_a11y_e_table_factory_get_type: + * @void: + * + * Registers the &GalA11yETableFactory class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yETableFactory class. + **/ +GType +gal_a11y_e_table_item_factory_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yETableItemFactoryClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gal_a11y_e_table_item_factory_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yETableItemFactory), + 0, + (GInstanceInitFunc) gal_a11y_e_table_item_factory_init, + NULL /* value_table */ + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yETableItemFactory", &info, 0); + } + + return type; +} diff --git a/widgets/table/gal-a11y-e-table-item-factory.h b/widgets/table/gal-a11y-e-table-item-factory.h new file mode 100644 index 0000000000..f27c491a4d --- /dev/null +++ b/widgets/table/gal-a11y-e-table-item-factory.h @@ -0,0 +1,50 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Yuedong Du + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TABLE_ITEM_FACTORY_H__ +#define __GAL_A11Y_E_TABLE_ITEM_FACTORY_H__ + +#include +#include + +#define GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY (gal_a11y_e_table_item_factory_get_type ()) +#define GAL_A11Y_E_TABLE_ITEM_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY, GalA11yETableItemFactory)) +#define GAL_A11Y_E_TABLE_ITEM_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY, GalA11yETableItemFactoryClass)) +#define GAL_A11Y_IS_E_TABLE_ITEM_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY)) +#define GAL_A11Y_IS_E_TABLE_ITEM_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY)) + +typedef struct _GalA11yETableItemFactory GalA11yETableItemFactory; +typedef struct _GalA11yETableItemFactoryClass GalA11yETableItemFactoryClass; + +struct _GalA11yETableItemFactory { + AtkObject object; +}; + +struct _GalA11yETableItemFactoryClass { + AtkObjectClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_table_item_factory_get_type (void); + +#endif /* ! __GAL_A11Y_E_TABLE_FACTORY_H__ */ diff --git a/widgets/table/gal-a11y-e-table-item.c b/widgets/table/gal-a11y-e-table-item.c new file mode 100644 index 0000000000..561b9a84d6 --- /dev/null +++ b/widgets/table/gal-a11y-e-table-item.c @@ -0,0 +1,1327 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Christopher James Lahey + * Bolian Yin + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include + +#include + +#include + +#include "a11y/gal-a11y-util.h" +#include "table/e-table-click-to-add.h" +#include "table/e-table-subset.h" +#include "table/e-table.h" +#include "table/e-tree.h" +#include "misc/e-canvas.h" +#include "misc/e-selection-model.h" + +#include "gal-a11y-e-table-item.h" +#include "gal-a11y-e-table-item-factory.h" +#include "gal-a11y-e-table-click-to-add.h" +#include "gal-a11y-e-cell-registry.h" +#include "gal-a11y-e-cell.h" +#include "gal-a11y-e-table-column-header.h" + +#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yETableItemClass)) +static GObjectClass *parent_class; +static AtkComponentIface *component_parent_iface; +static GType parent_type; +static gint priv_offset; +static GQuark quark_accessible_object = 0; +#define GET_PRIVATE(object) ((GalA11yETableItemPrivate *) (((gchar *) object) + priv_offset)) +#define PARENT_TYPE (parent_type) + +struct _GalA11yETableItemPrivate { + gint cols; + gint rows; + gint selection_change_id; + gint cursor_change_id; + ETableCol ** columns; + ESelectionModel *selection; + AtkStateSet *state_set; + GtkWidget *widget; +}; + +static gboolean gal_a11y_e_table_item_ref_selection (GalA11yETableItem *a11y, + ESelectionModel *selection); +static gboolean gal_a11y_e_table_item_unref_selection (GalA11yETableItem *a11y); + +static AtkObject* eti_ref_at (AtkTable *table, gint row, gint column); + +static void +item_destroyed (GtkObject *item, gpointer user_data) +{ + GalA11yETableItem *a11y = GAL_A11Y_E_TABLE_ITEM (user_data); + GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y); + + atk_state_set_add_state (priv->state_set, ATK_STATE_DEFUNCT); + atk_object_notify_state_change (ATK_OBJECT (a11y), ATK_STATE_DEFUNCT, TRUE); + + if (priv->selection) + gal_a11y_e_table_item_unref_selection (a11y); + +} + +static AtkStateSet * +eti_ref_state_set (AtkObject *accessible) +{ + GalA11yETableItemPrivate *priv = GET_PRIVATE (accessible); + + g_object_ref(priv->state_set); + + return priv->state_set; +} + +inline static gint +view_to_model_row(ETableItem *eti, gint row) +{ + if (eti->uses_source_model) { + ETableSubset *etss = E_TABLE_SUBSET(eti->table_model); + if (row >= 0 && row < etss->n_map) { + eti->row_guess = row; + return etss->map_table[row]; + } else + return -1; + } else + return row; +} + +inline static gint +view_to_model_col(ETableItem *eti, gint col) +{ + ETableCol *ecol = e_table_header_get_column (eti->header, col); + return ecol ? ecol->col_idx : -1; +} + +inline static gint +model_to_view_row(ETableItem *eti, gint row) +{ + gint i; + if (row == -1) + return -1; + if (eti->uses_source_model) { + ETableSubset *etss = E_TABLE_SUBSET(eti->table_model); + if (eti->row_guess >= 0 && eti->row_guess < etss->n_map) { + if (etss->map_table[eti->row_guess] == row) { + return eti->row_guess; + } + } + for (i = 0; i < etss->n_map; i++) { + if (etss->map_table[i] == row) + return i; + } + return -1; + } else + return row; +} + +inline static gint +model_to_view_col(ETableItem *eti, gint col) +{ + gint i; + if (col == -1) + return -1; + for (i = 0; i < eti->cols; i++) { + ETableCol *ecol = e_table_header_get_column (eti->header, i); + if (ecol->col_idx == col) + return i; + } + return -1; +} + +inline static GObject * +eti_a11y_get_gobject (AtkObject *accessible) +{ + return atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible)); +} + +static void +eti_a11y_reset_focus_object (GalA11yETableItem *a11y, ETableItem *item, gboolean notify) +{ + ESelectionModel * esm; + gint cursor_row, cursor_col, view_row, view_col; + AtkObject *cell, *old_cell; + + esm = item->selection; + g_return_if_fail (esm); + + cursor_row = e_selection_model_cursor_row (esm); + cursor_col = e_selection_model_cursor_col (esm); + + view_row = model_to_view_row (item, cursor_row); + view_col = model_to_view_col (item, cursor_col); + + if (view_row == -1) + view_row = 0; + if (view_col == -1) + view_col = 0; + + old_cell = (AtkObject *)g_object_get_data (G_OBJECT (a11y), "gail-focus-object"); + if (old_cell && GAL_A11Y_IS_E_CELL (old_cell)) + gal_a11y_e_cell_remove_state (GAL_A11Y_E_CELL (old_cell), ATK_STATE_FOCUSED, FALSE); + if (old_cell) + g_object_unref (old_cell); + + cell = eti_ref_at (ATK_TABLE (a11y), view_row, view_col); + + if (cell != NULL) { + g_object_set_data (G_OBJECT (a11y), "gail-focus-object", cell); + gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (cell), ATK_STATE_FOCUSED, FALSE); + } else + g_object_set_data (G_OBJECT (a11y), "gail-focus-object", NULL); + + if (notify && cell) + atk_focus_tracker_notify (cell); +} + +static void +eti_dispose (GObject *object) +{ + GalA11yETableItem *a11y = GAL_A11Y_E_TABLE_ITEM (object); + GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y); + + if (priv->columns) { + g_free(priv->columns); + priv->columns = NULL; + } + + if (parent_class->dispose) + parent_class->dispose (object); +} + +/* Static functions */ +static gint +eti_get_n_children (AtkObject *accessible) +{ + g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (accessible), 0); + if (!eti_a11y_get_gobject (accessible)) + return 0; + + return atk_table_get_n_columns (ATK_TABLE (accessible)) * + (atk_table_get_n_rows (ATK_TABLE (accessible)) + 1); +} + +static AtkObject* +eti_ref_child (AtkObject *accessible, gint index) +{ + ETableItem *item; + gint col, row; + + g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (accessible), NULL); + item = E_TABLE_ITEM (eti_a11y_get_gobject (accessible)); + if (!item) + return NULL; + + if (index < item->cols) { + ETableCol *ecol; + AtkObject *child; + + ecol = e_table_header_get_column (item->header, index); + child = gal_a11y_e_table_column_header_new (ecol, item); + return child; + } + index -= item->cols; + + col = index % item->cols; + row = index / item->cols; + + return eti_ref_at (ATK_TABLE (accessible), row, col); +} + +static void +eti_get_extents (AtkComponent *component, + gint *x, + gint *y, + gint *width, + gint *height, + AtkCoordType coord_type) +{ + ETableItem *item; + AtkObject *parent; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (component))); + if (!item) + return; + + parent = ATK_OBJECT (component)->accessible_parent; + if (parent && ATK_IS_COMPONENT (parent)) + atk_component_get_extents (ATK_COMPONENT (parent), x, y, + width, height, + coord_type); + + if (parent && GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD (parent)) { + ETableClickToAdd *etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (parent))); + if (etcta) { + *width = etcta->width; + *height = etcta->height; + } + } +} + +static AtkObject* +eti_ref_accessible_at_point (AtkComponent *component, + gint x, + gint y, + AtkCoordType coord_type) +{ + gint row = -1; + gint col = -1; + gint x_origin, y_origin; + ETableItem *item; + GtkWidget *tableOrTree; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (component))); + if (!item) + return NULL; + + atk_component_get_position (component, + &x_origin, + &y_origin, + coord_type); + x -= x_origin; + y -= y_origin; + + tableOrTree = gtk_widget_get_parent (GTK_WIDGET (item->parent.canvas)); + + if (E_IS_TREE(tableOrTree)) + e_tree_get_cell_at (E_TREE (tableOrTree), x, y, &row, &col); + else + e_table_get_cell_at (E_TABLE (tableOrTree), x, y, &row, &col); + + if (row != -1 && col != -1) { + return eti_ref_at (ATK_TABLE (component), row, col); + } else { + return NULL; + } +} + + +static void +cell_destroyed (gpointer data) +{ + GalA11yECell * cell; + + g_return_if_fail (GAL_A11Y_IS_E_CELL (data)); + cell = GAL_A11Y_E_CELL (data); + + g_return_if_fail (cell->item && G_IS_OBJECT (cell->item)); + + if (cell->item) { + g_object_unref (cell->item); + cell->item = NULL; + } + +} + +/* atk table */ +static AtkObject* +eti_ref_at (AtkTable *table, gint row, gint column) +{ + ETableItem *item; + AtkObject* ret; + GalA11yETableItemPrivate *priv = GET_PRIVATE (table); + + if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) + return NULL; + + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return NULL; + + if (column >= 0 && + column < item->cols && + row >= 0 && + row < item->rows && + item->cell_views_realized) { + ECellView *cell_view = item->cell_views[column]; + ETableCol *ecol = e_table_header_get_column (item->header, column); + ret = gal_a11y_e_cell_registry_get_object (NULL, + item, + cell_view, + ATK_OBJECT (table), + ecol->col_idx, + column, + row); + if (ATK_IS_OBJECT (ret)) { + g_object_weak_ref (G_OBJECT (ret), + (GWeakNotify) cell_destroyed, + ret); + /* if current cell is focused, add FOCUSED state */ + if (e_selection_model_cursor_row (item->selection) == GAL_A11Y_E_CELL (ret)->row && + e_selection_model_cursor_col (item->selection) == GAL_A11Y_E_CELL (ret)->model_col) + gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (ret), ATK_STATE_FOCUSED, FALSE); + } else + ret = NULL; + + return ret; + } + + return NULL; +} + +static gint +eti_get_index_at (AtkTable *table, gint row, gint column) +{ + ETableItem *item; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return -1; + + return column + (row + 1) * item->cols; +} + +static gint +eti_get_column_at_index (AtkTable *table, gint index) +{ + ETableItem *item; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return -1; + + return index % item->cols; +} + +static gint +eti_get_row_at_index (AtkTable *table, gint index) +{ + ETableItem *item; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return -1; + + return index / item->cols - 1; +} + +static gint +eti_get_n_columns (AtkTable *table) +{ + ETableItem *item; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return -1; + + return item->cols; +} + +static gint +eti_get_n_rows (AtkTable *table) +{ + ETableItem *item; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return -1; + + return item->rows; +} + +static gint +eti_get_column_extent_at (AtkTable *table, + gint row, + gint column) +{ + ETableItem *item; + gint width; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return -1; + + e_table_item_get_cell_geometry (item, + &row, + &column, + NULL, + NULL, + &width, + NULL); + + return width; +} + +static gint +eti_get_row_extent_at (AtkTable *table, + gint row, + gint column) +{ + ETableItem *item; + gint height; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return -1; + + e_table_item_get_cell_geometry (item, + &row, + &column, + NULL, + NULL, + NULL, + &height); + + return height; +} + +static AtkObject * +eti_get_caption (AtkTable *table) +{ + /* Unimplemented */ + return NULL; +} + +static G_CONST_RETURN gchar * +eti_get_column_description (AtkTable *table, + gint column) +{ + ETableItem *item; + ETableCol *ecol; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return NULL; + + ecol = e_table_header_get_column (item->header, column); + + return ecol->text; +} + +static AtkObject * +eti_get_column_header (AtkTable *table, gint column) +{ + ETableItem *item; + ETableCol *ecol; + AtkObject *atk_obj = NULL; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return NULL; + + ecol = e_table_header_get_column (item->header, column); + if (ecol) { + atk_obj = gal_a11y_e_table_column_header_new (ecol, item); + } + + return atk_obj; +} + +static G_CONST_RETURN gchar * +eti_get_row_description (AtkTable *table, + gint row) +{ + /* Unimplemented */ + return NULL; +} + +static AtkObject * +eti_get_row_header (AtkTable *table, + gint row) +{ + /* Unimplemented */ + return NULL; +} + +static AtkObject * +eti_get_summary (AtkTable *table) +{ + /* Unimplemented */ + return NULL; +} + +static gboolean +table_is_row_selected (AtkTable *table, gint row) +{ + ETableItem *item; + GalA11yETableItemPrivate *priv = GET_PRIVATE (table); + + if (row < 0) + return FALSE; + + if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) + return FALSE; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return FALSE; + + return e_selection_model_is_row_selected(item->selection, view_to_model_row (item, row)); +} + +static gboolean +table_is_selected (AtkTable *table, gint row, gint column) +{ + return table_is_row_selected (table, row); +} + +static gint +table_get_selected_rows (AtkTable *table, gint **rows_selected) +{ + ETableItem *item; + gint n_selected, row, index_selected; + GalA11yETableItemPrivate *priv = GET_PRIVATE (table); + + if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) + return 0; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return 0; + + n_selected = e_selection_model_selected_count (item->selection); + if (rows_selected) { + *rows_selected = (gint *) g_malloc (n_selected * sizeof (gint)); + + index_selected = 0; + for (row = 0; row < item->rows && index_selected < n_selected; ++row) { + if (atk_table_is_row_selected (table, row)) { + (*rows_selected)[index_selected] = row; + ++index_selected; + } + } + } + return n_selected; +} + +static gboolean +table_add_row_selection (AtkTable *table, gint row) +{ + ETableItem *item; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return FALSE; + + if (table_is_row_selected (table, row)) + return TRUE; + e_selection_model_toggle_single_row (item->selection, + view_to_model_row (item, row)); + + return TRUE; +} + +static gboolean +table_remove_row_selection (AtkTable *table, gint row) +{ + ETableItem *item; + GalA11yETableItemPrivate *priv = GET_PRIVATE (table); + + if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) + return FALSE; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return FALSE; + + if (!atk_table_is_row_selected (table, row)) + return TRUE; + e_selection_model_toggle_single_row (item->selection, view_to_model_row (item, row)); + return TRUE; +} + +static void +eti_atk_table_iface_init (AtkTableIface *iface) +{ + iface->ref_at = eti_ref_at; + iface->get_index_at = eti_get_index_at; + iface->get_column_at_index = eti_get_column_at_index; + iface->get_row_at_index = eti_get_row_at_index; + iface->get_n_columns = eti_get_n_columns; + iface->get_n_rows = eti_get_n_rows; + iface->get_column_extent_at = eti_get_column_extent_at; + iface->get_row_extent_at = eti_get_row_extent_at; + iface->get_caption = eti_get_caption; + iface->get_column_description = eti_get_column_description; + iface->get_column_header = eti_get_column_header; + iface->get_row_description = eti_get_row_description; + iface->get_row_header = eti_get_row_header; + iface->get_summary = eti_get_summary; + + iface->is_row_selected = table_is_row_selected; + iface->is_selected = table_is_selected; + iface->get_selected_rows = table_get_selected_rows; + iface->add_row_selection = table_add_row_selection; + iface->remove_row_selection = table_remove_row_selection; +} + +static void +eti_atk_component_iface_init (AtkComponentIface *iface) +{ + component_parent_iface = g_type_interface_peek_parent (iface); + + iface->ref_accessible_at_point = eti_ref_accessible_at_point; + iface->get_extents = eti_get_extents; +} + +static void +eti_rows_inserted (ETableModel * model, gint row, gint count, + AtkObject * table_item) +{ + gint n_cols,n_rows,i,j; + GalA11yETableItem * item_a11y; + gint old_nrows; + + g_return_if_fail (table_item); + item_a11y = GAL_A11Y_E_TABLE_ITEM (table_item); + + n_cols = atk_table_get_n_columns (ATK_TABLE(table_item)); + n_rows = atk_table_get_n_rows (ATK_TABLE(table_item)); + + old_nrows = GET_PRIVATE(item_a11y)->rows; + + g_return_if_fail (n_cols > 0 && n_rows > 0); + g_return_if_fail (old_nrows == n_rows - count); + + GET_PRIVATE(table_item)->rows = n_rows; + + g_signal_emit_by_name (table_item, "row-inserted", row, + count, NULL); + + for (i = row; i < (row + count); i ++) { + for (j = 0; j < n_cols; j ++) { + g_signal_emit_by_name (table_item, + "children_changed::add", + ( ((i + 1)*n_cols) + j), NULL, NULL); + } + } + + g_signal_emit_by_name (table_item, "visible-data-changed"); +} + +static void +eti_rows_deleted (ETableModel * model, gint row, gint count, + AtkObject * table_item) +{ + gint i,j, n_rows, n_cols, old_nrows; + ETableItem *item = E_TABLE_ITEM (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (table_item))); + + n_rows = atk_table_get_n_rows (ATK_TABLE(table_item)); + n_cols = atk_table_get_n_columns (ATK_TABLE(table_item)); + + old_nrows = GET_PRIVATE(table_item)->rows; + + g_return_if_fail ( row+count <= old_nrows); + g_return_if_fail (old_nrows == n_rows + count); + GET_PRIVATE(table_item)->rows = n_rows; + + g_signal_emit_by_name (table_item, "row-deleted", row, + count, NULL); + + for (i = row; i < (row + count); i ++) { + for (j = 0; j < n_cols; j ++) { + g_signal_emit_by_name (table_item, + "children_changed::remove", + ( ((i + 1)*n_cols) + j), NULL, NULL); + } + } + g_signal_emit_by_name (table_item, "visible-data-changed"); + eti_a11y_reset_focus_object ((GalA11yETableItem *)table_item, item, TRUE); +} + +static void +eti_tree_model_node_changed_cb (ETreeModel *model, ETreePath node, ETableItem *eti) +{ + AtkObject *atk_obj; + GalA11yETableItem *a11y; + + g_return_if_fail (E_IS_TABLE_ITEM (eti)); + + atk_obj = atk_gobject_accessible_for_object (G_OBJECT (eti)); + a11y = GAL_A11Y_E_TABLE_ITEM (atk_obj); + + /* we can't figure out which rows are changed, so just send out a signal ... */ + if (GET_PRIVATE (a11y)->rows > 0) + g_signal_emit_by_name (a11y, "visible-data-changed"); +} + +enum { + ETI_HEADER_UNCHANGED = 0, + ETI_HEADER_REORDERED, + ETI_HEADER_NEW_ADDED, + ETI_HEADER_REMOVED +}; + +/* + * 1. Check what actually happened: column reorder, remove or add + * 2. Update cache + * 3. Emit signals + */ +static void +eti_header_structure_changed (ETableHeader *eth, AtkObject *a11y) +{ + + gboolean reorder_found=FALSE, added_found=FALSE, removed_found=FALSE; + GalA11yETableItem * a11y_item; + ETableCol ** cols, **prev_cols; + GalA11yETableItemPrivate *priv; + gint *state = NULL, *prev_state = NULL, *reorder = NULL; + gint i,j,n_rows,n_cols, prev_n_cols; + + a11y_item = GAL_A11Y_E_TABLE_ITEM (a11y); + priv = GET_PRIVATE (a11y_item); + + /* Assume rows do not changed. */ + n_rows = priv->rows; + + prev_n_cols = priv->cols; + prev_cols = priv->columns; + + cols = e_table_header_get_columns (eth); + n_cols = eth->col_count; + + g_return_if_fail (cols && prev_cols && n_cols > 0); + + /* Init to ETI_HEADER_UNCHANGED. */ + state = g_malloc0 (sizeof (gint) * n_cols); + prev_state = g_malloc0 (sizeof (gint) * prev_n_cols); + reorder = g_malloc0 (sizeof (gint) * n_cols); + + /* Compare with previously saved column headers. */ + for ( i = 0; i < n_cols && cols[i]; i ++ ) { + for ( j = 0; j < prev_n_cols && prev_cols[j]; j ++ ) { + if ( prev_cols [j] == cols[i] && i != j ) { + + reorder_found = TRUE; + state [i] = ETI_HEADER_REORDERED; + reorder [i] = j; + + break; + } else if (prev_cols[j] == cols[i]) { + /* OK, this column is not changed. */ + break; + } + } + + /* cols[i] is new added column. */ + if ( j == prev_n_cols ) { + added_found = TRUE; + state[i] = ETI_HEADER_NEW_ADDED; + } + } + + /* Now try to find if there are removed columns. */ + for (i = 0; i < prev_n_cols && prev_cols[i]; i ++) { + for (j = 0; j < n_cols && cols[j]; j ++) + if ( prev_cols [j] == cols[i] ) + break; + + /* Removed columns found. */ + if ( j == n_cols ) { + removed_found = TRUE; + prev_state[j] = ETI_HEADER_REMOVED; + } + } + + /* If nothing interesting just return. */ + if (!reorder_found && !added_found && !removed_found) + return; + + /* Emit signals */ + if (reorder_found) + g_signal_emit_by_name (G_OBJECT(a11y_item), "column_reordered"); + + + if (removed_found) { + for (i = 0; i < prev_n_cols; i ++ ) { + if (prev_state[i] == ETI_HEADER_REMOVED) { + g_signal_emit_by_name (G_OBJECT(a11y_item), "column-deleted", i, 1); + for (j = 0; j < n_rows; j ++) + g_signal_emit_by_name (G_OBJECT(a11y_item), "children_changed::remove", ((j+1)*prev_n_cols+i), NULL, NULL); + } + } + } + + if (added_found) { + for ( i = 0; i < n_cols; i ++ ) { + if (state[i] == ETI_HEADER_NEW_ADDED) { + g_signal_emit_by_name (G_OBJECT(a11y_item), "column-inserted", i, 1); + for (j = 0; j < n_rows; j ++) + g_signal_emit_by_name (G_OBJECT(a11y_item), "children_changed::add", ((j+1)*n_cols+i), NULL, NULL); + } + } + } + + priv->cols = n_cols; + + g_free (state); + g_free (reorder); + g_free (prev_state); + + g_free (priv->columns); + priv->columns = cols; +} + + +static void +eti_real_initialize (AtkObject *obj, + gpointer data) +{ + ETableItem * eti; + ETableModel * model; + + ATK_OBJECT_CLASS (parent_class)->initialize (obj, data); + eti = E_TABLE_ITEM (data); + + model = eti->table_model; + + g_signal_connect (model, "model-rows-inserted", + G_CALLBACK (eti_rows_inserted), + obj); + g_signal_connect (model, "model-rows-deleted", + G_CALLBACK (eti_rows_deleted), + obj); + g_signal_connect (G_OBJECT (eti->header), "structure_change", + G_CALLBACK (eti_header_structure_changed), obj); + +} + +static void +eti_class_init (GalA11yETableItemClass *klass) +{ + AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + quark_accessible_object = g_quark_from_static_string ("gtk-accessible-object"); + + parent_class = g_type_class_ref (PARENT_TYPE); + + object_class->dispose = eti_dispose; + + atk_object_class->get_n_children = eti_get_n_children; + atk_object_class->ref_child = eti_ref_child; + atk_object_class->initialize = eti_real_initialize; + atk_object_class->ref_state_set = eti_ref_state_set; +} + +static void +eti_init (GalA11yETableItem *a11y) +{ + GalA11yETableItemPrivate *priv; + + priv = GET_PRIVATE (a11y); + + priv->selection_change_id = 0; + priv->cursor_change_id = 0; + priv->selection = NULL; +} + +/* atk selection */ + +static void atk_selection_interface_init (AtkSelectionIface *iface); +static gboolean selection_add_selection (AtkSelection *selection, + gint i); +static gboolean selection_clear_selection (AtkSelection *selection); +static AtkObject* selection_ref_selection (AtkSelection *selection, + gint i); +static gint selection_get_selection_count (AtkSelection *selection); +static gboolean selection_is_child_selected (AtkSelection *selection, + gint i); + +/* callbacks */ +static void eti_a11y_selection_model_removed_cb (ETableItem *eti, + ESelectionModel *selection, + gpointer data); +static void eti_a11y_selection_model_added_cb (ETableItem *eti, + ESelectionModel *selection, + gpointer data); +static void eti_a11y_selection_changed_cb (ESelectionModel *selection, + GalA11yETableItem *a11y); +static void eti_a11y_cursor_changed_cb (ESelectionModel *selection, + gint row, gint col, + GalA11yETableItem *a11y); + +/** + * gal_a11y_e_table_item_get_type: + * @void: + * + * Registers the &GalA11yETableItem class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yETableItem class. + **/ +GType +gal_a11y_e_table_item_get_type (void) +{ + static GType type = 0; + + if (!type) { + AtkObjectFactory *factory; + + GTypeInfo info = { + sizeof (GalA11yETableItemClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) eti_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yETableItem), + 0, + (GInstanceInitFunc) eti_init, + NULL /* value_table_item */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) eti_atk_component_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + static const GInterfaceInfo atk_table_info = { + (GInterfaceInitFunc) eti_atk_table_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + static const GInterfaceInfo atk_selection_info = { + (GInterfaceInitFunc) atk_selection_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + + factory = atk_registry_get_factory (atk_get_default_registry (), GNOME_TYPE_CANVAS_ITEM); + parent_type = atk_object_factory_get_accessible_type (factory); + + type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yETableItem", &info, 0, + sizeof (GalA11yETableItemPrivate), &priv_offset); + + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); + g_type_add_interface_static (type, ATK_TYPE_TABLE, &atk_table_info); + g_type_add_interface_static (type, ATK_TYPE_SELECTION, &atk_selection_info); + } + + return type; +} + +AtkObject * +gal_a11y_e_table_item_new (ETableItem *item) +{ + GalA11yETableItem *a11y; + AtkObject *accessible; + ESelectionModel * esm; + AtkObject *parent; + const gchar *name; + + g_return_val_if_fail (item && item->cols >= 0 && item->rows >= 0, NULL); + a11y = g_object_new (gal_a11y_e_table_item_get_type (), NULL); + + atk_object_initialize (ATK_OBJECT (a11y), item); + + GET_PRIVATE (a11y)->state_set = atk_state_set_new (); + + atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_TRANSIENT); + atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_ENABLED); + atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_SENSITIVE); + atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_SHOWING); + atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_VISIBLE); + + + accessible = ATK_OBJECT(a11y); + + /* Initialize cell data. */ + GET_PRIVATE (a11y)->cols = item->cols; + GET_PRIVATE (a11y)->rows = item->rows; + + GET_PRIVATE (a11y)->columns = e_table_header_get_columns (item->header); + if ( GET_PRIVATE (a11y)->columns == NULL) + return NULL; + + if (item) { + g_signal_connect (G_OBJECT(item), "selection_model_removed", + G_CALLBACK (eti_a11y_selection_model_removed_cb), NULL); + g_signal_connect (G_OBJECT(item), "selection_model_added", + G_CALLBACK (eti_a11y_selection_model_added_cb), NULL); + if (item->selection) + gal_a11y_e_table_item_ref_selection (a11y, + item->selection); + + /* find the TableItem's parent: table or tree */ + GET_PRIVATE (a11y)->widget = gtk_widget_get_parent (GTK_WIDGET (item->parent.canvas)); + parent = gtk_widget_get_accessible (GET_PRIVATE (a11y)->widget); + name = atk_object_get_name (parent); + if (name) + atk_object_set_name (accessible, name); + atk_object_set_parent (accessible, parent); + + if (E_IS_TREE (GET_PRIVATE (a11y)->widget)) { + ETreeModel *model; + model = e_tree_get_model (E_TREE (GET_PRIVATE (a11y)->widget)); + g_signal_connect (G_OBJECT(model), "node_changed", + G_CALLBACK (eti_tree_model_node_changed_cb), item); + accessible->role = ATK_ROLE_TREE_TABLE; + } else if (E_IS_TABLE (GET_PRIVATE (a11y)->widget)) { + accessible->role = ATK_ROLE_TABLE; + } + } + + if (item) + g_signal_connect (G_OBJECT (item), "destroy", + G_CALLBACK (item_destroyed), + a11y); + esm = item->selection; + + if (esm != NULL) { + eti_a11y_reset_focus_object (a11y, item, FALSE); + } + + return ATK_OBJECT (a11y); +} + +static gboolean +gal_a11y_e_table_item_ref_selection (GalA11yETableItem *a11y, + ESelectionModel *selection) +{ + GalA11yETableItemPrivate *priv; + + g_return_val_if_fail (a11y && selection, FALSE); + + priv = GET_PRIVATE (a11y); + priv->selection_change_id = g_signal_connect ( + G_OBJECT(selection), "selection_changed", + G_CALLBACK (eti_a11y_selection_changed_cb), a11y); + priv->cursor_change_id = g_signal_connect ( + G_OBJECT(selection), "cursor_changed", + G_CALLBACK (eti_a11y_cursor_changed_cb), a11y); + + priv->selection = selection; + g_object_ref (selection); + + return TRUE; +} + +static gboolean +gal_a11y_e_table_item_unref_selection (GalA11yETableItem *a11y) +{ + GalA11yETableItemPrivate *priv; + + g_return_val_if_fail (a11y, FALSE); + + priv = GET_PRIVATE (a11y); + + g_return_val_if_fail (priv->selection_change_id != 0, FALSE); + g_return_val_if_fail (priv->cursor_change_id != 0, FALSE); + + + g_signal_handler_disconnect (priv->selection, + priv->selection_change_id); + g_signal_handler_disconnect (priv->selection, + priv->cursor_change_id); + priv->cursor_change_id = 0; + priv->selection_change_id = 0; + + g_object_unref (priv->selection); + priv->selection = NULL; + + return TRUE; +} + +/* callbacks */ + +static void +eti_a11y_selection_model_removed_cb (ETableItem *eti, ESelectionModel *selection, + gpointer data) +{ + AtkObject *atk_obj; + GalA11yETableItem *a11y; + + g_return_if_fail (E_IS_TABLE_ITEM (eti)); + g_return_if_fail (E_IS_SELECTION_MODEL (selection)); + + atk_obj = atk_gobject_accessible_for_object (G_OBJECT (eti)); + a11y = GAL_A11Y_E_TABLE_ITEM (atk_obj); + + if (selection == GET_PRIVATE (a11y)->selection) + gal_a11y_e_table_item_unref_selection (a11y); +} + +static void +eti_a11y_selection_model_added_cb (ETableItem *eti, ESelectionModel *selection, + gpointer data) +{ + AtkObject *atk_obj; + GalA11yETableItem *a11y; + + g_return_if_fail (E_IS_TABLE_ITEM (eti)); + g_return_if_fail (E_IS_SELECTION_MODEL (selection)); + + atk_obj = atk_gobject_accessible_for_object (G_OBJECT (eti)); + a11y = GAL_A11Y_E_TABLE_ITEM (atk_obj); + + if (GET_PRIVATE (a11y)->selection) + gal_a11y_e_table_item_unref_selection (a11y); + gal_a11y_e_table_item_ref_selection (a11y, selection); +} + +static void +eti_a11y_selection_changed_cb (ESelectionModel *selection, GalA11yETableItem *a11y) +{ + GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y); + + if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) + return; + + g_return_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (a11y)); + + g_signal_emit_by_name (a11y, "selection_changed"); +} + +static void +eti_a11y_cursor_changed_cb (ESelectionModel *selection, + gint row, gint col, GalA11yETableItem *a11y) +{ + ETableItem *item; + GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y); + + g_return_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (a11y)); + + if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) + return; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (a11y))); + + g_return_if_fail (item); + + if (row == -1 && col == -1) + return; + eti_a11y_reset_focus_object (a11y, item, TRUE); +} + +/* atk selection */ + +static void atk_selection_interface_init (AtkSelectionIface *iface) +{ + g_return_if_fail (iface != NULL); + iface->add_selection = selection_add_selection; + iface->clear_selection = selection_clear_selection; + iface->ref_selection = selection_ref_selection; + iface->get_selection_count = selection_get_selection_count; + iface->is_child_selected = selection_is_child_selected; +} + +static gboolean +selection_add_selection (AtkSelection *selection, gint index) +{ + AtkTable *table; + gint row, col, cursor_row, cursor_col, model_row, model_col; + ETableItem *item; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (selection))); + if (!item) + return FALSE; + + table = ATK_TABLE (selection); + + row = atk_table_get_row_at_index (table, index); + col = atk_table_get_column_at_index (table, index); + + model_row = view_to_model_row (item, row); + model_col = view_to_model_col (item, col); + + cursor_row = e_selection_model_cursor_row (item->selection); + cursor_col = e_selection_model_cursor_col (item->selection); + + /* check whether is selected already */ + if (model_row == cursor_row && model_col == cursor_col) + return TRUE; + + if (model_row != cursor_row) { + /* we need to make the item get focus */ + e_canvas_item_grab_focus (GNOME_CANVAS_ITEM (item), TRUE); + + /* FIXME, currently we only support single row selection */ + atk_selection_clear_selection (selection); + atk_table_add_row_selection (table, row); + } + + e_selection_model_change_cursor (item->selection, + model_row, + model_col); + e_selection_model_cursor_changed (item->selection, + model_row, + model_col); + e_selection_model_cursor_activated (item->selection, + model_row, + model_col); + return TRUE; +} + +static gboolean +selection_clear_selection (AtkSelection *selection) +{ + ETableItem *item; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (selection))); + if (!item) + return FALSE; + + e_selection_model_clear (item->selection); + return TRUE; +} + +static AtkObject * +selection_ref_selection (AtkSelection *selection, gint index) +{ + AtkTable *table; + gint row, col; + + table = ATK_TABLE (selection); + row = atk_table_get_row_at_index (table, index); + col = atk_table_get_column_at_index (table, index); + if (!atk_table_is_row_selected (table, row)) + return NULL; + + return eti_ref_at (table, row, col); +} + +static gint +selection_get_selection_count (AtkSelection *selection) +{ + AtkTable *table; + gint n_selected; + + table = ATK_TABLE (selection); + n_selected = atk_table_get_selected_rows (table, NULL); + if (n_selected > 0) + n_selected *= atk_table_get_n_columns (table); + return n_selected; +} + +static gboolean +selection_is_child_selected (AtkSelection *selection, gint i) +{ + gint row; + + row = atk_table_get_row_at_index (ATK_TABLE (selection), i); + return atk_table_is_row_selected (ATK_TABLE (selection), row); +} + +void +gal_a11y_e_table_item_init (void) +{ + if (atk_get_root ()) + atk_registry_set_factory_type (atk_get_default_registry (), + E_TABLE_ITEM_TYPE, + gal_a11y_e_table_item_factory_get_type ()); +} + diff --git a/widgets/table/gal-a11y-e-table-item.h b/widgets/table/gal-a11y-e-table-item.h new file mode 100644 index 0000000000..27d6a8244b --- /dev/null +++ b/widgets/table/gal-a11y-e-table-item.h @@ -0,0 +1,59 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Christopher James Lahey + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TABLE_ITEM_H__ +#define __GAL_A11Y_E_TABLE_ITEM_H__ + +#include +#include
+#include + +#define GAL_A11Y_TYPE_E_TABLE_ITEM (gal_a11y_e_table_item_get_type ()) +#define GAL_A11Y_E_TABLE_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_ITEM, GalA11yETableItem)) +#define GAL_A11Y_E_TABLE_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_ITEM, GalA11yETableItemClass)) +#define GAL_A11Y_IS_E_TABLE_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_ITEM)) +#define GAL_A11Y_IS_E_TABLE_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_ITEM)) + +typedef struct _GalA11yETableItem GalA11yETableItem; +typedef struct _GalA11yETableItemClass GalA11yETableItemClass; +typedef struct _GalA11yETableItemPrivate GalA11yETableItemPrivate; + +/* This struct should actually be larger as this isn't what we derive from. + * The GalA11yETableItemPrivate comes right after the parent class structure. + **/ +struct _GalA11yETableItem { + AtkGObjectAccessible parent; +}; + +struct _GalA11yETableItemClass { + AtkGObjectAccessibleClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_table_item_get_type (void); +AtkObject *gal_a11y_e_table_item_new (ETableItem *item); + +void gal_a11y_e_table_item_init (void); + +#endif /* ! __GAL_A11Y_E_TABLE_ITEM_H__ */ diff --git a/widgets/table/gal-a11y-e-table.c b/widgets/table/gal-a11y-e-table.c new file mode 100644 index 0000000000..bf75227af4 --- /dev/null +++ b/widgets/table/gal-a11y-e-table.c @@ -0,0 +1,308 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Christopher James Lahey + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include + +#include "a11y/gal-a11y-util.h" +#include "table/e-table.h" +#include "table/e-table-click-to-add.h" +#include "table/e-table-group.h" +#include "table/e-table-group-container.h" +#include "table/e-table-group-leaf.h" + +#include "gal-a11y-e-table.h" +#include "gal-a11y-e-table-factory.h" +#include "gal-a11y-e-table-item.h" + +#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yETableClass)) +static AtkObjectClass *parent_class; +static GType parent_type; +static gint priv_offset; +#define GET_PRIVATE(object) ((GalA11yETablePrivate *) (((gchar *) object) + priv_offset)) +#define PARENT_TYPE (parent_type) + +struct _GalA11yETablePrivate { + AtkObject *child_item; +}; + +/* Static functions */ +static ETableItem * +find_first_table_item (ETableGroup *group) +{ + GnomeCanvasGroup *cgroup; + GList *l; + + cgroup = GNOME_CANVAS_GROUP (group); + + for (l = cgroup->item_list; l; l = l->next) { + GnomeCanvasItem *i; + + i = GNOME_CANVAS_ITEM (l->data); + + if (E_IS_TABLE_GROUP (i)) + return find_first_table_item (E_TABLE_GROUP (i)); + else if (E_IS_TABLE_ITEM (i)) { + return E_TABLE_ITEM (i); + } + } + + return NULL; +} + +static AtkObject* +eti_get_accessible (ETableItem *eti, AtkObject *parent) +{ + AtkObject *a11y = NULL; + + g_return_val_if_fail (eti, NULL); + + a11y = atk_gobject_accessible_for_object (G_OBJECT (eti)); + g_return_val_if_fail (a11y, NULL); + + return a11y; +} + +static gboolean +init_child_item (GalA11yETable *a11y) +{ + ETable *table; + + if (!a11y || !GTK_IS_ACCESSIBLE (a11y)) + return FALSE; + + table = E_TABLE (GTK_ACCESSIBLE (a11y)->widget); + if (table && GTK_WIDGET_MAPPED (GTK_WIDGET (table)) && table->group && E_IS_TABLE_GROUP_CONTAINER(table->group)) { + ETableGroupContainer *etgc = (ETableGroupContainer *)table->group; + GList *list; + + for (list = etgc->children; list; list = g_list_next (list)) { + ETableGroupContainerChildNode *child_node = list->data; + ETableGroup *child = child_node->child; + ETableItem *eti = find_first_table_item (child); + + eti_get_accessible (eti, ATK_OBJECT (a11y)); + } + } + g_object_unref (a11y); + g_object_unref (table); + + return FALSE; +} + +static AtkObject* +et_ref_accessible_at_point (AtkComponent *component, + gint x, + gint y, + AtkCoordType coord_type) +{ + GalA11yETable *a11y = GAL_A11Y_E_TABLE (component); + if (GET_PRIVATE (a11y)->child_item) + g_object_ref (GET_PRIVATE (a11y)->child_item); + return GET_PRIVATE (a11y)->child_item; +} + +static gint +et_get_n_children (AtkObject *accessible) +{ + GalA11yETable *a11y = GAL_A11Y_E_TABLE (accessible); + ETable * et; + gint n = 0; + + et = E_TABLE(GTK_ACCESSIBLE (a11y)->widget); + + if (et->group) { + if (E_IS_TABLE_GROUP_LEAF (et->group)) + n = 1; + else if (E_IS_TABLE_GROUP_CONTAINER (et->group)) { + ETableGroupContainer *etgc = (ETableGroupContainer *)et->group; + n = g_list_length (etgc->children); + } + } + + if (et && et->use_click_to_add && et->click_to_add) { + n++; + } + return n; +} + +static AtkObject* +et_ref_child (AtkObject *accessible, + gint i) +{ + GalA11yETable *a11y = GAL_A11Y_E_TABLE (accessible); + ETable * et; + gint child_no; + + et = E_TABLE(GTK_ACCESSIBLE (a11y)->widget); + + child_no = et_get_n_children (accessible); + if (i == 0 || i < child_no - 1) { + if (E_IS_TABLE_GROUP_LEAF (et->group)) { + ETableItem *eti = find_first_table_item (et->group); + AtkObject *aeti = eti_get_accessible (eti, accessible); + if (aeti) + g_object_ref (aeti); + return aeti; + + } else if (E_IS_TABLE_GROUP_CONTAINER (et->group)) { + ETableGroupContainer *etgc = (ETableGroupContainer *) et->group; + ETableGroupContainerChildNode *child_node = g_list_nth_data (etgc->children, i); + if (child_node) { + ETableGroup *child = child_node->child; + ETableItem * eti = find_first_table_item (child); + AtkObject *aeti = eti_get_accessible (eti, accessible); + if (aeti) + g_object_ref (aeti); + return aeti; + } + } + } else if (i == child_no -1) { + ETableClickToAdd * etcta; + + if (et && et->use_click_to_add && et->click_to_add) { + etcta = E_TABLE_CLICK_TO_ADD(et->click_to_add); + accessible = atk_gobject_accessible_for_object (G_OBJECT(etcta)); + if (accessible) + g_object_ref (accessible); + return accessible; + } + } + + return NULL; +} + +static AtkLayer +et_get_layer (AtkComponent *component) +{ + return ATK_LAYER_WIDGET; +} + +static void +et_class_init (GalA11yETableClass *klass) +{ + AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + atk_object_class->get_n_children = et_get_n_children; + atk_object_class->ref_child = et_ref_child; +} + +static void +et_atk_component_iface_init (AtkComponentIface *iface) +{ + iface->ref_accessible_at_point = et_ref_accessible_at_point; + iface->get_layer = et_get_layer; +} + +static void +et_init (GalA11yETable *a11y) +{ + GalA11yETablePrivate *priv; + + priv = GET_PRIVATE (a11y); + + priv->child_item = NULL; +} + +/** + * gal_a11y_e_table_get_type: + * @void: + * + * Registers the &GalA11yETable class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yETable class. + **/ +GType +gal_a11y_e_table_get_type (void) +{ + static GType type = 0; + + if (!type) { + AtkObjectFactory *factory; + + GTypeInfo info = { + sizeof (GalA11yETableClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) et_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yETable), + 0, + (GInstanceInitFunc) et_init, + NULL /* value_table */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) et_atk_component_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + factory = atk_registry_get_factory (atk_get_default_registry (), GTK_TYPE_WIDGET); + parent_type = atk_object_factory_get_accessible_type (factory); + + type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yETable", &info, 0, + sizeof (GalA11yETablePrivate), &priv_offset); + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); + } + + return type; +} + +AtkObject * +gal_a11y_e_table_new (GObject *widget) +{ + GalA11yETable *a11y; + ETable *table; + + table = E_TABLE (widget); + + a11y = g_object_new (gal_a11y_e_table_get_type (), NULL); + + GTK_ACCESSIBLE (a11y)->widget = GTK_WIDGET (widget); + + /* we need to init all the children for multiple table items */ + if (table && GTK_WIDGET_MAPPED (GTK_WIDGET (table)) && table->group && E_IS_TABLE_GROUP_CONTAINER (table->group)) { + /* Ref it here so that it is still valid in the idle function */ + /* It will be unrefed in the idle function */ + g_object_ref (a11y); + g_object_ref (widget); + + g_idle_add ((GSourceFunc)init_child_item, a11y); + } + + return ATK_OBJECT (a11y); +} + +void +gal_a11y_e_table_init (void) +{ + if (atk_get_root ()) + atk_registry_set_factory_type (atk_get_default_registry (), + E_TABLE_TYPE, + gal_a11y_e_table_factory_get_type ()); + +} + diff --git a/widgets/table/gal-a11y-e-table.h b/widgets/table/gal-a11y-e-table.h new file mode 100644 index 0000000000..d8f972df81 --- /dev/null +++ b/widgets/table/gal-a11y-e-table.h @@ -0,0 +1,59 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Christopher James Lahey + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TABLE_H__ +#define __GAL_A11Y_E_TABLE_H__ + +#include +#include +#include + +#define GAL_A11Y_TYPE_E_TABLE (gal_a11y_e_table_get_type ()) +#define GAL_A11Y_E_TABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE, GalA11yETable)) +#define GAL_A11Y_E_TABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE, GalA11yETableClass)) +#define GAL_A11Y_IS_E_TABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE)) +#define GAL_A11Y_IS_E_TABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE)) + +typedef struct _GalA11yETable GalA11yETable; +typedef struct _GalA11yETableClass GalA11yETableClass; +typedef struct _GalA11yETablePrivate GalA11yETablePrivate; + +/* This struct should actually be larger as this isn't what we derive from. + * The GalA11yETablePrivate comes right after the parent class structure. + **/ +struct _GalA11yETable { + GtkAccessible object; +}; + +struct _GalA11yETableClass { + GtkAccessibleClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_table_get_type (void); +AtkObject *gal_a11y_e_table_new (GObject *table); + +void gal_a11y_e_table_init (void); + +#endif /* ! __GAL_A11Y_E_TABLE_H__ */ diff --git a/widgets/table/gal-a11y-e-tree-factory.c b/widgets/table/gal-a11y-e-tree-factory.c new file mode 100644 index 0000000000..8dc06e2936 --- /dev/null +++ b/widgets/table/gal-a11y-e-tree-factory.c @@ -0,0 +1,98 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Yuedong Du + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include + +#include "gal-a11y-e-tree.h" +#include "gal-a11y-e-tree-factory.h" + +#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETreeFactoryClass)) +static AtkObjectFactoryClass *parent_class; +#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY) + +/* Static functions */ + +static GType +gal_a11y_e_tree_factory_get_accessible_type (void) +{ + return GAL_A11Y_TYPE_E_TREE; +} + +static AtkObject* +gal_a11y_e_tree_factory_create_accessible (GObject *obj) +{ + AtkObject *accessible; + + accessible = gal_a11y_e_tree_new (obj); + + return accessible; +} + +static void +gal_a11y_e_tree_factory_class_init (GalA11yETreeFactoryClass *klass) +{ + AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + factory_class->create_accessible = gal_a11y_e_tree_factory_create_accessible; + factory_class->get_accessible_type = gal_a11y_e_tree_factory_get_accessible_type; +} + +static void +gal_a11y_e_tree_factory_init (GalA11yETreeFactory *factory) +{ +} + +/** + * gal_a11y_e_tree_factory_get_type: + * @void: + * + * Registers the &GalA11yETreeFactory class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yETreeFactory class. + **/ +GType +gal_a11y_e_tree_factory_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yETreeFactoryClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gal_a11y_e_tree_factory_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yETreeFactory), + 0, + (GInstanceInitFunc) gal_a11y_e_tree_factory_init, + NULL /* value_tree */ + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yETreeFactory", &info, 0); + } + + return type; +} diff --git a/widgets/table/gal-a11y-e-tree-factory.h b/widgets/table/gal-a11y-e-tree-factory.h new file mode 100644 index 0000000000..3d97c7a3b1 --- /dev/null +++ b/widgets/table/gal-a11y-e-tree-factory.h @@ -0,0 +1,50 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Yuedong Du + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TREE_FACTORY_H__ +#define __GAL_A11Y_E_TREE_FACTORY_H__ + +#include +#include + +#define GAL_A11Y_TYPE_E_TREE_FACTORY (gal_a11y_e_table_factory_get_type ()) +#define GAL_A11Y_E_TREE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TREE_FACTORY, GalA11yETreeFactory)) +#define GAL_A11Y_E_TREE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TREE_FACTORY, GalA11yETreeFactoryClass)) +#define GAL_A11Y_IS_E_TREE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TREE_FACTORY)) +#define GAL_A11Y_IS_E_TREE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TREE_FACTORY)) + +typedef struct _GalA11yETreeFactory GalA11yETreeFactory; +typedef struct _GalA11yETreeFactoryClass GalA11yETreeFactoryClass; + +struct _GalA11yETreeFactory { + AtkObject object; +}; + +struct _GalA11yETreeFactoryClass { + AtkObjectClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_tree_factory_get_type (void); + +#endif /* ! __GAL_A11Y_E_TREE_FACTORY_H__ */ diff --git a/widgets/table/gal-a11y-e-tree.c b/widgets/table/gal-a11y-e-tree.c new file mode 100644 index 0000000000..879b517aab --- /dev/null +++ b/widgets/table/gal-a11y-e-tree.c @@ -0,0 +1,191 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Yuedong Du + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include + +#include "a11y/gal-a11y-util.h" +#include "table/e-table-item.h" +#include "table/e-tree.h" + +#include "gal-a11y-e-table-item.h" +#include "gal-a11y-e-tree.h" +#include "gal-a11y-e-tree-factory.h" + +#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yETreeClass)) +static AtkObjectClass *parent_class; +static GType parent_type; +static gint priv_offset; +#define GET_PRIVATE(object) ((GalA11yETreePrivate *) (((gchar *) object) + priv_offset)) +#define PARENT_TYPE (parent_type) + +struct _GalA11yETreePrivate { + AtkObject *child_item; +}; + +/* Static functions */ + +static void +init_child_item (GalA11yETree *a11y) +{ + GalA11yETreePrivate *priv = GET_PRIVATE (a11y); + ETree *tree = E_TREE (GTK_ACCESSIBLE (a11y)->widget); + ETableItem * eti; + + g_return_if_fail (tree); + eti = e_tree_get_item (tree); + if (priv->child_item == NULL) { + priv->child_item = atk_gobject_accessible_for_object (G_OBJECT (eti)); + } +} + +static AtkObject* +et_ref_accessible_at_point (AtkComponent *component, + gint x, + gint y, + AtkCoordType coord_type) +{ + GalA11yETree *a11y = GAL_A11Y_E_TREE (component); + init_child_item (a11y); + return GET_PRIVATE (a11y)->child_item; +} + +static gint +et_get_n_children (AtkObject *accessible) +{ + return 1; +} + +static AtkObject* +et_ref_child (AtkObject *accessible, + gint i) +{ + GalA11yETree *a11y = GAL_A11Y_E_TREE (accessible); + if (i != 0) + return NULL; + init_child_item (a11y); + g_object_ref (GET_PRIVATE (a11y)->child_item); + return GET_PRIVATE (a11y)->child_item; +} + +static AtkLayer +et_get_layer (AtkComponent *component) +{ + return ATK_LAYER_WIDGET; +} + +static void +et_class_init (GalA11yETreeClass *klass) +{ + AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + atk_object_class->get_n_children = et_get_n_children; + atk_object_class->ref_child = et_ref_child; +} + +static void +et_atk_component_iface_init (AtkComponentIface *iface) +{ + iface->ref_accessible_at_point = et_ref_accessible_at_point; + iface->get_layer = et_get_layer; +} + +static void +et_init (GalA11yETree *a11y) +{ + GalA11yETreePrivate *priv; + + priv = GET_PRIVATE (a11y); + + priv->child_item = NULL; +} + +/** + * gal_a11y_e_tree_get_type: + * @void: + * + * Registers the &GalA11yETree class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yETree class. + **/ +GType +gal_a11y_e_tree_get_type (void) +{ + static GType type = 0; + + if (!type) { + AtkObjectFactory *factory; + + GTypeInfo info = { + sizeof (GalA11yETreeClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) et_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yETree), + 0, + (GInstanceInitFunc) et_init, + NULL /* value_tree */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) et_atk_component_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + factory = atk_registry_get_factory (atk_get_default_registry (), GTK_TYPE_WIDGET); + parent_type = atk_object_factory_get_accessible_type (factory); + + type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yETree", &info, 0, + sizeof (GalA11yETreePrivate), &priv_offset); + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); + } + + return type; +} + +AtkObject * +gal_a11y_e_tree_new (GObject *widget) +{ + GalA11yETree *a11y; + + a11y = g_object_new (gal_a11y_e_tree_get_type (), NULL); + + GTK_ACCESSIBLE (a11y)->widget = GTK_WIDGET (widget); + + return ATK_OBJECT (a11y); +} + +void +gal_a11y_e_tree_init (void) +{ + if (atk_get_root ()) + atk_registry_set_factory_type (atk_get_default_registry (), + E_TREE_TYPE, + gal_a11y_e_tree_factory_get_type ()); + +} + diff --git a/widgets/table/gal-a11y-e-tree.h b/widgets/table/gal-a11y-e-tree.h new file mode 100644 index 0000000000..d2aa8a0d2a --- /dev/null +++ b/widgets/table/gal-a11y-e-tree.h @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Yuedong Du + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TREE_H__ +#define __GAL_A11Y_E_TREE_H__ + +#include +#include +#include + +#define GAL_A11Y_TYPE_E_TREE (gal_a11y_e_tree_get_type ()) +#define GAL_A11Y_E_TREE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TREE, GalA11yETree)) +#define GAL_A11Y_E_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TREE, GalA11yETreeClass)) +#define GAL_A11Y_IS_E_TREE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TREE)) +#define GAL_A11Y_IS_E_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TREE)) + +typedef struct _GalA11yETree GalA11yETree; +typedef struct _GalA11yETreeClass GalA11yETreeClass; +typedef struct _GalA11yETreePrivate GalA11yETreePrivate; + +/* This struct should actually be larger as this isn't what we derive from. + * The GalA11yETablePrivate comes right after the parent class structure. + **/ +struct _GalA11yETree { + GtkAccessible object; +}; + +struct _GalA11yETreeClass { + GtkAccessibleClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_tree_get_type (void); +AtkObject *gal_a11y_e_tree_new (GObject *tree); + +void gal_a11y_e_tree_init (void); + +#endif /* ! __GAL_A11Y_E_TREE_H__ */ diff --git a/widgets/text/Makefile.am b/widgets/text/Makefile.am index e035d8714d..70adbfec39 100644 --- a/widgets/text/Makefile.am +++ b/widgets/text/Makefile.am @@ -14,8 +14,8 @@ libetext_la_SOURCES = \ e-text.c \ e-reflow.c \ e-reflow-model.c \ - a11y/gal-a11y-e-text-factory.c \ - a11y/gal-a11y-e-text.c + gal-a11y-e-text-factory.c \ + gal-a11y-e-text.c libetextincludedir = $(privincludedir)/text @@ -25,8 +25,8 @@ libetextinclude_HEADERS = \ e-text.h \ e-reflow.h \ e-reflow-model.h \ - a11y/gal-a11y-e-text-factory.h \ - a11y/gal-a11y-e-text.h + gal-a11y-e-text-factory.h \ + gal-a11y-e-text.h libetext_la_LDFLAGS = $(NO_UNDEFINED) diff --git a/widgets/text/a11y/gal-a11y-e-text-factory.c b/widgets/text/a11y/gal-a11y-e-text-factory.c deleted file mode 100644 index 2df9241014..0000000000 --- a/widgets/text/a11y/gal-a11y-e-text-factory.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Christopher James Lahey - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include -#include "text/e-text.h" -#include "gal-a11y-e-text-factory.h" -#include "gal-a11y-e-text.h" - -#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETextFactoryClass)) -static AtkObjectFactoryClass *parent_class; -#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY) - -/* Static functions */ - -static GType -gal_a11y_e_text_factory_get_accessible_type (void) -{ - return GAL_A11Y_TYPE_E_TEXT; -} - -static AtkObject* -gal_a11y_e_text_factory_create_accessible (GObject *obj) -{ - AtkObject *atk_object; - - g_return_val_if_fail (E_IS_TEXT (obj), NULL); - - atk_object = g_object_new (GAL_A11Y_TYPE_E_TEXT, NULL); - atk_object_initialize (atk_object, obj); - - return atk_object; -} - -static void -gal_a11y_e_text_factory_class_init (GalA11yETextFactoryClass *klass) -{ - AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass); - - parent_class = g_type_class_ref (PARENT_TYPE); - - factory_class->create_accessible = gal_a11y_e_text_factory_create_accessible; - factory_class->get_accessible_type = gal_a11y_e_text_factory_get_accessible_type; -} - -static void -gal_a11y_e_text_factory_init (GalA11yETextFactory *factory) -{ -} - -/** - * gal_a11y_e_text_factory_get_type: - * @void: - * - * Registers the &GalA11yETextFactory class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &GalA11yETextFactory class. - **/ -GType -gal_a11y_e_text_factory_get_type (void) -{ - static GType type = 0; - - if (!type) { - GTypeInfo info = { - sizeof (GalA11yETextFactoryClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gal_a11y_e_text_factory_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (GalA11yETextFactory), - 0, - (GInstanceInitFunc) gal_a11y_e_text_factory_init, - NULL /* value_text */ - }; - - type = g_type_register_static (PARENT_TYPE, "GalA11yETextFactory", &info, 0); - } - - return type; -} diff --git a/widgets/text/a11y/gal-a11y-e-text-factory.h b/widgets/text/a11y/gal-a11y-e-text-factory.h deleted file mode 100644 index df7638f64f..0000000000 --- a/widgets/text/a11y/gal-a11y-e-text-factory.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Christopher James Lahey - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __GAL_A11Y_E_TEXT_FACTORY_H__ -#define __GAL_A11Y_E_TEXT_FACTORY_H__ - -#include -#include - -#define GAL_A11Y_TYPE_E_TEXT_FACTORY (gal_a11y_e_text_factory_get_type ()) -#define GAL_A11Y_E_TEXT_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TEXT_FACTORY, GalA11yETextFactory)) -#define GAL_A11Y_E_TEXT_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TEXT_FACTORY, GalA11yETextFactoryClass)) -#define GAL_A11Y_IS_E_TEXT_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TEXT_FACTORY)) -#define GAL_A11Y_IS_E_TEXT_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TEXT_FACTORY)) - -typedef struct _GalA11yETextFactory GalA11yETextFactory; -typedef struct _GalA11yETextFactoryClass GalA11yETextFactoryClass; - -struct _GalA11yETextFactory { - AtkObjectFactory object; -}; - -struct _GalA11yETextFactoryClass { - AtkObjectFactoryClass parent_class; -}; - - -/* Standard Glib function */ -GType gal_a11y_e_text_factory_get_type (void); - -#endif /* ! __GAL_A11Y_E_TEXT_FACTORY_H__ */ diff --git a/widgets/text/a11y/gal-a11y-e-text.c b/widgets/text/a11y/gal-a11y-e-text.c deleted file mode 100644 index 99fb4e8a94..0000000000 --- a/widgets/text/a11y/gal-a11y-e-text.c +++ /dev/null @@ -1,1134 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Christopher James Lahey - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include - -#include - -#include - -#include "a11y/gal-a11y-util.h" -#include "text/e-text.h" -#include "text/e-text-model-repos.h" - -#include "gal-a11y-e-text.h" -#include "gal-a11y-e-text-factory.h" - -#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yETextClass)) -static GObjectClass *parent_class; -static AtkComponentIface *component_parent_iface; -static GType parent_type; -static gint priv_offset; -static GQuark quark_accessible_object = 0; -#define GET_PRIVATE(object) ((GalA11yETextPrivate *) (((gchar *) object) + priv_offset)) -#define PARENT_TYPE (parent_type) - -struct _GalA11yETextPrivate { - gint dummy; -}; - -static void -et_dispose (GObject *object) -{ - if (parent_class->dispose) - parent_class->dispose (object); -} - -/* Static functions */ - -static void -et_get_extents (AtkComponent *component, - gint *x, - gint *y, - gint *width, - gint *height, - AtkCoordType coord_type) -{ - EText *item = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (component))); - double real_width; - double real_height; - gint fake_width; - gint fake_height; - - if (component_parent_iface && - component_parent_iface->get_extents) - component_parent_iface->get_extents (component, - x, - y, - &fake_width, - &fake_height, - coord_type); - - g_object_get (item, - "text_width", &real_width, - "text_height", &real_height, - NULL); - - if (width) - *width = real_width; - if (height) - *height = real_height; -} - -static const gchar * -et_get_full_text (AtkText *text) -{ - EText *etext = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text))); - ETextModel *model; - const gchar *full_text; - - g_object_get (etext, "model", &model, NULL); - - full_text = e_text_model_get_text (model); - - return full_text; -} - -static void -et_set_full_text (AtkEditableText *text, - const gchar *full_text) -{ - EText *etext = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text))); - ETextModel *model; - - g_object_get (etext, "model", &model, NULL); - - e_text_model_set_text (model, full_text); -} - -static gchar * -et_get_text (AtkText *text, - gint start_offset, - gint end_offset) -{ - gint start, end, real_start, real_end, len; - const gchar *full_text = et_get_full_text (text); - if (full_text == NULL) - return NULL; - len = g_utf8_strlen (full_text, -1); - - start = MIN (MAX (0, start_offset), len); - end = MIN (MAX (-1, end_offset), len); - - if (end_offset == -1) - end = strlen (full_text); - else - end = g_utf8_offset_to_pointer (full_text, end) - full_text; - - start = g_utf8_offset_to_pointer (full_text, start) - full_text; - - real_start = MIN (start, end); - real_end = MAX (start, end); - - return g_strndup (full_text + real_start, real_end - real_start); -} - -static gboolean -is_a_seperator (gunichar c) -{ - return g_unichar_ispunct(c) || g_unichar_isspace(c); -} - -static gint -find_word_start (const gchar *text, - gint begin_offset, - gint step) -{ - gint offset; - gchar *at_offset; - gunichar current, previous; - gint len; - - offset = begin_offset; - len = g_utf8_strlen (text, -1); - - while (offset > 0 && offset < len) { - at_offset = g_utf8_offset_to_pointer (text, offset); - current = g_utf8_get_char_validated (at_offset, -1); - at_offset = g_utf8_offset_to_pointer (text, offset-1); - previous = g_utf8_get_char_validated (at_offset, -1); - if ((! is_a_seperator (current)) && is_a_seperator (previous)) - break; - offset += step; - } - - return offset; -} - -static gint -find_word_end (const gchar *text, - gint begin_offset, - gint step) -{ - gint offset; - gchar *at_offset; - gunichar current, previous; - gint len; - - offset = begin_offset; - len = g_utf8_strlen (text, -1); - - while (offset > 0 && offset < len) { - at_offset = g_utf8_offset_to_pointer (text, offset); - current = g_utf8_get_char_validated (at_offset, -1); - at_offset = g_utf8_offset_to_pointer (text, offset-1); - previous = g_utf8_get_char_validated (at_offset, -1); - if (is_a_seperator (current) && (! is_a_seperator (previous))) - break; - offset += step; - } - - return offset; -} - -static gint -find_sentence_start (const gchar *text, - gint begin_offset, - gint step) -{ - gint offset, last_word_end, len; - gchar *at_offset; - gunichar ch; - gint i; - - offset = find_word_start (text, begin_offset, step); - len = g_utf8_strlen (text, -1); - - while (offset>0 && offset 0 && offset < len) { - at_offset = g_utf8_offset_to_pointer (text, offset - 1); - previous = g_utf8_get_char_validated (at_offset, -1); - if (previous == '.' || previous == '!' || previous == '?') - break; - offset += step; - } - - return offset; -} - -static gint -find_line_start (const gchar *text, - gint begin_offset, - gint step) -{ - gint offset; - gchar *at_offset; - gunichar previous; - gint len; - - offset = begin_offset; - len = g_utf8_strlen (text, -1); - - while (offset > 0 && offset < len) { - at_offset = g_utf8_offset_to_pointer (text, offset - 1); - previous = g_utf8_get_char_validated (at_offset, -1); - if (previous == '\n' || previous == '\r') - break; - offset += step; - } - - return offset; -} - -static gint -find_line_end (const gchar *text, - gint begin_offset, - gint step) -{ - gint offset; - gchar *at_offset; - gunichar current; - gint len; - - offset = begin_offset; - len = g_utf8_strlen (text, -1); - - while (offset >= 0 && offset < len) { - at_offset = g_utf8_offset_to_pointer (text, offset); - current = g_utf8_get_char_validated (at_offset, -1); - if (current == '\n' || current == '\r') - break; - offset += step; - } - - return offset; -} - -static gchar * -et_get_text_after_offset (AtkText *text, - gint offset, - AtkTextBoundary boundary_type, - gint *start_offset, - gint *end_offset) -{ - gint start, end, len; - const gchar *full_text = et_get_full_text (text); - g_return_val_if_fail (full_text, NULL); - - switch (boundary_type) - { - case ATK_TEXT_BOUNDARY_CHAR: - start = offset + 1; - end = offset + 2; - break; - case ATK_TEXT_BOUNDARY_WORD_START: - start = find_word_start (full_text, offset + 1, 1); - end = find_word_start (full_text, start + 1, 1); - break; - case ATK_TEXT_BOUNDARY_WORD_END: - start = find_word_end (full_text, offset + 1, 1); - end = find_word_end (full_text, start + 1, 1); - break; - case ATK_TEXT_BOUNDARY_SENTENCE_START: - start = find_sentence_start (full_text, offset + 1, 1); - end = find_sentence_start (full_text, start + 1, 1); - break; - case ATK_TEXT_BOUNDARY_SENTENCE_END: - start = find_sentence_end (full_text, offset + 1, 1); - end = find_sentence_end (full_text, start + 1, 1); - break; - case ATK_TEXT_BOUNDARY_LINE_START: - start = find_line_start (full_text, offset + 1, 1); - end = find_line_start (full_text, start + 1, 1); - break; - case ATK_TEXT_BOUNDARY_LINE_END: - start = find_line_end (full_text, offset + 1, 1); - end = find_line_end (full_text, start + 1, 1); - break; - default: - return NULL; - } - - len = g_utf8_strlen (full_text, -1); - if (start_offset) - *start_offset = MIN (MAX (0, start), len); - if (end_offset) - *end_offset = MIN (MAX (0, end), len); - return et_get_text (text, start, end); -} - -static gchar * -et_get_text_at_offset (AtkText *text, - gint offset, - AtkTextBoundary boundary_type, - gint *start_offset, - gint *end_offset) -{ - gint start, end, len; - const gchar *full_text = et_get_full_text (text); - g_return_val_if_fail (full_text, NULL); - - switch (boundary_type) - { - case ATK_TEXT_BOUNDARY_CHAR: - start = offset; - end = offset + 1; - break; - case ATK_TEXT_BOUNDARY_WORD_START: - start = find_word_start (full_text, offset - 1, -1); - end = find_word_start (full_text, offset, 1); - break; - case ATK_TEXT_BOUNDARY_WORD_END: - start = find_word_end (full_text, offset, -1); - end = find_word_end (full_text, offset + 1, 1); - break; - case ATK_TEXT_BOUNDARY_SENTENCE_START: - start = find_sentence_start (full_text, offset - 1, -1); - end = find_sentence_start (full_text, offset, 1); - break; - case ATK_TEXT_BOUNDARY_SENTENCE_END: - start = find_sentence_end (full_text, offset, -1); - end = find_sentence_end (full_text, offset + 1, 1); - break; - case ATK_TEXT_BOUNDARY_LINE_START: - start = find_line_start (full_text, offset - 1, -1); - end = find_line_start (full_text, offset, 1); - break; - case ATK_TEXT_BOUNDARY_LINE_END: - start = find_line_end (full_text, offset, -1); - end = find_line_end (full_text, offset + 1, 1); - break; - default: - return NULL; - } - - len = g_utf8_strlen (full_text, -1); - if (start_offset) - *start_offset = MIN (MAX (0, start), len); - if (end_offset) - *end_offset = MIN (MAX (0, end), len); - return et_get_text (text, start, end); -} - -static gunichar -et_get_character_at_offset (AtkText *text, - gint offset) -{ - const gchar *full_text = et_get_full_text (text); - gchar *at_offset; - - at_offset = g_utf8_offset_to_pointer (full_text, offset); - return g_utf8_get_char_validated (at_offset, -1); -} - - -static gchar * -et_get_text_before_offset (AtkText *text, - gint offset, - AtkTextBoundary boundary_type, - gint *start_offset, - gint *end_offset) -{ - gint start, end, len; - const gchar *full_text = et_get_full_text (text); - g_return_val_if_fail (full_text, NULL); - - switch (boundary_type) - { - case ATK_TEXT_BOUNDARY_CHAR: - start = offset - 1; - end = offset; - break; - case ATK_TEXT_BOUNDARY_WORD_START: - end = find_word_start (full_text, offset - 1, -1); - start = find_word_start (full_text, end - 1, -1); - break; - case ATK_TEXT_BOUNDARY_WORD_END: - end = find_word_end (full_text, offset, -1); - start = find_word_end (full_text, end - 1, -1); - break; - case ATK_TEXT_BOUNDARY_SENTENCE_START: - end = find_sentence_start (full_text, offset, -1); - start = find_sentence_start (full_text, end - 1, -1); - break; - case ATK_TEXT_BOUNDARY_SENTENCE_END: - end = find_sentence_end (full_text, offset, -1); - start = find_sentence_end (full_text, end - 1, -1); - break; - case ATK_TEXT_BOUNDARY_LINE_START: - end = find_line_start (full_text, offset, -1); - start = find_line_start (full_text, end - 1, -1); - break; - case ATK_TEXT_BOUNDARY_LINE_END: - end = find_line_end (full_text, offset, -1); - start = find_line_end (full_text, end - 1, -1); - break; - default: - return NULL; - } - - len = g_utf8_strlen (full_text, -1); - if (start_offset) - *start_offset = MIN (MAX (0, start), len); - if (end_offset) - *end_offset = MIN (MAX (0, end), len); - return et_get_text (text, start, end); -} - -static gint -et_get_caret_offset (AtkText *text) -{ - GObject *obj; - EText *etext; - gint offset; - - g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE(text), -1); - obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); - if (obj == NULL) - return -1; - - g_return_val_if_fail (E_IS_TEXT (obj), -1); - etext = E_TEXT (obj); - - g_object_get (etext, "cursor_pos", &offset, NULL); - return offset; -} - - -static AtkAttributeSet* -et_get_run_attributes (AtkText *text, - gint offset, - gint *start_offset, - gint *end_offset) -{ - /* Unimplemented */ - return NULL; -} - - -static AtkAttributeSet* -et_get_default_attributes (AtkText *text) -{ - /* Unimplemented */ - return NULL; -} - - -static void -et_get_character_extents (AtkText *text, - gint offset, - gint *x, - gint *y, - gint *width, - gint *height, - AtkCoordType coords) -{ - GObject *obj; - EText *etext; - GnomeCanvas *canvas; - gint x_widget, y_widget, x_window, y_window; - GdkWindow *window; - GtkWidget *widget; - PangoRectangle pango_pos; - - g_return_if_fail (ATK_IS_GOBJECT_ACCESSIBLE(text)); - obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); - if (obj == NULL) - return; - g_return_if_fail (E_IS_TEXT (obj)); - etext = E_TEXT(obj); - canvas = GNOME_CANVAS_ITEM(etext)->canvas; - widget = GTK_WIDGET(canvas); - window = widget->window; - gdk_window_get_origin (window, &x_widget, &y_widget); - - pango_layout_index_to_pos (etext->layout, offset, &pango_pos); - pango_pos.x = PANGO_PIXELS (pango_pos.x); - pango_pos.y = PANGO_PIXELS (pango_pos.y); - pango_pos.width = (pango_pos.width + PANGO_SCALE / 2) / PANGO_SCALE; - pango_pos.height = (pango_pos.height + PANGO_SCALE / 2) / PANGO_SCALE; - - *x = pango_pos.x + x_widget; - *y = pango_pos.y + y_widget; - - *width = pango_pos.width; - *height = pango_pos.height; - - if (etext->draw_borders) { - *x += 3; /*BORDER_INDENT;*/ - *y += 3; /*BORDER_INDENT;*/ - } - - *x += etext->xofs; - *y += etext->yofs; - - if (etext->editing) { - *x -= etext->xofs_edit; - *y -= etext->yofs_edit; - } - - *x += etext->cx; - *y += etext->cy; - - if (coords == ATK_XY_WINDOW) { - window = gdk_window_get_toplevel (window); - gdk_window_get_origin (window, &x_window, &y_window); - *x -= x_window; - *y -= y_window; - } - else if (coords == ATK_XY_SCREEN) { - } - else { - *x = 0; - *y = 0; - *height = 0; - *width = 0; - } -} - - -static gint -et_get_character_count (AtkText *text) -{ - const gchar *full_text = et_get_full_text (text); - - return g_utf8_strlen (full_text, -1); -} - - -static gint -et_get_offset_at_point (AtkText *text, - gint x, - gint y, - AtkCoordType coords) -{ - GObject *obj; - EText *etext; - GnomeCanvas *canvas; - gint x_widget, y_widget, x_window, y_window; - GdkWindow *window; - GtkWidget *widget; - gint index; - gint trailing; - - g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE(text), -1); - obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); - if (obj == NULL) - return -1; - g_return_val_if_fail (E_IS_TEXT (obj), -1); - etext = E_TEXT(obj); - canvas = GNOME_CANVAS_ITEM(etext)->canvas; - widget = GTK_WIDGET(canvas); - window = widget->window; - gdk_window_get_origin (window, &x_widget, &y_widget); - - if (coords == ATK_XY_SCREEN) { - x = x - x_widget; - y = y - y_widget; - } - else if (coords == ATK_XY_WINDOW) { - window = gdk_window_get_toplevel (window); - gdk_window_get_origin (window, &x_window, &y_window); - x = x - x_widget + x_window; - y = y - y_widget + y_window; - } - else - return -1; - - if (etext->draw_borders) { - x -= 3; /*BORDER_INDENT;*/ - y -= 3; /*BORDER_INDENT;*/ - } - - x -= etext->xofs; - y -= etext->yofs; - - if (etext->editing) { - x += etext->xofs_edit; - y += etext->yofs_edit; - } - - x -= etext->cx; - y -= etext->cy; - - pango_layout_xy_to_index (etext->layout, - x * PANGO_SCALE - PANGO_SCALE / 2, - y * PANGO_SCALE - PANGO_SCALE / 2, - &index, - &trailing); - - return g_utf8_pointer_to_offset (etext->text, etext->text + index + trailing); -} - - -static gint -et_get_n_selections (AtkText *text) -{ - EText *etext = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text))); - if (etext->selection_start != - etext->selection_end) - return 1; - return 0; -} - - -static gchar * -et_get_selection (AtkText *text, - gint selection_num, - gint *start_offset, - gint *end_offset) -{ - gint start, end, real_start, real_end, len; - EText *etext; - if (selection_num == 0) { - const gchar *full_text = et_get_full_text (text); - if (full_text == NULL) - return NULL; - len = g_utf8_strlen (full_text, -1); - etext = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text))); - start = MIN (etext->selection_start, etext->selection_end); - end = MAX (etext->selection_start, etext->selection_end); - start = MIN (MAX (0, start), len); - end = MIN (MAX (0, end), len); - if (start != end) { - if (start_offset) - *start_offset = start; - if (end_offset) - *end_offset = end; - real_start = g_utf8_offset_to_pointer (full_text, start) - full_text; - real_end = g_utf8_offset_to_pointer (full_text, end) - full_text; - return g_strndup (full_text + real_start, real_end - real_start); - } - } - - return NULL; -} - - -static gboolean -et_add_selection (AtkText *text, - gint start_offset, - gint end_offset) -{ - GObject *obj; - EText *etext; - - g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text), FALSE); - obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); - if (obj == NULL) - return FALSE; - g_return_val_if_fail (E_IS_TEXT (obj), FALSE); - etext = E_TEXT (obj); - - g_return_val_if_fail (start_offset >= 0, FALSE); - g_return_val_if_fail (start_offset >= -1, FALSE); - if (end_offset == -1) - end_offset = et_get_character_count (text); - - if (start_offset != end_offset) { - gint real_start, real_end; - real_start = MIN (start_offset, end_offset); - real_end = MAX (start_offset, end_offset); - etext->selection_start = real_start; - etext->selection_end = real_end; - - gnome_canvas_item_grab_focus (GNOME_CANVAS_ITEM (etext)); - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (etext)); - - g_signal_emit_by_name (ATK_OBJECT (text), "text_selection_changed"); - - return TRUE; - } - - return FALSE; -} - - -static gboolean -et_remove_selection (AtkText *text, - gint selection_num) -{ - GObject *obj; - EText *etext; - - g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text), FALSE); - obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); - if (obj == NULL) - return FALSE; - g_return_val_if_fail (E_IS_TEXT (obj), FALSE); - etext = E_TEXT (obj); - - if (selection_num == 0 - && etext->selection_start != etext->selection_end) { - etext->selection_end = etext->selection_start; - g_signal_emit_by_name (ATK_OBJECT(text), "text_selection_changed"); - return TRUE; - } - - return FALSE; -} - - -static gboolean -et_set_selection (AtkText *text, - gint selection_num, - gint start_offset, - gint end_offset) -{ - GObject *obj; - - g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text), FALSE); - obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); - if (obj == NULL) - return FALSE; - g_return_val_if_fail (E_IS_TEXT (obj), FALSE); - if (selection_num == 0) - return et_add_selection (text, start_offset, end_offset); - return FALSE; -} - - -static gboolean -et_set_caret_offset (AtkText *text, - gint offset) -{ - GObject *obj; - EText *etext; - - g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text), FALSE); - obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); - if (obj == NULL) - return FALSE; - - g_return_val_if_fail (E_IS_TEXT (obj), FALSE); - etext = E_TEXT (obj); - - if (offset < -1) - return FALSE; - else { - ETextEventProcessorCommand command; - - if (offset == -1) - offset = et_get_character_count (text); - - command.action = E_TEP_MOVE; - command.position = E_TEP_VALUE; - command.value = offset; - command.time = GDK_CURRENT_TIME; - g_signal_emit_by_name (etext->tep, "command", &command); - return TRUE; - } -} - -static gboolean -et_set_run_attributes (AtkEditableText *text, - AtkAttributeSet *attrib_set, - gint start_offset, - gint end_offset) -{ - /* Unimplemented */ - return FALSE; -} - -static void -et_set_text_contents (AtkEditableText *text, - const gchar *string) -{ - et_set_full_text (text, string); -} - -static void -et_insert_text (AtkEditableText *text, - const gchar *string, - gint length, - gint *position) -{ - /* Utf8 unimplemented */ - gchar *result; - - const gchar *full_text = et_get_full_text (ATK_TEXT (text)); - if (full_text == NULL) - return; - - result = g_strdup_printf ("%.*s%.*s%s", *position, full_text, length, string, full_text + *position); - - et_set_full_text (text, result); - - *position += length; - - g_free (result); -} - -static void -et_copy_text (AtkEditableText *text, - gint start_pos, - gint end_pos) -{ - GObject *obj; - EText *etext; - - g_return_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text)); - obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); - if (obj == NULL) - return; - - g_return_if_fail (E_IS_TEXT (obj)); - etext = E_TEXT (obj); - - if (start_pos != end_pos) { - etext->selection_start = start_pos; - etext->selection_end = end_pos; - e_text_copy_clipboard (etext); - } -} - -static void -et_delete_text (AtkEditableText *text, - gint start_pos, - gint end_pos) -{ - GObject *obj; - EText *etext; - - g_return_if_fail (ATK_IS_GOBJECT_ACCESSIBLE(text)); - obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); - if (obj == NULL) - return; - - g_return_if_fail (E_IS_TEXT (obj)); - etext = E_TEXT (obj); - - etext->selection_start = start_pos; - etext->selection_end = end_pos; - - e_text_delete_selection (etext); -} - -static void -et_cut_text (AtkEditableText *text, - gint start_pos, - gint end_pos) -{ - et_copy_text (text, start_pos, end_pos); - et_delete_text (text, start_pos, end_pos); -} - -static void -et_paste_text (AtkEditableText *text, - gint position) -{ - GObject *obj; - EText *etext; - - g_return_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text)); - obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); - if (obj == NULL) - return; - - g_return_if_fail (E_IS_TEXT (obj)); - etext = E_TEXT (obj); - - g_object_set (etext, "cursor_pos", position, NULL); - e_text_paste_clipboard (etext); -} - -static void -et_atk_component_iface_init (AtkComponentIface *iface) -{ - iface->get_extents = et_get_extents; -} - -static void -et_atk_text_iface_init (AtkTextIface *iface) -{ - iface->get_text = et_get_text; - iface->get_text_after_offset = et_get_text_after_offset; - iface->get_text_at_offset = et_get_text_at_offset; - iface->get_character_at_offset = et_get_character_at_offset; - iface->get_text_before_offset = et_get_text_before_offset; - iface->get_caret_offset = et_get_caret_offset; - iface->get_run_attributes = et_get_run_attributes; - iface->get_default_attributes = et_get_default_attributes; - iface->get_character_extents = et_get_character_extents; - iface->get_character_count = et_get_character_count; - iface->get_offset_at_point = et_get_offset_at_point; - iface->get_n_selections = et_get_n_selections; - iface->get_selection = et_get_selection; - iface->add_selection = et_add_selection; - iface->remove_selection = et_remove_selection; - iface->set_selection = et_set_selection; - iface->set_caret_offset = et_set_caret_offset; -} - -static void -et_atk_editable_text_iface_init (AtkEditableTextIface *iface) -{ - iface->set_run_attributes = et_set_run_attributes; - iface->set_text_contents = et_set_text_contents; - iface->insert_text = et_insert_text; - iface->copy_text = et_copy_text; - iface->cut_text = et_cut_text; - iface->delete_text = et_delete_text; - iface->paste_text = et_paste_text; -} - -static void -_et_reposition_cb (ETextModel *model, - ETextModelReposFn fn, - gpointer repos_data, - gpointer user_data) -{ - AtkObject *accessible; - AtkText *text; - - accessible = ATK_OBJECT (user_data); - text = ATK_TEXT (accessible); - - if (fn == e_repos_delete_shift) { - EReposDeleteShift *info = (EReposDeleteShift *) repos_data; - g_signal_emit_by_name (text, "text-changed::delete", info->pos, info->len); - } - else if (fn == e_repos_insert_shift) { - EReposInsertShift *info = (EReposInsertShift *) repos_data; - g_signal_emit_by_name (text, "text-changed::insert", info->pos, info->len); - } -} - -static void -_et_command_cb (ETextEventProcessor *tep, - ETextEventProcessorCommand *command, - gpointer user_data) -{ - AtkObject *accessible; - AtkText *text; - - accessible = ATK_OBJECT (user_data); - text = ATK_TEXT (accessible); - - switch (command->action) { - case E_TEP_MOVE: - g_signal_emit_by_name (text, "text-caret-moved", et_get_caret_offset (text)); - break; - case E_TEP_SELECT: - g_signal_emit_by_name (text, "text-selection-changed"); - break; - default: - break; - } -} - -static void -et_real_initialize (AtkObject *obj, - gpointer data) -{ - EText *etext; - - ATK_OBJECT_CLASS (parent_class)->initialize (obj, data); - - g_return_if_fail (GAL_A11Y_IS_E_TEXT (obj)); - g_return_if_fail (E_IS_TEXT (data)); - - etext = E_TEXT (data); - - /* Set up signal callbacks */ - g_signal_connect (etext->model, "reposition", - G_CALLBACK (_et_reposition_cb), obj); - - if (etext->tep) - g_signal_connect_after (etext->tep, "command", - (GCallback) _et_command_cb, obj); - - obj->role = ATK_ROLE_TEXT; -} - -static void -et_class_init (GalA11yETextClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass); - - quark_accessible_object = g_quark_from_static_string ("gtk-accessible-object"); - parent_class = g_type_class_ref (PARENT_TYPE); - component_parent_iface = g_type_interface_peek(parent_class, ATK_TYPE_COMPONENT); - object_class->dispose = et_dispose; - atk_class->initialize = et_real_initialize; -} - -static void -et_init (GalA11yEText *a11y) -{ -#if 0 - GalA11yETextPrivate *priv; - - priv = GET_PRIVATE (a11y); -#endif -} - -/** - * gal_a11y_e_text_get_type: - * @void: - * - * Registers the &GalA11yEText class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &GalA11yEText class. - **/ -GType -gal_a11y_e_text_get_type (void) -{ - static GType type = 0; - - if (!type) { - AtkObjectFactory *factory; - - GTypeInfo info = { - sizeof (GalA11yETextClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) et_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (GalA11yEText), - 0, - (GInstanceInitFunc) et_init, - NULL /* value_text */ - }; - - static const GInterfaceInfo atk_component_info = { - (GInterfaceInitFunc) et_atk_component_iface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - static const GInterfaceInfo atk_text_info = { - (GInterfaceInitFunc) et_atk_text_iface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - static const GInterfaceInfo atk_editable_text_info = { - (GInterfaceInitFunc) et_atk_editable_text_iface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - - factory = atk_registry_get_factory (atk_get_default_registry (), GNOME_TYPE_CANVAS_ITEM); - parent_type = atk_object_factory_get_accessible_type (factory); - - type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yEText", &info, 0, - sizeof (GalA11yETextPrivate), &priv_offset); - - g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); - g_type_add_interface_static (type, ATK_TYPE_TEXT, &atk_text_info); - g_type_add_interface_static (type, ATK_TYPE_EDITABLE_TEXT, &atk_editable_text_info); - } - - return type; -} - -void -gal_a11y_e_text_init (void) -{ - if (atk_get_root ()) - atk_registry_set_factory_type (atk_get_default_registry (), - E_TYPE_TEXT, - gal_a11y_e_text_factory_get_type ()); - -} - diff --git a/widgets/text/a11y/gal-a11y-e-text.h b/widgets/text/a11y/gal-a11y-e-text.h deleted file mode 100644 index 6a5bb80de0..0000000000 --- a/widgets/text/a11y/gal-a11y-e-text.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * - * Authors: - * Christopher James Lahey - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __GAL_A11Y_E_TEXT_H__ -#define __GAL_A11Y_E_TEXT_H__ - -#include -#include
- -#define GAL_A11Y_TYPE_E_TEXT (gal_a11y_e_text_get_type ()) -#define GAL_A11Y_E_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TEXT, GalA11yEText)) -#define GAL_A11Y_E_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TEXT, GalA11yETextClass)) -#define GAL_A11Y_IS_E_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TEXT)) -#define GAL_A11Y_IS_E_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TEXT)) - -typedef struct _GalA11yEText GalA11yEText; -typedef struct _GalA11yETextClass GalA11yETextClass; -typedef struct _GalA11yETextPrivate GalA11yETextPrivate; - -/* This struct should actually be larger as this isn't what we derive from. - * The GalA11yETextPrivate comes right after the parent class structure. - **/ -struct _GalA11yEText { - AtkObject object; -}; - -struct _GalA11yETextClass { - AtkObject parent_class; -}; - - -/* Standard Glib function */ -GType gal_a11y_e_text_get_type (void); - -void gal_a11y_e_text_init (void); - -#endif /* ! __GAL_A11Y_E_TEXT_H__ */ diff --git a/widgets/text/e-text.c b/widgets/text/e-text.c index f6371aa551..7c542d8f5f 100644 --- a/widgets/text/e-text.c +++ b/widgets/text/e-text.c @@ -46,7 +46,7 @@ #include #include -#include "a11y/gal-a11y-e-text.h" +#include "gal-a11y-e-text.h" #include "misc/e-canvas.h" #include "misc/e-canvas-utils.h" #include "e-util/e-unicode.h" diff --git a/widgets/text/gal-a11y-e-text-factory.c b/widgets/text/gal-a11y-e-text-factory.c new file mode 100644 index 0000000000..2df9241014 --- /dev/null +++ b/widgets/text/gal-a11y-e-text-factory.c @@ -0,0 +1,101 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Christopher James Lahey + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include +#include "text/e-text.h" +#include "gal-a11y-e-text-factory.h" +#include "gal-a11y-e-text.h" + +#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETextFactoryClass)) +static AtkObjectFactoryClass *parent_class; +#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY) + +/* Static functions */ + +static GType +gal_a11y_e_text_factory_get_accessible_type (void) +{ + return GAL_A11Y_TYPE_E_TEXT; +} + +static AtkObject* +gal_a11y_e_text_factory_create_accessible (GObject *obj) +{ + AtkObject *atk_object; + + g_return_val_if_fail (E_IS_TEXT (obj), NULL); + + atk_object = g_object_new (GAL_A11Y_TYPE_E_TEXT, NULL); + atk_object_initialize (atk_object, obj); + + return atk_object; +} + +static void +gal_a11y_e_text_factory_class_init (GalA11yETextFactoryClass *klass) +{ + AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + factory_class->create_accessible = gal_a11y_e_text_factory_create_accessible; + factory_class->get_accessible_type = gal_a11y_e_text_factory_get_accessible_type; +} + +static void +gal_a11y_e_text_factory_init (GalA11yETextFactory *factory) +{ +} + +/** + * gal_a11y_e_text_factory_get_type: + * @void: + * + * Registers the &GalA11yETextFactory class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yETextFactory class. + **/ +GType +gal_a11y_e_text_factory_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yETextFactoryClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gal_a11y_e_text_factory_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yETextFactory), + 0, + (GInstanceInitFunc) gal_a11y_e_text_factory_init, + NULL /* value_text */ + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yETextFactory", &info, 0); + } + + return type; +} diff --git a/widgets/text/gal-a11y-e-text-factory.h b/widgets/text/gal-a11y-e-text-factory.h new file mode 100644 index 0000000000..df7638f64f --- /dev/null +++ b/widgets/text/gal-a11y-e-text-factory.h @@ -0,0 +1,50 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Christopher James Lahey + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TEXT_FACTORY_H__ +#define __GAL_A11Y_E_TEXT_FACTORY_H__ + +#include +#include + +#define GAL_A11Y_TYPE_E_TEXT_FACTORY (gal_a11y_e_text_factory_get_type ()) +#define GAL_A11Y_E_TEXT_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TEXT_FACTORY, GalA11yETextFactory)) +#define GAL_A11Y_E_TEXT_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TEXT_FACTORY, GalA11yETextFactoryClass)) +#define GAL_A11Y_IS_E_TEXT_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TEXT_FACTORY)) +#define GAL_A11Y_IS_E_TEXT_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TEXT_FACTORY)) + +typedef struct _GalA11yETextFactory GalA11yETextFactory; +typedef struct _GalA11yETextFactoryClass GalA11yETextFactoryClass; + +struct _GalA11yETextFactory { + AtkObjectFactory object; +}; + +struct _GalA11yETextFactoryClass { + AtkObjectFactoryClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_text_factory_get_type (void); + +#endif /* ! __GAL_A11Y_E_TEXT_FACTORY_H__ */ diff --git a/widgets/text/gal-a11y-e-text.c b/widgets/text/gal-a11y-e-text.c new file mode 100644 index 0000000000..99fb4e8a94 --- /dev/null +++ b/widgets/text/gal-a11y-e-text.c @@ -0,0 +1,1134 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Christopher James Lahey + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include + +#include + +#include + +#include "a11y/gal-a11y-util.h" +#include "text/e-text.h" +#include "text/e-text-model-repos.h" + +#include "gal-a11y-e-text.h" +#include "gal-a11y-e-text-factory.h" + +#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yETextClass)) +static GObjectClass *parent_class; +static AtkComponentIface *component_parent_iface; +static GType parent_type; +static gint priv_offset; +static GQuark quark_accessible_object = 0; +#define GET_PRIVATE(object) ((GalA11yETextPrivate *) (((gchar *) object) + priv_offset)) +#define PARENT_TYPE (parent_type) + +struct _GalA11yETextPrivate { + gint dummy; +}; + +static void +et_dispose (GObject *object) +{ + if (parent_class->dispose) + parent_class->dispose (object); +} + +/* Static functions */ + +static void +et_get_extents (AtkComponent *component, + gint *x, + gint *y, + gint *width, + gint *height, + AtkCoordType coord_type) +{ + EText *item = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (component))); + double real_width; + double real_height; + gint fake_width; + gint fake_height; + + if (component_parent_iface && + component_parent_iface->get_extents) + component_parent_iface->get_extents (component, + x, + y, + &fake_width, + &fake_height, + coord_type); + + g_object_get (item, + "text_width", &real_width, + "text_height", &real_height, + NULL); + + if (width) + *width = real_width; + if (height) + *height = real_height; +} + +static const gchar * +et_get_full_text (AtkText *text) +{ + EText *etext = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text))); + ETextModel *model; + const gchar *full_text; + + g_object_get (etext, "model", &model, NULL); + + full_text = e_text_model_get_text (model); + + return full_text; +} + +static void +et_set_full_text (AtkEditableText *text, + const gchar *full_text) +{ + EText *etext = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text))); + ETextModel *model; + + g_object_get (etext, "model", &model, NULL); + + e_text_model_set_text (model, full_text); +} + +static gchar * +et_get_text (AtkText *text, + gint start_offset, + gint end_offset) +{ + gint start, end, real_start, real_end, len; + const gchar *full_text = et_get_full_text (text); + if (full_text == NULL) + return NULL; + len = g_utf8_strlen (full_text, -1); + + start = MIN (MAX (0, start_offset), len); + end = MIN (MAX (-1, end_offset), len); + + if (end_offset == -1) + end = strlen (full_text); + else + end = g_utf8_offset_to_pointer (full_text, end) - full_text; + + start = g_utf8_offset_to_pointer (full_text, start) - full_text; + + real_start = MIN (start, end); + real_end = MAX (start, end); + + return g_strndup (full_text + real_start, real_end - real_start); +} + +static gboolean +is_a_seperator (gunichar c) +{ + return g_unichar_ispunct(c) || g_unichar_isspace(c); +} + +static gint +find_word_start (const gchar *text, + gint begin_offset, + gint step) +{ + gint offset; + gchar *at_offset; + gunichar current, previous; + gint len; + + offset = begin_offset; + len = g_utf8_strlen (text, -1); + + while (offset > 0 && offset < len) { + at_offset = g_utf8_offset_to_pointer (text, offset); + current = g_utf8_get_char_validated (at_offset, -1); + at_offset = g_utf8_offset_to_pointer (text, offset-1); + previous = g_utf8_get_char_validated (at_offset, -1); + if ((! is_a_seperator (current)) && is_a_seperator (previous)) + break; + offset += step; + } + + return offset; +} + +static gint +find_word_end (const gchar *text, + gint begin_offset, + gint step) +{ + gint offset; + gchar *at_offset; + gunichar current, previous; + gint len; + + offset = begin_offset; + len = g_utf8_strlen (text, -1); + + while (offset > 0 && offset < len) { + at_offset = g_utf8_offset_to_pointer (text, offset); + current = g_utf8_get_char_validated (at_offset, -1); + at_offset = g_utf8_offset_to_pointer (text, offset-1); + previous = g_utf8_get_char_validated (at_offset, -1); + if (is_a_seperator (current) && (! is_a_seperator (previous))) + break; + offset += step; + } + + return offset; +} + +static gint +find_sentence_start (const gchar *text, + gint begin_offset, + gint step) +{ + gint offset, last_word_end, len; + gchar *at_offset; + gunichar ch; + gint i; + + offset = find_word_start (text, begin_offset, step); + len = g_utf8_strlen (text, -1); + + while (offset>0 && offset 0 && offset < len) { + at_offset = g_utf8_offset_to_pointer (text, offset - 1); + previous = g_utf8_get_char_validated (at_offset, -1); + if (previous == '.' || previous == '!' || previous == '?') + break; + offset += step; + } + + return offset; +} + +static gint +find_line_start (const gchar *text, + gint begin_offset, + gint step) +{ + gint offset; + gchar *at_offset; + gunichar previous; + gint len; + + offset = begin_offset; + len = g_utf8_strlen (text, -1); + + while (offset > 0 && offset < len) { + at_offset = g_utf8_offset_to_pointer (text, offset - 1); + previous = g_utf8_get_char_validated (at_offset, -1); + if (previous == '\n' || previous == '\r') + break; + offset += step; + } + + return offset; +} + +static gint +find_line_end (const gchar *text, + gint begin_offset, + gint step) +{ + gint offset; + gchar *at_offset; + gunichar current; + gint len; + + offset = begin_offset; + len = g_utf8_strlen (text, -1); + + while (offset >= 0 && offset < len) { + at_offset = g_utf8_offset_to_pointer (text, offset); + current = g_utf8_get_char_validated (at_offset, -1); + if (current == '\n' || current == '\r') + break; + offset += step; + } + + return offset; +} + +static gchar * +et_get_text_after_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset) +{ + gint start, end, len; + const gchar *full_text = et_get_full_text (text); + g_return_val_if_fail (full_text, NULL); + + switch (boundary_type) + { + case ATK_TEXT_BOUNDARY_CHAR: + start = offset + 1; + end = offset + 2; + break; + case ATK_TEXT_BOUNDARY_WORD_START: + start = find_word_start (full_text, offset + 1, 1); + end = find_word_start (full_text, start + 1, 1); + break; + case ATK_TEXT_BOUNDARY_WORD_END: + start = find_word_end (full_text, offset + 1, 1); + end = find_word_end (full_text, start + 1, 1); + break; + case ATK_TEXT_BOUNDARY_SENTENCE_START: + start = find_sentence_start (full_text, offset + 1, 1); + end = find_sentence_start (full_text, start + 1, 1); + break; + case ATK_TEXT_BOUNDARY_SENTENCE_END: + start = find_sentence_end (full_text, offset + 1, 1); + end = find_sentence_end (full_text, start + 1, 1); + break; + case ATK_TEXT_BOUNDARY_LINE_START: + start = find_line_start (full_text, offset + 1, 1); + end = find_line_start (full_text, start + 1, 1); + break; + case ATK_TEXT_BOUNDARY_LINE_END: + start = find_line_end (full_text, offset + 1, 1); + end = find_line_end (full_text, start + 1, 1); + break; + default: + return NULL; + } + + len = g_utf8_strlen (full_text, -1); + if (start_offset) + *start_offset = MIN (MAX (0, start), len); + if (end_offset) + *end_offset = MIN (MAX (0, end), len); + return et_get_text (text, start, end); +} + +static gchar * +et_get_text_at_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset) +{ + gint start, end, len; + const gchar *full_text = et_get_full_text (text); + g_return_val_if_fail (full_text, NULL); + + switch (boundary_type) + { + case ATK_TEXT_BOUNDARY_CHAR: + start = offset; + end = offset + 1; + break; + case ATK_TEXT_BOUNDARY_WORD_START: + start = find_word_start (full_text, offset - 1, -1); + end = find_word_start (full_text, offset, 1); + break; + case ATK_TEXT_BOUNDARY_WORD_END: + start = find_word_end (full_text, offset, -1); + end = find_word_end (full_text, offset + 1, 1); + break; + case ATK_TEXT_BOUNDARY_SENTENCE_START: + start = find_sentence_start (full_text, offset - 1, -1); + end = find_sentence_start (full_text, offset, 1); + break; + case ATK_TEXT_BOUNDARY_SENTENCE_END: + start = find_sentence_end (full_text, offset, -1); + end = find_sentence_end (full_text, offset + 1, 1); + break; + case ATK_TEXT_BOUNDARY_LINE_START: + start = find_line_start (full_text, offset - 1, -1); + end = find_line_start (full_text, offset, 1); + break; + case ATK_TEXT_BOUNDARY_LINE_END: + start = find_line_end (full_text, offset, -1); + end = find_line_end (full_text, offset + 1, 1); + break; + default: + return NULL; + } + + len = g_utf8_strlen (full_text, -1); + if (start_offset) + *start_offset = MIN (MAX (0, start), len); + if (end_offset) + *end_offset = MIN (MAX (0, end), len); + return et_get_text (text, start, end); +} + +static gunichar +et_get_character_at_offset (AtkText *text, + gint offset) +{ + const gchar *full_text = et_get_full_text (text); + gchar *at_offset; + + at_offset = g_utf8_offset_to_pointer (full_text, offset); + return g_utf8_get_char_validated (at_offset, -1); +} + + +static gchar * +et_get_text_before_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset) +{ + gint start, end, len; + const gchar *full_text = et_get_full_text (text); + g_return_val_if_fail (full_text, NULL); + + switch (boundary_type) + { + case ATK_TEXT_BOUNDARY_CHAR: + start = offset - 1; + end = offset; + break; + case ATK_TEXT_BOUNDARY_WORD_START: + end = find_word_start (full_text, offset - 1, -1); + start = find_word_start (full_text, end - 1, -1); + break; + case ATK_TEXT_BOUNDARY_WORD_END: + end = find_word_end (full_text, offset, -1); + start = find_word_end (full_text, end - 1, -1); + break; + case ATK_TEXT_BOUNDARY_SENTENCE_START: + end = find_sentence_start (full_text, offset, -1); + start = find_sentence_start (full_text, end - 1, -1); + break; + case ATK_TEXT_BOUNDARY_SENTENCE_END: + end = find_sentence_end (full_text, offset, -1); + start = find_sentence_end (full_text, end - 1, -1); + break; + case ATK_TEXT_BOUNDARY_LINE_START: + end = find_line_start (full_text, offset, -1); + start = find_line_start (full_text, end - 1, -1); + break; + case ATK_TEXT_BOUNDARY_LINE_END: + end = find_line_end (full_text, offset, -1); + start = find_line_end (full_text, end - 1, -1); + break; + default: + return NULL; + } + + len = g_utf8_strlen (full_text, -1); + if (start_offset) + *start_offset = MIN (MAX (0, start), len); + if (end_offset) + *end_offset = MIN (MAX (0, end), len); + return et_get_text (text, start, end); +} + +static gint +et_get_caret_offset (AtkText *text) +{ + GObject *obj; + EText *etext; + gint offset; + + g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE(text), -1); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return -1; + + g_return_val_if_fail (E_IS_TEXT (obj), -1); + etext = E_TEXT (obj); + + g_object_get (etext, "cursor_pos", &offset, NULL); + return offset; +} + + +static AtkAttributeSet* +et_get_run_attributes (AtkText *text, + gint offset, + gint *start_offset, + gint *end_offset) +{ + /* Unimplemented */ + return NULL; +} + + +static AtkAttributeSet* +et_get_default_attributes (AtkText *text) +{ + /* Unimplemented */ + return NULL; +} + + +static void +et_get_character_extents (AtkText *text, + gint offset, + gint *x, + gint *y, + gint *width, + gint *height, + AtkCoordType coords) +{ + GObject *obj; + EText *etext; + GnomeCanvas *canvas; + gint x_widget, y_widget, x_window, y_window; + GdkWindow *window; + GtkWidget *widget; + PangoRectangle pango_pos; + + g_return_if_fail (ATK_IS_GOBJECT_ACCESSIBLE(text)); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return; + g_return_if_fail (E_IS_TEXT (obj)); + etext = E_TEXT(obj); + canvas = GNOME_CANVAS_ITEM(etext)->canvas; + widget = GTK_WIDGET(canvas); + window = widget->window; + gdk_window_get_origin (window, &x_widget, &y_widget); + + pango_layout_index_to_pos (etext->layout, offset, &pango_pos); + pango_pos.x = PANGO_PIXELS (pango_pos.x); + pango_pos.y = PANGO_PIXELS (pango_pos.y); + pango_pos.width = (pango_pos.width + PANGO_SCALE / 2) / PANGO_SCALE; + pango_pos.height = (pango_pos.height + PANGO_SCALE / 2) / PANGO_SCALE; + + *x = pango_pos.x + x_widget; + *y = pango_pos.y + y_widget; + + *width = pango_pos.width; + *height = pango_pos.height; + + if (etext->draw_borders) { + *x += 3; /*BORDER_INDENT;*/ + *y += 3; /*BORDER_INDENT;*/ + } + + *x += etext->xofs; + *y += etext->yofs; + + if (etext->editing) { + *x -= etext->xofs_edit; + *y -= etext->yofs_edit; + } + + *x += etext->cx; + *y += etext->cy; + + if (coords == ATK_XY_WINDOW) { + window = gdk_window_get_toplevel (window); + gdk_window_get_origin (window, &x_window, &y_window); + *x -= x_window; + *y -= y_window; + } + else if (coords == ATK_XY_SCREEN) { + } + else { + *x = 0; + *y = 0; + *height = 0; + *width = 0; + } +} + + +static gint +et_get_character_count (AtkText *text) +{ + const gchar *full_text = et_get_full_text (text); + + return g_utf8_strlen (full_text, -1); +} + + +static gint +et_get_offset_at_point (AtkText *text, + gint x, + gint y, + AtkCoordType coords) +{ + GObject *obj; + EText *etext; + GnomeCanvas *canvas; + gint x_widget, y_widget, x_window, y_window; + GdkWindow *window; + GtkWidget *widget; + gint index; + gint trailing; + + g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE(text), -1); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return -1; + g_return_val_if_fail (E_IS_TEXT (obj), -1); + etext = E_TEXT(obj); + canvas = GNOME_CANVAS_ITEM(etext)->canvas; + widget = GTK_WIDGET(canvas); + window = widget->window; + gdk_window_get_origin (window, &x_widget, &y_widget); + + if (coords == ATK_XY_SCREEN) { + x = x - x_widget; + y = y - y_widget; + } + else if (coords == ATK_XY_WINDOW) { + window = gdk_window_get_toplevel (window); + gdk_window_get_origin (window, &x_window, &y_window); + x = x - x_widget + x_window; + y = y - y_widget + y_window; + } + else + return -1; + + if (etext->draw_borders) { + x -= 3; /*BORDER_INDENT;*/ + y -= 3; /*BORDER_INDENT;*/ + } + + x -= etext->xofs; + y -= etext->yofs; + + if (etext->editing) { + x += etext->xofs_edit; + y += etext->yofs_edit; + } + + x -= etext->cx; + y -= etext->cy; + + pango_layout_xy_to_index (etext->layout, + x * PANGO_SCALE - PANGO_SCALE / 2, + y * PANGO_SCALE - PANGO_SCALE / 2, + &index, + &trailing); + + return g_utf8_pointer_to_offset (etext->text, etext->text + index + trailing); +} + + +static gint +et_get_n_selections (AtkText *text) +{ + EText *etext = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text))); + if (etext->selection_start != + etext->selection_end) + return 1; + return 0; +} + + +static gchar * +et_get_selection (AtkText *text, + gint selection_num, + gint *start_offset, + gint *end_offset) +{ + gint start, end, real_start, real_end, len; + EText *etext; + if (selection_num == 0) { + const gchar *full_text = et_get_full_text (text); + if (full_text == NULL) + return NULL; + len = g_utf8_strlen (full_text, -1); + etext = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text))); + start = MIN (etext->selection_start, etext->selection_end); + end = MAX (etext->selection_start, etext->selection_end); + start = MIN (MAX (0, start), len); + end = MIN (MAX (0, end), len); + if (start != end) { + if (start_offset) + *start_offset = start; + if (end_offset) + *end_offset = end; + real_start = g_utf8_offset_to_pointer (full_text, start) - full_text; + real_end = g_utf8_offset_to_pointer (full_text, end) - full_text; + return g_strndup (full_text + real_start, real_end - real_start); + } + } + + return NULL; +} + + +static gboolean +et_add_selection (AtkText *text, + gint start_offset, + gint end_offset) +{ + GObject *obj; + EText *etext; + + g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text), FALSE); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return FALSE; + g_return_val_if_fail (E_IS_TEXT (obj), FALSE); + etext = E_TEXT (obj); + + g_return_val_if_fail (start_offset >= 0, FALSE); + g_return_val_if_fail (start_offset >= -1, FALSE); + if (end_offset == -1) + end_offset = et_get_character_count (text); + + if (start_offset != end_offset) { + gint real_start, real_end; + real_start = MIN (start_offset, end_offset); + real_end = MAX (start_offset, end_offset); + etext->selection_start = real_start; + etext->selection_end = real_end; + + gnome_canvas_item_grab_focus (GNOME_CANVAS_ITEM (etext)); + gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (etext)); + + g_signal_emit_by_name (ATK_OBJECT (text), "text_selection_changed"); + + return TRUE; + } + + return FALSE; +} + + +static gboolean +et_remove_selection (AtkText *text, + gint selection_num) +{ + GObject *obj; + EText *etext; + + g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text), FALSE); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return FALSE; + g_return_val_if_fail (E_IS_TEXT (obj), FALSE); + etext = E_TEXT (obj); + + if (selection_num == 0 + && etext->selection_start != etext->selection_end) { + etext->selection_end = etext->selection_start; + g_signal_emit_by_name (ATK_OBJECT(text), "text_selection_changed"); + return TRUE; + } + + return FALSE; +} + + +static gboolean +et_set_selection (AtkText *text, + gint selection_num, + gint start_offset, + gint end_offset) +{ + GObject *obj; + + g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text), FALSE); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return FALSE; + g_return_val_if_fail (E_IS_TEXT (obj), FALSE); + if (selection_num == 0) + return et_add_selection (text, start_offset, end_offset); + return FALSE; +} + + +static gboolean +et_set_caret_offset (AtkText *text, + gint offset) +{ + GObject *obj; + EText *etext; + + g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text), FALSE); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return FALSE; + + g_return_val_if_fail (E_IS_TEXT (obj), FALSE); + etext = E_TEXT (obj); + + if (offset < -1) + return FALSE; + else { + ETextEventProcessorCommand command; + + if (offset == -1) + offset = et_get_character_count (text); + + command.action = E_TEP_MOVE; + command.position = E_TEP_VALUE; + command.value = offset; + command.time = GDK_CURRENT_TIME; + g_signal_emit_by_name (etext->tep, "command", &command); + return TRUE; + } +} + +static gboolean +et_set_run_attributes (AtkEditableText *text, + AtkAttributeSet *attrib_set, + gint start_offset, + gint end_offset) +{ + /* Unimplemented */ + return FALSE; +} + +static void +et_set_text_contents (AtkEditableText *text, + const gchar *string) +{ + et_set_full_text (text, string); +} + +static void +et_insert_text (AtkEditableText *text, + const gchar *string, + gint length, + gint *position) +{ + /* Utf8 unimplemented */ + gchar *result; + + const gchar *full_text = et_get_full_text (ATK_TEXT (text)); + if (full_text == NULL) + return; + + result = g_strdup_printf ("%.*s%.*s%s", *position, full_text, length, string, full_text + *position); + + et_set_full_text (text, result); + + *position += length; + + g_free (result); +} + +static void +et_copy_text (AtkEditableText *text, + gint start_pos, + gint end_pos) +{ + GObject *obj; + EText *etext; + + g_return_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text)); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return; + + g_return_if_fail (E_IS_TEXT (obj)); + etext = E_TEXT (obj); + + if (start_pos != end_pos) { + etext->selection_start = start_pos; + etext->selection_end = end_pos; + e_text_copy_clipboard (etext); + } +} + +static void +et_delete_text (AtkEditableText *text, + gint start_pos, + gint end_pos) +{ + GObject *obj; + EText *etext; + + g_return_if_fail (ATK_IS_GOBJECT_ACCESSIBLE(text)); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return; + + g_return_if_fail (E_IS_TEXT (obj)); + etext = E_TEXT (obj); + + etext->selection_start = start_pos; + etext->selection_end = end_pos; + + e_text_delete_selection (etext); +} + +static void +et_cut_text (AtkEditableText *text, + gint start_pos, + gint end_pos) +{ + et_copy_text (text, start_pos, end_pos); + et_delete_text (text, start_pos, end_pos); +} + +static void +et_paste_text (AtkEditableText *text, + gint position) +{ + GObject *obj; + EText *etext; + + g_return_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text)); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return; + + g_return_if_fail (E_IS_TEXT (obj)); + etext = E_TEXT (obj); + + g_object_set (etext, "cursor_pos", position, NULL); + e_text_paste_clipboard (etext); +} + +static void +et_atk_component_iface_init (AtkComponentIface *iface) +{ + iface->get_extents = et_get_extents; +} + +static void +et_atk_text_iface_init (AtkTextIface *iface) +{ + iface->get_text = et_get_text; + iface->get_text_after_offset = et_get_text_after_offset; + iface->get_text_at_offset = et_get_text_at_offset; + iface->get_character_at_offset = et_get_character_at_offset; + iface->get_text_before_offset = et_get_text_before_offset; + iface->get_caret_offset = et_get_caret_offset; + iface->get_run_attributes = et_get_run_attributes; + iface->get_default_attributes = et_get_default_attributes; + iface->get_character_extents = et_get_character_extents; + iface->get_character_count = et_get_character_count; + iface->get_offset_at_point = et_get_offset_at_point; + iface->get_n_selections = et_get_n_selections; + iface->get_selection = et_get_selection; + iface->add_selection = et_add_selection; + iface->remove_selection = et_remove_selection; + iface->set_selection = et_set_selection; + iface->set_caret_offset = et_set_caret_offset; +} + +static void +et_atk_editable_text_iface_init (AtkEditableTextIface *iface) +{ + iface->set_run_attributes = et_set_run_attributes; + iface->set_text_contents = et_set_text_contents; + iface->insert_text = et_insert_text; + iface->copy_text = et_copy_text; + iface->cut_text = et_cut_text; + iface->delete_text = et_delete_text; + iface->paste_text = et_paste_text; +} + +static void +_et_reposition_cb (ETextModel *model, + ETextModelReposFn fn, + gpointer repos_data, + gpointer user_data) +{ + AtkObject *accessible; + AtkText *text; + + accessible = ATK_OBJECT (user_data); + text = ATK_TEXT (accessible); + + if (fn == e_repos_delete_shift) { + EReposDeleteShift *info = (EReposDeleteShift *) repos_data; + g_signal_emit_by_name (text, "text-changed::delete", info->pos, info->len); + } + else if (fn == e_repos_insert_shift) { + EReposInsertShift *info = (EReposInsertShift *) repos_data; + g_signal_emit_by_name (text, "text-changed::insert", info->pos, info->len); + } +} + +static void +_et_command_cb (ETextEventProcessor *tep, + ETextEventProcessorCommand *command, + gpointer user_data) +{ + AtkObject *accessible; + AtkText *text; + + accessible = ATK_OBJECT (user_data); + text = ATK_TEXT (accessible); + + switch (command->action) { + case E_TEP_MOVE: + g_signal_emit_by_name (text, "text-caret-moved", et_get_caret_offset (text)); + break; + case E_TEP_SELECT: + g_signal_emit_by_name (text, "text-selection-changed"); + break; + default: + break; + } +} + +static void +et_real_initialize (AtkObject *obj, + gpointer data) +{ + EText *etext; + + ATK_OBJECT_CLASS (parent_class)->initialize (obj, data); + + g_return_if_fail (GAL_A11Y_IS_E_TEXT (obj)); + g_return_if_fail (E_IS_TEXT (data)); + + etext = E_TEXT (data); + + /* Set up signal callbacks */ + g_signal_connect (etext->model, "reposition", + G_CALLBACK (_et_reposition_cb), obj); + + if (etext->tep) + g_signal_connect_after (etext->tep, "command", + (GCallback) _et_command_cb, obj); + + obj->role = ATK_ROLE_TEXT; +} + +static void +et_class_init (GalA11yETextClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass); + + quark_accessible_object = g_quark_from_static_string ("gtk-accessible-object"); + parent_class = g_type_class_ref (PARENT_TYPE); + component_parent_iface = g_type_interface_peek(parent_class, ATK_TYPE_COMPONENT); + object_class->dispose = et_dispose; + atk_class->initialize = et_real_initialize; +} + +static void +et_init (GalA11yEText *a11y) +{ +#if 0 + GalA11yETextPrivate *priv; + + priv = GET_PRIVATE (a11y); +#endif +} + +/** + * gal_a11y_e_text_get_type: + * @void: + * + * Registers the &GalA11yEText class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yEText class. + **/ +GType +gal_a11y_e_text_get_type (void) +{ + static GType type = 0; + + if (!type) { + AtkObjectFactory *factory; + + GTypeInfo info = { + sizeof (GalA11yETextClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) et_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yEText), + 0, + (GInstanceInitFunc) et_init, + NULL /* value_text */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) et_atk_component_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + static const GInterfaceInfo atk_text_info = { + (GInterfaceInitFunc) et_atk_text_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + static const GInterfaceInfo atk_editable_text_info = { + (GInterfaceInitFunc) et_atk_editable_text_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + factory = atk_registry_get_factory (atk_get_default_registry (), GNOME_TYPE_CANVAS_ITEM); + parent_type = atk_object_factory_get_accessible_type (factory); + + type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yEText", &info, 0, + sizeof (GalA11yETextPrivate), &priv_offset); + + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); + g_type_add_interface_static (type, ATK_TYPE_TEXT, &atk_text_info); + g_type_add_interface_static (type, ATK_TYPE_EDITABLE_TEXT, &atk_editable_text_info); + } + + return type; +} + +void +gal_a11y_e_text_init (void) +{ + if (atk_get_root ()) + atk_registry_set_factory_type (atk_get_default_registry (), + E_TYPE_TEXT, + gal_a11y_e_text_factory_get_type ()); + +} + diff --git a/widgets/text/gal-a11y-e-text.h b/widgets/text/gal-a11y-e-text.h new file mode 100644 index 0000000000..6a5bb80de0 --- /dev/null +++ b/widgets/text/gal-a11y-e-text.h @@ -0,0 +1,57 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Christopher James Lahey + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TEXT_H__ +#define __GAL_A11Y_E_TEXT_H__ + +#include +#include
+ +#define GAL_A11Y_TYPE_E_TEXT (gal_a11y_e_text_get_type ()) +#define GAL_A11Y_E_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TEXT, GalA11yEText)) +#define GAL_A11Y_E_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TEXT, GalA11yETextClass)) +#define GAL_A11Y_IS_E_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TEXT)) +#define GAL_A11Y_IS_E_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TEXT)) + +typedef struct _GalA11yEText GalA11yEText; +typedef struct _GalA11yETextClass GalA11yETextClass; +typedef struct _GalA11yETextPrivate GalA11yETextPrivate; + +/* This struct should actually be larger as this isn't what we derive from. + * The GalA11yETextPrivate comes right after the parent class structure. + **/ +struct _GalA11yEText { + AtkObject object; +}; + +struct _GalA11yETextClass { + AtkObject parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_text_get_type (void); + +void gal_a11y_e_text_init (void); + +#endif /* ! __GAL_A11Y_E_TEXT_H__ */ diff --git a/win32/Makefile.am b/win32/Makefile.am index d2b25958c0..7720d56543 100644 --- a/win32/Makefile.am +++ b/win32/Makefile.am @@ -6,7 +6,6 @@ EXTRA_DIST = \ libevolution-addressbook.def \ libevolution-calendar.def \ libevolution-mail.def \ - libevolution-mail-shared.def \ libfilter.def if OS_WIN32 @@ -17,7 +16,6 @@ BOOTSTRAP_LIBS = \ libevolution-addressbook.la \ libevolution-calendar.la \ libevolution-mail.la \ - libevolution-mail-shared.la \ libfilter.la endif @@ -58,11 +56,6 @@ libevolution-mail.la: dummy.la libevolution-mail.def mkdir -p .libs $(DLLTOOL) --output-lib=.libs/libevolution-mail.dll.a --dllname=libevolution-mail.dll --input-def=libevolution-mail.def -libevolution-mail-shared.la: dummy.la libevolution-mail-shared.def - sed -e s!%DLL%!libevolution-mail-shared-0! -e s!%LIB%!libevolution-mail-shared! -e s!%PFX%!$(prefix)! $@ - mkdir -p .libs - $(DLLTOOL) --output-lib=.libs/libevolution-mail-shared.dll.a --dllname=libevolution-mail-shared-0.dll --input-def=libevolution-mail-shared.def - libfilter.la: dummy.la libfilter.def sed -e s!%DLL%!libfilter-0! -e s!%LIB%!libfilter! -e s!%PFX%!$(prefix)! $@ mkdir -p .libs -- cgit v1.2.3