[Checkins] SVN: Zem/trunk/ Initial checkin of Zem 0.9.8
Zachery Bir
zbir at urbanape.com
Wed Dec 20 09:23:20 EST 2006
Log message for revision 71616:
Initial checkin of Zem 0.9.8
Changed:
A Zem/trunk/
A Zem/trunk/LICENSE.txt
A Zem/trunk/Nibs/
A Zem/trunk/Nibs/InfoPlist.strings
A Zem/trunk/Nibs/MainMenu.nib/
A Zem/trunk/Nibs/MainMenu.nib/classes.nib
A Zem/trunk/Nibs/MainMenu.nib/info.nib
A Zem/trunk/Nibs/MainMenu.nib/keyedobjects.nib
A Zem/trunk/Nibs/MainMenu.nib/objects.nib
A Zem/trunk/Nibs/Preferences.nib/
A Zem/trunk/Nibs/Preferences.nib/classes.nib
A Zem/trunk/Nibs/Preferences.nib/info.nib
A Zem/trunk/Nibs/Preferences.nib/keyedobjects.nib
A Zem/trunk/PreferenceController.py
A Zem/trunk/Readme.html
A Zem/trunk/Readme.txt
A Zem/trunk/Resources/
A Zem/trunk/Resources/Files.png
A Zem/trunk/Resources/HelperApps.png
A Zem/trunk/Resources/WebDAV.png
A Zem/trunk/Resources/ZEM.icns
A Zem/trunk/Resources/ZEMDocument.icns
A Zem/trunk/Resources/add_disabled.png
A Zem/trunk/Resources/add_idle.png
A Zem/trunk/Resources/add_pressed.png
A Zem/trunk/Resources/com.urbanape.zopeeditmanager.plist
A Zem/trunk/Resources/remove_disabled.png
A Zem/trunk/Resources/remove_idle.png
A Zem/trunk/Resources/remove_pressed.png
A Zem/trunk/ZemAppDelegate.py
A Zem/trunk/ZopeDocument.py
A Zem/trunk/images/
A Zem/trunk/images/mozilla_config.png
A Zem/trunk/images/zem_files_prefs.png
A Zem/trunk/images/zem_helper_apps_prefs.png
A Zem/trunk/images/zem_screenshot_1.png
A Zem/trunk/images/zem_screenshot_2.png
A Zem/trunk/images/zem_webdav_prefs.png
A Zem/trunk/setup.py
-=-
Added: Zem/trunk/LICENSE.txt
===================================================================
--- Zem/trunk/LICENSE.txt 2006-12-20 14:18:52 UTC (rev 71615)
+++ Zem/trunk/LICENSE.txt 2006-12-20 14:23:16 UTC (rev 71616)
@@ -0,0 +1,53 @@
+Zope Public License (ZPL) Version 2.0
+-----------------------------------------------
+
+This software is Copyright (c) Zope Corporation (tm) and
+Contributors. All rights reserved.
+
+This license has been certified as open source. It has also
+been designated as GPL compatible by the Free Software
+Foundation (FSF).
+
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the
+following conditions are met:
+
+1. Redistributions in source code must retain the above
+ copyright notice, this list of conditions, and the following
+ disclaimer.
+
+2. Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions, and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+3. The name Zope Corporation (tm) must not be used to
+ endorse or promote products derived from this software
+ without prior written permission from Zope Corporation.
+
+4. The right to distribute this software or to use it for
+ any purpose does not give you the right to use Servicemarks
+ (sm) or Trademarks (tm) of Zope Corporation. Use of them is
+ covered in a separate agreement (see
+ http://www.zope.com/Marks).
+
+5. If any files are modified, you must cause the modified
+ files to carry prominent notices stating that you changed
+ the files and the date of any change.
+
+Disclaimer
+
+ THIS SOFTWARE IS PROVIDED BY ZOPE CORPORATION ``AS IS''
+ AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
+ NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ NO EVENT SHALL ZOPE CORPORATION OR ITS CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGE.
Property changes on: Zem/trunk/LICENSE.txt
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Zem/trunk/Nibs/InfoPlist.strings
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/Nibs/InfoPlist.strings
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: Zem/trunk/Nibs/MainMenu.nib/classes.nib
===================================================================
--- Zem/trunk/Nibs/MainMenu.nib/classes.nib 2006-12-20 14:18:52 UTC (rev 71615)
+++ Zem/trunk/Nibs/MainMenu.nib/classes.nib 2006-12-20 14:23:16 UTC (rev 71616)
@@ -0,0 +1,19 @@
+{
+ IBClasses = (
+ {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
+ {
+ ACTIONS = {finishEdits = id; performClose = id; showPreferencePanel = id; };
+ CLASS = ZemAppDelegate;
+ LANGUAGE = ObjC;
+ OUTLETS = {
+ "current_edits" = NSTableView;
+ finish = id;
+ "sync_message" = id;
+ "sync_spinner" = id;
+ window = id;
+ };
+ SUPERCLASS = NSObject;
+ }
+ );
+ IBVersion = 1;
+}
\ No newline at end of file
Property changes on: Zem/trunk/Nibs/MainMenu.nib/classes.nib
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zem/trunk/Nibs/MainMenu.nib/info.nib
===================================================================
--- Zem/trunk/Nibs/MainMenu.nib/info.nib 2006-12-20 14:18:52 UTC (rev 71615)
+++ Zem/trunk/Nibs/MainMenu.nib/info.nib 2006-12-20 14:23:16 UTC (rev 71616)
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBDocumentLocation</key>
+ <string>11 30 356 240 0 0 1440 878 </string>
+ <key>IBEditorPositions</key>
+ <dict>
+ <key>29</key>
+ <string>18 522 312 44 0 0 1440 878 </string>
+ </dict>
+ <key>IBFramework Version</key>
+ <string>446.1</string>
+ <key>IBOpenObjects</key>
+ <array>
+ <integer>202</integer>
+ <integer>29</integer>
+ </array>
+ <key>IBSystem Version</key>
+ <string>8L2127</string>
+</dict>
+</plist>
Property changes on: Zem/trunk/Nibs/MainMenu.nib/info.nib
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zem/trunk/Nibs/MainMenu.nib/keyedobjects.nib
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/Nibs/MainMenu.nib/keyedobjects.nib
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: Zem/trunk/Nibs/MainMenu.nib/objects.nib
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/Nibs/MainMenu.nib/objects.nib
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: Zem/trunk/Nibs/Preferences.nib/classes.nib
===================================================================
--- Zem/trunk/Nibs/Preferences.nib/classes.nib 2006-12-20 14:18:52 UTC (rev 71615)
+++ Zem/trunk/Nibs/Preferences.nib/classes.nib 2006-12-20 14:23:16 UTC (rev 71616)
@@ -0,0 +1,36 @@
+{
+ IBClasses = (
+ {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
+ {
+ ACTIONS = {
+ addHelper = id;
+ chooseTempDir = id;
+ removeHelper = id;
+ savePreferences = id;
+ setAlwaysBorrowWebDAVLocks = id;
+ setCleanupFiles = id;
+ setConfirmOnFinish = id;
+ setSaveInterval = id;
+ setUseWebDAVLocks = id;
+ };
+ CLASS = PreferenceController;
+ LANGUAGE = ObjC;
+ OUTLETS = {
+ "add_helper" = id;
+ "always_borrow_webdav_locks" = id;
+ "cleanup_files" = id;
+ "confirm_on_finish" = id;
+ "files_pane" = id;
+ "helper_apps" = id;
+ "helper_apps_pane" = id;
+ "remove_helper" = id;
+ "save_interval" = id;
+ "temp_dir" = id;
+ "use_webdav_locks" = id;
+ "webdav_pane" = id;
+ };
+ SUPERCLASS = NSWindowController;
+ }
+ );
+ IBVersion = 1;
+}
\ No newline at end of file
Property changes on: Zem/trunk/Nibs/Preferences.nib/classes.nib
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zem/trunk/Nibs/Preferences.nib/info.nib
===================================================================
--- Zem/trunk/Nibs/Preferences.nib/info.nib 2006-12-20 14:18:52 UTC (rev 71615)
+++ Zem/trunk/Nibs/Preferences.nib/info.nib 2006-12-20 14:23:16 UTC (rev 71616)
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBDocumentLocation</key>
+ <string>376 29 356 240 0 0 1440 878 </string>
+ <key>IBEditorPositions</key>
+ <dict>
+ <key>15</key>
+ <string>510 525 420 122 0 0 1440 878 </string>
+ <key>16</key>
+ <string>132 347 420 342 0 0 1440 878 </string>
+ <key>7</key>
+ <string>341 643 420 195 0 0 1440 878 </string>
+ </dict>
+ <key>IBFramework Version</key>
+ <string>446.1</string>
+ <key>IBOpenObjects</key>
+ <array>
+ <integer>15</integer>
+ <integer>6</integer>
+ <integer>7</integer>
+ <integer>16</integer>
+ </array>
+ <key>IBSystem Version</key>
+ <string>8L2127</string>
+</dict>
+</plist>
Property changes on: Zem/trunk/Nibs/Preferences.nib/info.nib
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zem/trunk/Nibs/Preferences.nib/keyedobjects.nib
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/Nibs/Preferences.nib/keyedobjects.nib
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: Zem/trunk/PreferenceController.py
===================================================================
--- Zem/trunk/PreferenceController.py 2006-12-20 14:18:52 UTC (rev 71615)
+++ Zem/trunk/PreferenceController.py 2006-12-20 14:23:16 UTC (rev 71616)
@@ -0,0 +1,357 @@
+#
+# PreferenceController.py
+# ZopeEditManager
+#
+# Created by Zachery Bir on 2003-10-29.
+# Copyright (c) 2004 Zope Corporation. All rights reserved.
+#
+
+# library imports
+import os, re
+import objc
+from objc import YES, NO
+from PyObjCTools import NibClassBuilder
+
+# import needed classes/functions from Foundation
+from Foundation import *
+
+# import Nib loading functionality from AppKit
+from AppKit import *
+
+# local product imports
+
+MACOSX_VERSION = os.uname()[2] >= u'7.0.0' and u'panther' or u'jaguar'
+
+def addToolbarItem(aController, anIdentifier, aLabel, aPaletteLabel,
+ aToolTip, aTarget, anAction, anItemContent, aMenu):
+ """
+ Adds an freshly created item to the toolbar defined by
+ aController. Makes a number of assumptions about the
+ implementation of aController. It should be refactored into a
+ generically useful toolbar management untility.
+ """
+ toolbarItem = NSToolbarItem.alloc().initWithItemIdentifier_(anIdentifier)
+
+ toolbarItem.setLabel_(aLabel)
+ toolbarItem.setPaletteLabel_(aPaletteLabel)
+ toolbarItem.setToolTip_(aToolTip)
+ toolbarItem.setTarget_(aTarget)
+ if anAction:
+ toolbarItem.setAction_(anAction)
+
+ if type(anItemContent) == NSImage:
+ toolbarItem.setImage_(anItemContent)
+ else:
+ toolbarItem.setView_(anItemContent)
+ bounds = anItemContent.bounds()
+ minSize = (100, bounds[1][1])
+ maxSize = (1000, bounds[1][1])
+ toolbarItem.setMinSize_( minSize )
+ toolbarItem.setMaxSize_( maxSize )
+
+ if aMenu:
+ menuItem = NSMenuItem.alloc().init()
+ menuItem.setSubmenu_(aMenu)
+ menuItem.setTitle_( aMenu.title() )
+ toolbarItem.setMenuFormRepresentation_(menuItem)
+
+ aController._toolbarItems[anIdentifier] = toolbarItem
+
+# create ObjC classes as defined in Preferences.nib
+NibClassBuilder.extractClasses("Preferences")
+class PreferenceController(NibClassBuilder.AutoBaseClass):
+ """
+ The Controller object for managing various preference variables.
+ """
+ def addHelper_(self, sender):
+ lastIndex = self.numberOfRowsInTableView_(self.helper_apps)
+ self._edited_fields.append({
+ u'type' : u'Type %d' % lastIndex,
+ u'extension' : u'Ext %d' % lastIndex,
+ u'editor' : u'Editor %d' % lastIndex})
+ self.helper_apps.reloadData()
+
+ def removeHelper_(self, sender):
+ row = self.helper_apps.selectedRow()
+ if row != -1:
+ del self._edited_fields[row]
+ self.helper_apps.reloadData()
+
+ def savePreferences_(self, sender):
+ self.sud.setBool_forKey_(bool(self._cleanup_files), u'cleanup_files')
+ self.sud.setBool_forKey_(bool(self._confirm_on_finish),
+ u'confirm_on_finish')
+ self.sud.setBool_forKey_(bool(self._use_webdav_locks), u'use_locks')
+ self.sud.setBool_forKey_(bool(self._always_borrow_webdav_locks),
+ u'always_borrow_locks')
+ self.sud.setFloat_forKey_(self._save_interval, u'save_interval')
+ self.sud.setObject_forKey_(self._temp_dir, u'temp_dir')
+
+ for field in self._edited_fields:
+ self._helper_apps[field[u'type']] = {
+ u'editor' : field[u'editor'],
+ u'extension' : field[u'extension']}
+ self.sud.setObject_forKey_(self._helper_apps, u'helper_apps')
+
+ self.sud.synchronize()
+
+ def chooseTempDir_(self, sender):
+ panel = NSOpenPanel.openPanel()
+ panel.setCanChooseDirectories_(True)
+ panel.setCanChooseFiles_(False)
+ panel.setAllowsMultipleSelection_(False)
+ panel.setResolvesAliases_(True)
+ bSFD = panel.beginSheetForDirectory_file_types_modalForWindow_modalDelegate_didEndSelector_contextInfo_
+ bSFD(self._temp_dir, # directory
+ None, # file
+ None, # types
+ self.window(), # modalForWindow
+ self, # modalDelegate
+ self.chooseTempDirDidEnd_returnCode_contextInfo_, # didEndSelector
+ 0 # contextInfo
+ )
+
+ def chooseTempDirDidEnd_returnCode_contextInfo_(self, sheet, returnCode,
+ contextInfo):
+ if returnCode:
+ self._temp_dir = sheet.filenames()[0]
+ self.temp_dir.setStringValue_(self._temp_dir)
+
+ chooseTempDirDidEnd_returnCode_contextInfo_ = objc.selector(
+ chooseTempDirDidEnd_returnCode_contextInfo_,
+ selector='chooseTempDirDidEnd:returnCode:contextInfo:',
+ signature='@@:@i@'
+ )
+
+ def setCleanupFiles_(self, sender):
+ self._cleanup_files = self.cleanup_files.state()
+
+ def setConfirmOnFinish_(self, sender):
+ self._confirm_on_finish = self.confirm_on_finish.state()
+
+ def setSaveInterval_(self, sender):
+ self._save_interval = self.save_interval.floatValue()
+
+ def setUseWebDAVLocks_(self, sender):
+ self._use_webdav_locks = self.use_webdav_locks.state()
+ if self._use_webdav_locks:
+ self.always_borrow_webdav_locks.setEnabled_(YES)
+ else:
+ self.always_borrow_webdav_locks.setState_(0)
+ self.always_borrow_webdav_locks.setEnabled_(NO)
+
+ def setAlwaysBorrowWebDAVLocks_(self, sender):
+ self._always_borrow_webdav_locks = self.always_borrow_webdav_locks.state()
+
+ def windowWillClose_(self, sender):
+ self.savePreferences_(self)
+
+ def numberOfRowsInTableView_(self, tableView):
+ return len(self._edited_fields)
+
+ def tableView_objectValueForTableColumn_row_(self, tableView,
+ aColumn, aRow):
+ ident = aColumn.identifier()
+ return self._edited_fields[aRow].get(ident, u'')
+
+ def tableView_setObjectValue_forTableColumn_row_(self, aTableView,
+ anObject, aTableColumn,
+ rowIndex):
+ ident = aTableColumn.identifier()
+ self._edited_fields[rowIndex][ident] = anObject
+
+ def tableView_shouldEditTableColumn_row_(self, aTableView, aTableColumn,
+ rowIndex):
+ return YES
+
+ if MACOSX_VERSION == u'panther':
+ def tableView_sortDescriptorsDidChange_(self, aTableView,
+ oldDescriptors):
+
+ array = NSArray.arrayWithArray_(self._edited_fields)
+ self._edited_fields = array.sortedArrayUsingDescriptors_(
+ aTableView.sortDescriptors())
+ self.helper_apps.reloadData()
+
+ def tableViewSelectionDidChange_(self, aNotification):
+ if self.helper_apps.selectedRow() == -1:
+ self.remove_helper.setEnabled_(NO)
+ self.remove_helper.setImage_(self.remove_disabled)
+ else:
+ self.remove_helper.setEnabled_(YES)
+ self.remove_helper.setImage_(self.remove_idle)
+
+ def awakeFromNib(self):
+ self.createToolbar()
+ self.cleanup_files.setState_(self._cleanup_files and 1 or 0)
+ self.confirm_on_finish.setState_(self._confirm_on_finish and 1 or 0)
+ self.save_interval.setFloatValue_(
+ self._save_interval and self._save_interval or 0.0)
+ self.use_webdav_locks.setState_(self._use_webdav_locks and 1 or 0)
+ self.always_borrow_webdav_locks.setState_(
+ self._always_borrow_webdav_locks and 1 or 0)
+ self.always_borrow_webdav_locks.setEnabled_(
+ self._use_webdav_locks and 1 or 0)
+ self.temp_dir.setStringValue_(self._temp_dir)
+
+ if MACOSX_VERSION == u'panther':
+ self.helper_apps.tableColumnWithIdentifier_(
+ u"type").setSortDescriptorPrototype_(self.typeDescriptor)
+ self.helper_apps.tableColumnWithIdentifier_(
+ u"editor").setSortDescriptorPrototype_(self.editorDescriptor)
+ self.helper_apps.tableColumnWithIdentifier_(
+ u"extension").setSortDescriptorPrototype_(self.extensionDescriptor)
+ self.helper_apps.setSortDescriptors_([self.typeDescriptor,])
+
+ self.cached_window_frame = self.window().frame()
+ self.cached_files_pane_frame = self.files_pane.frame()
+ self.cached_webdav_pane_frame = self.webdav_pane.frame()
+ self.cached_helper_apps_pane_frame = self.helper_apps_pane.frame()
+
+ self.remove_helper.setEnabled_(NO)
+ self.remove_helper.setImage_(self.remove_disabled)
+
+ self.window().toolbar().setSelectedItemIdentifier_(u"Files Pane")
+ self.showFilesPane_(self)
+
+ def createToolbar(self):
+ toolbar = NSToolbar.alloc().initWithIdentifier_(u"Preferences Window")
+ toolbar.setDelegate_(self)
+ toolbar.setAllowsUserCustomization_(NO)
+ toolbar.setAutosavesConfiguration_(YES)
+
+ self.createToolbarItems()
+
+ self.window().setToolbar_(toolbar)
+
+ def createToolbarItems(self):
+ addToolbarItem(self, u'Files Pane', u'Files', u'Files',
+ u'Set File Preferences', None, 'showFilesPane:',
+ NSImage.imageNamed_(u"Files"), None)
+
+ addToolbarItem(self, u'WebDAV Pane', u'WebDAV', u'WebDAV',
+ u'Set WebDAV Preferences', None, 'showWebDAVPane:',
+ NSImage.imageNamed_(u"WebDAV"), None)
+
+ addToolbarItem(self, u'Helper Apps Pane', u'Helper Apps',
+ u'Helper Apps', u'Set Helper Apps Preferences', None,
+ 'showHelperAppsPane:', NSImage.imageNamed_(u"HelperApps"), None)
+
+ self._toolbarDefaultItemIdentifiers = [
+ u'Files Pane',
+ u'WebDAV Pane',
+ u'Helper Apps Pane',
+ ]
+
+ def toolbarDefaultItemIdentifiers_(self, anIdentifier):
+ return self._toolbarDefaultItemIdentifiers
+
+ def toolbarAllowedItemIdentifiers_(self, anIdentifier):
+ return self._toolbarDefaultItemIdentifiers
+
+ def toolbarSelectableItemIdentifiers_(self, anIdentifier):
+ return self._toolbarDefaultItemIdentifiers
+
+ def toolbarWillAddItem_(self, notification):
+ pass
+
+ def toolbarDidRemoveItem_(self, notification):
+ pass
+
+ def toolbar_itemForItemIdentifier_willBeInsertedIntoToolbar_(self,
+ toolbar, itemIdentifier, flag):
+ newItem = NSToolbarItem.alloc().initWithItemIdentifier_(itemIdentifier)
+ item = self._toolbarItems[itemIdentifier]
+
+ newItem.setLabel_(item.label())
+ newItem.setPaletteLabel_(item.paletteLabel())
+ if item.view():
+ newItem.setView_(item.view())
+ else:
+ newItem.setImage_(item.image())
+
+ newItem.setToolTip_(item.toolTip())
+ newItem.setTarget_(item.target())
+ newItem.setAction_(item.action())
+ newItem.setMenuFormRepresentation_(item.menuFormRepresentation())
+
+ if newItem.view():
+ newItem.setMinSize_(item.minSize())
+ newItem.setMaxSize_(item.maxSize())
+
+ return newItem
+
+ def showFilesPane_(self, sender):
+ self.resizeViewFor_(self.cached_files_pane_frame)
+ self.window().setContentView_(self.files_pane)
+
+ def showWebDAVPane_(self, sender):
+ self.resizeViewFor_(self.cached_webdav_pane_frame)
+ self.window().setContentView_(self.webdav_pane)
+
+ def showHelperAppsPane_(self, sender):
+ self.resizeViewFor_(self.cached_helper_apps_pane_frame)
+ self.window().setContentView_(self.helper_apps_pane)
+
+ def resizeViewFor_(self, view_frame):
+ windowFrame = self.window().contentRectForFrameRect_styleMask_(
+ self.window().frame(), self.window().styleMask())
+ newWindowHeight = NSHeight(view_frame)
+ toolbarHeight = 0.0
+ if self.window().toolbar().isVisible():
+ toolbarHeight = NSHeight(
+ self.window().toolbar()._toolbarView().frame())
+ newWindowFrame = self.window().frameRectForContentRect_styleMask_(
+ ((NSMinX(windowFrame), NSMaxY(windowFrame) - newWindowHeight),
+ (NSWidth(windowFrame), newWindowHeight)),
+ self.window().styleMask())
+ self.window().setFrame_display_animate_(newWindowFrame,
+ YES,
+ self.window().isVisible())
+
+ def init(self):
+
+ self = self.initWithWindowNibName_(u"Preferences")
+
+ self._edited_fields = []
+ self._toolbarItems = {}
+ self._toolbarDefaultItemIdentifiers = []
+
+ self.sud = NSUserDefaults.standardUserDefaults()
+ self._cleanup_files = self.sud.boolForKey_(u'cleanup_files')
+ self._confirm_on_finish = self.sud.boolForKey_(u'confirm_on_finish')
+ self._save_interval = self.sud.floatForKey_(u'save_interval')
+ self._use_webdav_locks = self.sud.boolForKey_(u'use_locks')
+ self._always_borrow_webdav_locks = self.sud.boolForKey_(
+ u'always_borrow_locks')
+ self._helper_apps = NSMutableDictionary.dictionaryWithDictionary_(
+ self.sud.dictionaryForKey_(u'helper_apps'))
+ self._temp_dir = self.sud.stringForKey_(u'temp_dir') or u'/tmp'
+
+ # This button will change, so we should pre-load them
+ self.remove_idle = NSImage.imageNamed_(u"remove_idle")
+ self.remove_disabled = NSImage.imageNamed_(u"remove_disabled")
+
+ for x in range(len(self._helper_apps.keys())):
+ type = self._helper_apps.keys()[x]
+ extension = self._helper_apps[type].get(u'extension', u'')
+ editor = self._helper_apps[type].get(u'editor', u'')
+ self._edited_fields.append({u'type': type,
+ u'extension': extension,
+ u'editor': editor})
+
+ if MACOSX_VERSION == u'panther':
+ self.typeDescriptor = (
+ NSSortDescriptor.alloc().initWithKey_ascending_selector_(
+ u"type", YES, 'caseInsensitiveCompare:'))
+
+ self.editorDescriptor = (
+ NSSortDescriptor.alloc().initWithKey_ascending_selector_(
+ u"editor", YES, 'caseInsensitiveCompare:'))
+
+ self.extensionDescriptor = (
+ NSSortDescriptor.alloc().initWithKey_ascending_selector_(
+ u"extension", YES, 'caseInsensitiveCompare:'))
+
+ return self
+
Property changes on: Zem/trunk/PreferenceController.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Zem/trunk/Readme.html
===================================================================
--- Zem/trunk/Readme.html 2006-12-20 14:18:52 UTC (rev 71615)
+++ Zem/trunk/Readme.html 2006-12-20 14:23:16 UTC (rev 71616)
@@ -0,0 +1,178 @@
+<html>
+ <head>
+ <title>Zem</title>
+ </head>
+ <body>
+ <h1>Zem</h1>
+
+ <p>Zem is an implementation of Casey Duncan's excellent External
+ Editor for Mac OS X, providing Mac users with flexibility in
+ their choice of content-specific editors, and as many concurrent
+ editors as they need running at the same time.</p>
+
+ <p>Taking Casey's work, and adapting it for Mac OS X users using
+ the PyObjC bridge, I provide the same functionality, but in a
+ native Mac OS X application with an intuitive graphical user
+ interface. This means that you can specify any Mac OS X
+ application (Carbon or Cocoa) to act as the editor for a MIME
+ type, type group, or Zope meta_type. And you can have as many
+ concurrent edits as you like, since all edits are handled
+ through Zem.</p>
+
+ <h2>Installing It</h2>
+
+ <p>Drag the ZopeEditManger application to the Applications folder
+ in your hard drive or home directory. You can use the built-in
+ preferences, one of the supplied preference files, or edit your
+ own.</p>
+
+ <h2>Using It</h2>
+
+ <p><img src="images/zem_screenshot_1.png" alt=""></p>
+
+ <p>As you download links from the Zope Management Interface (ZMI)
+ or the Content Management Framework (CMF) or Plone, new
+ documents will accumulate in the main table.</p>
+
+ <p><img src="images/zem_screenshot_2.png" alt=""></p>
+
+ <p>As saves are made in the editor, Zem will synch those changes
+ back to the server, and display the time of the last synch. To
+ remove a document from Zem, simply select it from the table, and
+ click the 'Finish' button, or press the 'delete' key.</p>
+
+ <h2>Configuring your Browser</h2>
+
+ <p>Currently, the only browser fully set to work with Zem is
+ Mozilla. Internet Explorer supports the configuration of File
+ Helpers, but I've been unable to get it working quite right. In
+ any case, other browsers will download a particular file. That
+ file can be dragged onto the Zem icon and it will work fine. To
+ enable Zem in Mozilla, select the Helper Applications pane from
+ the Navigator group, and create a New Type called
+ 'application/x-zope-edit', and choose Zem with the Application
+ picker.</p>
+
+ <p><img src="images/mozilla_config.png" alt=""></p>
+
+ <h2>Configuration</h2>
+
+ <p>Zem provides a GUI Preferences panel. Just choose
+ "Preferences..." from the Zem menu, or press Command-, to open
+ the window.</p>
+
+ <h2>Options</h2>
+
+ <p>The available options for Zem are (names in parentheses are the
+ corresponding key names in the Preferences plist):</p>
+
+ <h3>Files Prefs</h3>
+
+ <p><img src="images/zem_files_prefs.png" alt=""></p>
+
+ <dl>
+ <dt>Cleanup Files (<code>cleanup_files</code>)</dt>
+ <dd>Whether to delete the temp files created.<br/><br/>WARNING
+ the temp file coming from the browser contains authentication
+ information and therefore setting this to <false/> is a
+ security risk, especially on shared machines. If set to
+ <true/>, that file is deleted at the earliest
+ opportunity, before the editor is even spawned. Set to
+ <false/> for debugging only.</dd>
+
+ <dt>Confirm on Finish (<code>confirm_on_finish</code>)</dt>
+ <dd>When you are finished locally editing a file,
+ Zem will ask you to confirm this. You can disable
+ this behavior by unchecking this button.</dd>
+
+ <dt>Save Interval (<code>save_interval</code>)</dt>
+ <dd>The interval in seconds that the helper application checks
+ the edited file for changes.</dd>
+
+ <dt>Temporary Files (<code>temp_dir</code>)</dt>
+ <dd>Path to store local copies of object data being
+ edited. Defaults to /tmp (/private/tmp).</dd>
+
+ </dl>
+
+ <h3>WebDAV Prefs</h3>
+
+ <p><img src="images/zem_webdav_prefs.png" alt=""></p>
+
+ <dl>
+
+ <dt>Use WebDAV Locks (<code>use_locks</code>)</dt>
+ <dd>Whether to use WebDAV locking. The user editing must have
+ the proper WebDAV related permissions for this to work.</dd>
+
+ <dt>Always borrow WebDAV Locks
+ (<code>always_borrow_locks</code>)</dt>
+ <dd>When use_locks is enabled this features suppresses warnings
+ when trying to edit an object you have already locked. When
+ enabled, external editor will always "borrow" the existing
+ lock token instead of doing the locking itself. This is useful
+ when using CMFStaging for instance. If omitted, this option
+ defaults to <false/>.</dd>
+
+ </dl>
+
+ <h3>Helper Apps Prefs</h3>
+
+ <p><img src="images/zem_helper_apps_prefs.png" alt=""></p>
+
+ <p>To edit an entry, simply double click on the cell, and edit. To
+ add a new Helper App, click the '+' button. To remove an entry,
+ select a row, and click '-'. You can sort the table by any of
+ the columns, ascending or descending.</p>
+
+ <dl>
+
+ <dt>Type</dt>
+ <dd>Either the meta_type of the Zope object, or the MIME type of
+ the file it would represent.</dd>
+
+ <dt>Extension (<code>extension</code>)</dt>
+ <dd>The file extension to add to the content file. Allows better
+ handling of images and can improve syntax highlighting.</dd>
+
+ <dt>Editor (<code>editor</code>)</dt>
+ <dd>Application name used to invoke the editor application.</dd>
+
+ </dl>
+
+ <h2>Credits</h2>
+
+ <p>I would like to thank the following people for their help in
+ this endeavor:</p>
+
+ <ul>
+
+ <li>Casey Duncan, for the excellent ExternalEditor product, and
+ the initial zopeedit.py</li>
+ <li>Bill Bumgarner and Bob Ippolito, for their hard work on
+ PyObjC, and their endless help on #macpython on
+ irc.freenode.net.</li>
+ <li>Jesús Díaz Blanco, for his help refining the
+ UI</li>
+ <li>Sascha Gresk, Eric W. Brown, Brian Morton, Jeff Putsch,
+ Aurelius Prochazka, Jürgen Valldorf, Michael Bond,
+ Sébastien Verbois, Jonah Crawford, Jean-Philippe Rey,
+ Jim Allman, and Alan Runyan for using it and supplying
+ valuable feedback</li>
+
+ </ul>
+
+ <h2>Conclusion</h2>
+
+ <p>I hope you enjoy using this software. If you have any comments,
+ suggestions or would like to report a bug, send an email with
+ 'Zem' in the Subject line to the author:</p>
+
+ <p>Zachery Bir <a href="mailto:zbir at urbanape.com?subject=Zem%20Feedback"><zbir at urbanape.com></a></p>
+
+ <hr/>
+
+ <p>© 2003-2005, Zachery Bir and Zope Corporation. All rights
+ reserved.</p>
+ </body>
+</html>
Property changes on: Zem/trunk/Readme.html
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zem/trunk/Readme.txt
===================================================================
--- Zem/trunk/Readme.txt 2006-12-20 14:18:52 UTC (rev 71615)
+++ Zem/trunk/Readme.txt 2006-12-20 14:23:16 UTC (rev 71616)
@@ -0,0 +1,146 @@
+Zem
+
+Zem is an implementation of Casey Duncan's excellent External Editor
+for Mac OS X, providing Mac users with flexibility in their choice of
+content-specific editors, and as many concurrent editors as they need
+running at the same time.
+
+Taking Casey's work, and adapting it for Mac OS X users using the
+PyObjC bridge, I provide the same functionality, but in a native Mac
+OS X application with an intuitive graphical user interface. This
+means that you can specify any Mac OS X application (Carbon or Cocoa)
+to act as the editor for a MIME type, type group, or Zope
+meta_type. And you can have as many concurrent edits as you like,
+since all edits are handled through Zem.
+
+Installing It
+
+Drag the ZopeEditManger application to the Applications folder in your
+hard drive or home directory. You can use the built-in preferences,
+one of the supplied preference files, or edit your own.
+
+Using It
+
+As you download links from the Zope Management Interface (ZMI) or the
+Content Management Framework (CMF) or Plone, new documents will
+accumulate in the main table.
+
+As saves are made in the editor, Zem will synch those changes back to
+the server, and display the time of the last synch. To remove a
+document from Zem, simply select it from the table, and click the
+'Finish' button, or press the 'delete' key.
+
+Configuring your Browser
+
+Currently, the only browser fully set to work with Zem is
+Mozilla. Internet Explorer supports the configuration of File Helpers,
+but I've been unable to get it working quite right. In any case, other
+browsers will download a particular file. That file can be dragged
+onto the Zem icon and it will work fine. To enable Zem in Mozilla,
+select the Helper Applications pane from the Navigator group, and
+create a New Type called 'application/x-zope-edit', and choose Zem
+with the Application picker.
+
+Configuration
+
+Zem provides a GUI Preferences panel. Just choose "Preferences..."
+from the Zem menu, or press Command-, to open the window.
+
+Options
+
+The available options for Zem are (names in parentheses are the
+corresponding key names in the Preferences plist):
+
+Files Prefs
+
+Cleanup Files (cleanup_files)
+
+ Whether to delete the temp files created.
+
+ WARNING the temp file coming from the browser contains
+ authentication information and therefore setting this to <false/>
+ is a security risk, especially on shared machines. If set to
+ <true/>, that file is deleted at the earliest opportunity, before
+ the editor is even spawned. Set to <false /> for debugging only.
+
+Confirm on Finish (confirm_on_finish)
+
+ When you are finished locally editing a file, Zem will ask you to
+ confirm this. You can disable this behavior by unchecking this
+ button.
+
+Save Interval (save_interval)
+
+ The interval in seconds that the helper application checks the
+ edited file for changes.
+
+Temporary Files (temp_dir)
+
+ Path to store local copies of object data being edited. Defaults
+ to /tmp (/ private/tmp).
+
+WebDAV Prefs
+
+Use WebDAV Locks (use_locks)
+
+ Whether to use WebDAV locking. The user editing must have the
+ proper WebDAV related permissions for this to work.
+
+Always borrow WebDAV Locks (always_borrow_locks)
+
+ When use_locks is enabled this features suppresses warnings when
+ trying to edit an object you have already locked. When enabled,
+ external editor will always "borrow" the existing lock token
+ instead of doing the locking itself. This is useful when using
+ CMFStaging for instance. If omitted, this option defaults to
+ <false/>.
+
+Helper Apps Prefs
+
+To edit an entry, simply double click on the cell, and edit. To add a
+new Helper App, click the '+' button. To remove an entry, select a
+row, and click '-'. You can sort the table by any of the columns,
+ascending or descending.
+
+Type
+
+ Either the meta_type of the Zope object, or the MIME type of the
+ file it would represent.
+
+Extension (extension)
+
+ The file extension to add to the content file. Allows better
+ handling of images and can improve syntax highlighting.
+
+Editor (editor)
+
+ Application name used to invoke the editor application.
+
+Credits
+
+I would like to thank the following people for their help in this
+endeavor:
+
+ - Casey Duncan, for the excellent ExternalEditor product, and the
+ initial zopeedit.py
+
+ - Bill Bumgarner and Bob Ippolito, for their hard work on PyObjC,
+ and their endless help on #macpython on irc.freenode.net.
+
+ - Jesus Diaz Blanco, for his help refining the UI
+
+ - Sascha Gresk, Eric W. Brown, Brian Morton, Jeff Putsch, Aurelius
+ Prochazka, Jurgen Valldorf, Michael Bond, Sebastien Verbois, Jonah
+ Crawford, Jean-Philippe Rey, Jim Allman, and Alan Runyan for using
+ it and supplying valuable feedback
+
+Conclusion
+
+I hope you enjoy using this software. If you have any comments,
+suggestions or would like to report a bug, send an email with 'Zem' in
+the Subject line to the author:
+
+Zachery Bir <zbir at urbanape.com>
+
+(C) 2003-2005, Zachery Bir and Zope Corporation. All rights reserved.
+
Property changes on: Zem/trunk/Readme.txt
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Zem/trunk/Resources/Files.png
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/Resources/Files.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Added: Zem/trunk/Resources/HelperApps.png
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/Resources/HelperApps.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Added: Zem/trunk/Resources/WebDAV.png
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/Resources/WebDAV.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Added: Zem/trunk/Resources/ZEM.icns
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/Resources/ZEM.icns
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: Zem/trunk/Resources/ZEMDocument.icns
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/Resources/ZEMDocument.icns
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: Zem/trunk/Resources/add_disabled.png
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/Resources/add_disabled.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Added: Zem/trunk/Resources/add_idle.png
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/Resources/add_idle.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Added: Zem/trunk/Resources/add_pressed.png
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/Resources/add_pressed.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Added: Zem/trunk/Resources/com.urbanape.zopeeditmanager.plist
===================================================================
--- Zem/trunk/Resources/com.urbanape.zopeeditmanager.plist 2006-12-20 14:18:52 UTC (rev 71615)
+++ Zem/trunk/Resources/com.urbanape.zopeeditmanager.plist 2006-12-20 14:23:16 UTC (rev 71616)
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>helper_apps</key>
+ <dict>
+ <key>DTML Document</key>
+ <dict>
+ <key>extension</key>
+ <string>.dtml</string>
+ <key>editor</key>
+ <string>TextEdit</string>
+ </dict>
+ <key>DTML Method</key>
+ <dict>
+ <key>extension</key>
+ <string>.dtml</string>
+ <key>editor</key>
+ <string>TextEdit</string>
+ </dict>
+ <key>Script (Python)</key>
+ <dict>
+ <key>extension</key>
+ <string>.py</string>
+ <key>editor</key>
+ <string>TextEdit</string>
+ </dict>
+ <key>Page Template</key>
+ <dict>
+ <key>extension</key>
+ <string>.html</string>
+ <key>editor</key>
+ <string>TextEdit</string>
+ </dict>
+ <key>Z SQL Method</key>
+ <dict>
+ <key>extension</key>
+ <string>.sql</string>
+ <key>editor</key>
+ <string>TextEdit</string>
+ </dict>
+ <key>image/gif</key>
+ <dict>
+ <key>extension</key>
+ <string>.gif</string>
+ <key>editor</key>
+ <string>Preview</string>
+ </dict>
+ <key>image/jpeg</key>
+ <dict>
+ <key>extension</key>
+ <string>.jpg</string>
+ <key>editor</key>
+ <string>Preview</string>
+ </dict>
+ <key>image/png</key>
+ <dict>
+ <key>extension</key>
+ <string>.png</string>
+ <key>editor</key>
+ <string>Preview</string>
+ </dict>
+ <key>image/*</key>
+ <dict>
+ <key>editor</key>
+ <string>Preview</string>
+ </dict>
+ <key>text/html</key>
+ <dict>
+ <key>extension</key>
+ <string>.html</string>
+ <key>editor</key>
+ <string>TextEdit</string>
+ </dict>
+ <key>text/xml</key>
+ <dict>
+ <key>extension</key>
+ <string>.xml</string>
+ <key>editor</key>
+ <string>TextEdit</string>
+ </dict>
+ <key>text/*</key>
+ <dict>
+ <key>extension</key>
+ <string>.txt</string>
+ <key>editor</key>
+ <string>TextEdit</string>
+ </dict>
+ </dict>
+ <key>save_interval</key>
+ <real>10.0</real>
+ <key>confirm_on_finish</key>
+ <true/>
+ <key>cleanup_files</key>
+ <true/>
+ <key>use_locks</key>
+ <true/>
+ <key>always_borrow_locks</key>
+ <false/>
+ <key>version_check</key>
+ <string>0.9</string>
+</dict>
+</plist>
Property changes on: Zem/trunk/Resources/com.urbanape.zopeeditmanager.plist
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zem/trunk/Resources/remove_disabled.png
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/Resources/remove_disabled.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Added: Zem/trunk/Resources/remove_idle.png
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/Resources/remove_idle.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Added: Zem/trunk/Resources/remove_pressed.png
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/Resources/remove_pressed.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Added: Zem/trunk/ZemAppDelegate.py
===================================================================
--- Zem/trunk/ZemAppDelegate.py 2006-12-20 14:18:52 UTC (rev 71615)
+++ Zem/trunk/ZemAppDelegate.py 2006-12-20 14:23:16 UTC (rev 71616)
@@ -0,0 +1,232 @@
+#
+# ZemAppDelegate.py
+# Zem
+#
+# Created by Zachery Bir on Thu Jun 10 2004.
+# Copyright (c) 2004 Zope Corporation. All rights reserved.
+#
+
+# library imports
+import os, re
+from objc import YES, NO
+from PyObjCTools import NibClassBuilder, AppHelper
+
+# import needed classes/functions from Foundation
+from Foundation import *
+
+# import Nib loading functionality from AppKit
+from AppKit import *
+
+# local product imports
+from ZopeDocument import ZopeDocument, __version__
+from PreferenceController import PreferenceController
+
+def iterNSIndexSet(s):
+ val = s.lastIndex()
+ while val != NSNotFound:
+ yield val
+ val = s.indexLessThanIndex_(val)
+
+NibClassBuilder.extractClasses("MainMenu")
+class ZemAppDelegate(NibClassBuilder.AutoBaseClass):
+ """
+ The Controller object for managing various processes editing Zope
+ objects externally.
+ """
+ def updateIfModified(self, timer):
+ timerUser = timer.userInfo()
+ for doc in timerUser.current_edits_data:
+ mtime = os.path.getmtime(doc.getContentFile())
+
+ if mtime != doc.last_mtime:
+ # File was modified
+ self.sync_spinner.startAnimation_(self)
+ doc.putChanges()
+ self.sync_spinner.stopAnimation_(self)
+ self.sync_message.setStringValue_(u'Last synched: %s' % NSDate.date().descriptionWithCalendarFormat_timeZone_locale_(u"%a, %d %b %Y at %H:%M:%S %p", None, None))
+ doc.last_mtime = mtime
+
+ return 1
+
+ def performClose_(self, sender):
+ keyWindow = NSApplication.sharedApplication().keyWindow()
+ if keyWindow is self.window:
+ return NO
+ keyWindow.performClose_(sender)
+
+ def showPreferencePanel_(self, sender):
+ if self.preferenceController is None:
+ self.preferenceController = PreferenceController.alloc().init()
+ self.preferenceController.showWindow_(self)
+
+ def application_openFile_(self, app, filename):
+ """
+ Invoked by NSApplication when the app attempts to open a file
+ """
+ NSLog(u'Opening Application')
+
+ zopeDoc = ZopeDocument(filename)
+ zopeDoc.removeFileIfNecessary(filename)
+ self.current_edits_data.append(zopeDoc)
+ self.current_edits.reloadData()
+ return self.openDocument_(zopeDoc)
+
+ def gotoEdit_(self):
+ row = self.current_edits.selectedRow()
+ if row != -1:
+ zopeDoc = self.current_edits_data[row]
+ return self.openDocument_(zopeDoc)
+
+ def openDocument_(self, zopeDoc):
+ if self.sud.boolForKey_(u'use_locks'):
+ if zopeDoc.metadata.get(u'lock-token'):
+ if (self.sud.boolForKey_(u'always_borrow_locks')
+ or zopeDoc.metadata.get(u'borrow_lock')
+ or NSRunAlertPanel(u"Borrow Lock?",
+ u"This object is already locked by"
+ " you in another session. Do you want"
+ " to borrow this lock and continue?",
+ u"Yes", u"Cancel", None)):
+ zopeDoc.lock_token = (u'opaquelocktoken:%s'
+ % zopeDoc.metadata['lock-token'])
+ else:
+ self.finishEdits_()
+
+ if self.sud.boolForKey_(u'use_locks'):
+ zopeDoc.lock()
+
+ editor = zopeDoc.getEditor()
+ content_file = zopeDoc.getContentFile()
+ return self.ws.openFile_withApplication_andDeactivate_(content_file,
+ editor, YES)
+
+ def finishEdits_(self, sender=None):
+ """
+ We want to get rid of the lock on one or more Zope objects and
+ delete its local copy.
+ """
+ selected = self.current_edits.numberOfSelectedRows()
+ if selected:
+ perform = True
+ if self.sud.boolForKey_(u'confirm_on_finish'):
+ if selected == 1:
+ msg = u"Are you sure you're finished with this object?"
+ else:
+ msg = (u"Are you sure you're finished with these %d "
+ "objects?" % (selected))
+ perform = NSRunAlertPanel(u"Deleting Entry", msg,
+ u"Yes", u"Cancel", None)
+ for row in iterNSIndexSet(self.current_edits.selectedRowIndexes()):
+ del self.current_edits_data[row]
+ self.current_edits.reloadData()
+
+ def numberOfRowsInTableView_(self, tableView):
+ return len(self.current_edits_data)
+
+ def tableView_objectValueForTableColumn_row_(self, tableView,
+ aColumn, aRow):
+ ident = aColumn.identifier()
+ return getattr(self.current_edits_data[aRow], 'get' + ident)()
+
+ def tableViewSelectionDidChange_(self, aNotification):
+ if self.current_edits.selectedRow() == -1:
+ self.finish.setEnabled_(NO)
+ else:
+ self.finish.setEnabled_(YES)
+
+ def upgradePrefs(self):
+ new_prefs = {}
+ keep_keys = [u'always_borrow_locks', u'cleanup_files',
+ u'confirm_on_finish', u'helper_apps', u'save_interval',
+ u'use_locks', u'version_check']
+ for key in keep_keys:
+ new_prefs[key] = self.sud.objectForKey_(key)
+ edit_keys = self.sud.persistentDomainForName_(self.bundleIdent).keys()
+ helper_apps = self.sud.dictionaryForKey_(u'helper_apps')
+ if helper_apps is None:
+ helper_apps = {}
+ for key in edit_keys:
+ if key not in keep_keys:
+ if self.sud.objectForKey_(key).has_key(u'editor'):
+ helper_apps[key] = self.sud.objectForKey_(key)
+ else:
+ sub_keys = self.sud.objectForKey_(key).keys()
+ for sub_key in sub_keys:
+ helper_apps[u"%s/%s" % (key, sub_key)] = self.sud.objectForKey_(key)[sub_key]
+ new_prefs[u'helper_apps'] = helper_apps
+
+ # Possibly a new pref this version
+ if not new_prefs.has_key(u'confirm_on_finish'):
+ new_prefs[u'confirm_on_finish'] = YES
+
+ # Update this pref always
+ new_prefs[u'version_check'] = __version__
+
+ self.sud.removePersistentDomainForName_(self.bundleIdent)
+ self.sud.setPersistentDomain_forName_(new_prefs, self.bundleIdent)
+ self.sud.synchronize()
+ NSRunAlertPanel(u"Preferences Updated",
+ u"Your Preferences have been upgraded.",
+ u"Close", None, None)
+
+ def resetPrefs(self):
+ self.sud.removePersistentDomainForName_(self.bundleIdent)
+ self.sud.setPersistentDomain_forName_(
+ NSDictionary.dictionaryWithContentsOfFile_(
+ NSBundle.mainBundle().pathForResource_ofType_(
+ self.bundleIdent, "plist")),
+ self.bundleIdent)
+ self.sud.synchronize()
+ if NSRunAlertPanel(u"Preferences Reset",
+ u"Your Preferences have been reset.",
+ u"Edit Prefs", u"Close", None):
+ self.showPreferencePanel_(self)
+
+ def awakeFromNib(self):
+ self.current_edits.setDoubleAction_("gotoEdit:")
+ self.sync_message.setStringValue_(u'')
+ self.finish.setEnabled_(NO)
+
+ def init(self):
+ self.bundleIdent = NSBundle.mainBundle().bundleIdentifier()
+ self.preferenceController = None
+ self.current_edits_data = []
+ self.ws = NSWorkspace.sharedWorkspace()
+ NSUserDefaults.resetStandardUserDefaults()
+ self.sud = NSUserDefaults.standardUserDefaults()
+ pdomain = self.sud.persistentDomainForName_(self.bundleIdent)
+ if pdomain is None:
+ self.sud.setPersistentDomain_forName_(
+ NSDictionary.dictionaryWithContentsOfFile_(
+ NSBundle.mainBundle().pathForResource_ofType_(
+ self.bundleIdent, "plist")),
+ self.bundleIdent)
+ self.sud.synchronize()
+
+ version_check = self.sud.stringForKey_(u'version_check')
+ if version_check != __version__:
+ response = NSRunAlertPanel(u"Preferences Differ",
+ u"Your Preferences were set with "
+ "an older version of "
+ "Zem. Would you "
+ "like to upgrade your Preferences?",
+ u"Upgrade", u"Start Fresh", None)
+ if response == 1:
+ self.upgradePrefs()
+ if response == 0:
+ self.resetPrefs()
+
+ interval = (self.sud.floatForKey_(u'save_interval')) or 20.0
+ timer = (
+ NSTimer.scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(
+ interval, self, 'updateIfModified', self, YES))
+ NSRunLoop.currentRunLoop().addTimer_forMode_(timer,
+ NSDefaultRunLoopMode)
+
+ return self
+
+ def applicationWillTerminate_(self, notification):
+ for x in range(len(self.current_edits_data)):
+ del self.current_edits_data[x]
+
+AppHelper.runEventLoop(argv=[])
Property changes on: Zem/trunk/ZemAppDelegate.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Zem/trunk/ZopeDocument.py
===================================================================
--- Zem/trunk/ZopeDocument.py 2006-12-20 14:18:52 UTC (rev 71615)
+++ Zem/trunk/ZopeDocument.py 2006-12-20 14:23:16 UTC (rev 71616)
@@ -0,0 +1,299 @@
+#
+# ZopeEditController.py
+# ZopeEditManager
+#
+# Created by Zachery Bir on 2003-08-20.
+# Copyright (c) 2004 Zope Corporation. All rights reserved.
+#
+
+# library imports
+import sys, os, re
+import urllib
+from urlparse import urlparse
+from httplib import HTTPConnection, HTTPSConnection
+from tempfile import mktemp
+
+# import needed classes/functions from Foundation
+from Foundation import *
+
+# import Nib loading functionality from AppKit
+from AppKit import *
+
+__version__ = u"0.9"
+
+def fatalError(message):
+ """Show error message and exit"""
+ if NSRunAlertPanel('Sorry',
+ 'Fatal Error: %s' % message,
+ 'Quit', None, None):
+ # Write out debug info to a temp file
+ debug_f = open(mktemp('-zopeedit-traceback.txt'), 'w')
+ try:
+ traceback.print_exc(file=debug_f)
+ finally:
+ debug_f.close()
+ sys.exit(0)
+
+class ZopeDocument:
+
+ def __init__(self, filename):
+ self.filename = filename
+ (self.metadata, self.contents) = self.getMetadataAndContents(filename)
+ meta_type = self.metadata.get('meta_type', None)
+ content_type = self.metadata.get('content_type', 'text/plain')
+
+ self.sud = NSUserDefaults.standardUserDefaults()
+
+ options_group = self.sud.dictionaryForKey_('helper_apps')
+
+ self.options = options_group.get(meta_type,
+ options_group.get(content_type, None))
+ if not self.options:
+ content_type, content_subtype = re.split(r'[/_]', content_type, 1)
+ self.options = options_group.get("%s/*" % content_type)
+
+ scheme, self.host, self.path = urlparse(self.metadata['url'])[:3]
+ self.ssl = scheme == 'https'
+
+ self.content_file = self.generateContentFile()
+
+ self.last_mtime = os.path.getmtime(self.content_file)
+
+ if self.ssl:
+ # See if ssl is available
+ try:
+ from socket import ssl
+ except ImportError:
+ fatalError('SSL support is not available on this system. '
+ 'Make sure openssl is installed '
+ 'and reinstall Python.')
+
+ self.saved = 1
+ self.lock_token = None
+ self.did_lock = 0
+
+ def getEditor(self):
+ return self.options['editor']
+
+ def getContentFile(self):
+ return self.content_file
+
+ def getContentFileName(self):
+ return os.path.split(self.content_file)[-1].split(',')[-1]
+
+ def getFilename(self):
+ return self.filename
+
+ def generateContentFile(self):
+ content_file = urllib.unquote('-%s%s' % (self.host, self.path))
+ content_file = content_file.replace('/',
+ ',').replace(':',
+ ',').replace(' ',
+ '_')
+
+ extension = self.options.get('extension', None)
+
+ if extension and not content_file.endswith(extension):
+ content_file = content_file + extension
+
+ if self.sud.stringForKey_('temp_dir'):
+ while 1:
+ temp = os.path.expanduser(self.sud.stringForKey_('temp_dir'))
+ temp = os.tempnam(temp)
+ content_file = '%s%s' % (temp, content_file)
+ if not os.path.exists(content_file):
+ break
+ else:
+ content_file = mktemp(content_file)
+
+ out_f = open(content_file, 'wb')
+ out_f.write(self.contents)
+ out_f.close()
+
+ return content_file
+
+ def getMetadataAndContents(self, filename):
+ metadata = {}
+
+ in_f = open(filename, 'rb')
+
+ # grab the metadata and build a dictionary
+ while 1:
+ line = in_f.readline()[:-1]
+ if not line: break
+ key, val = line.split(':', 1)
+ metadata[key] = val
+
+ # grab the rest and stick it in contents
+ contents = in_f.read()
+
+ in_f.close()
+
+ return (metadata, contents)
+
+ def removeFileIfNecessary(self, filename):
+ if self.sud.boolForKey_('cleanup_files'):
+ try:
+ os.remove(filename)
+ except OSError:
+ pass # Sometimes we aren't allowed to delete it
+
+ def putChanges(self):
+ """Save changes to the file back to Zope"""
+ if self.sud.boolForKey_('use_locks') and self.lock_token is None:
+ # We failed to get a lock initially, so try again before saving
+ if not self.lock():
+ # Confirm save without lock
+ if not NSRunAlertPanel('Lock Error',
+ 'Could not acquire lock. '
+ 'Attempt to save to Zope anyway?',
+ 'Yes', 'No', None):
+ return 0
+
+ f = open(self.content_file, 'rb')
+ body = f.read()
+ f.close()
+ headers = {'Content-Type':
+ self.metadata.get('content_type', 'text/plain')}
+
+ if self.lock_token is not None:
+ headers['If'] = '<%s> (<%s>)' % (self.path, self.lock_token)
+
+ response = self.zopeRequest('PUT', headers, body)
+ del body # Don't keep the body around longer then we need to
+
+ if response.status / 100 != 2:
+ # Something went wrong
+ message = response.read()
+ NSLog(message)
+ if NSRunAlertPanel(message,
+ 'Could not save to Zope.\n'
+ 'Error occurred during HTTP put',
+ 'Retry', 'Cancel', None):
+ return self.putChanges()
+ else:
+ return 0
+ return 1
+
+ def lock(self):
+ """Apply a webdav lock to the object in Zope"""
+ if self.lock_token is not None:
+ return 0 # Already have a lock token
+
+ headers = {'Content-Type':'text/xml; charset="utf-8"',
+ 'Timeout':'infinite',
+ 'Depth':'infinity',
+ }
+ body = ('<?xml version="1.0" encoding="utf-8"?>\n'
+ '<d:lockinfo xmlns:d="DAV:">\n'
+ ' <d:lockscope><d:exclusive/></d:lockscope>\n'
+ ' <d:locktype><d:write/></d:locktype>\n'
+ ' <d:depth>infinity</d:depth>\n'
+ ' <d:owner>\n'
+ ' <d:href>Zope External Editor</d:href>\n'
+ ' </d:owner>\n'
+ '</d:lockinfo>'
+ )
+
+ response = self.zopeRequest('LOCK', headers, body)
+
+ if response.status / 100 == 2:
+ # We got our lock, extract the lock token and return it
+ reply = response.read()
+ token_start = reply.find('>opaquelocktoken:')
+ token_end = reply.find('<', token_start)
+ if token_start > 0 and token_end > 0:
+ self.lock_token = reply[token_start+1:token_end]
+ self.did_lock = 1
+ else:
+ # We can't lock her sir!
+ if response.status == 423:
+ message = '(object already locked)'
+ else:
+ message = ''
+
+ if NSRunAlertPanel(response.read(),
+ 'Lock request failed %s' % message,
+ 'Retry', 'Cancel', None):
+ self.lock()
+ else:
+ self.did_lock = 0
+ return self.did_lock
+
+ def unlock(self, interactive=1):
+ """Remove webdav lock from edited zope object"""
+ if not self.did_lock or self.lock_token is None:
+ return 0 # nothing to do
+
+ headers = {'Lock-Token':self.lock_token}
+ response = self.zopeRequest('UNLOCK', headers)
+
+ if interactive and response.status / 100 != 2:
+ # Captain, she's still locked!
+ if NSRunAlertPanel(response.read(),
+ 'Unlock request failed',
+ 'Retry', 'Cancel', None):
+ self.unlock()
+ else:
+ self.did_lock = 0
+ else:
+ self.did_lock = 1
+ self.lock_token = None
+ return self.did_lock
+
+ def zopeRequest(self, method, headers={}, body=''):
+ """Send a request back to Zope"""
+ try:
+ if self.ssl:
+ h = HTTPSConnection(self.host)
+ else:
+ h = HTTPConnection(self.host)
+
+ h.putrequest(method, self.path)
+ h.putheader('User-Agent', 'Zope External Editor/%s' % __version__)
+ h.putheader('Connection', 'close')
+
+ for header, value in headers.items():
+ h.putheader(header, value)
+
+ h.putheader("Content-Length", str(len(body)))
+
+ if self.metadata.get('auth','').startswith('Basic'):
+ h.putheader("Authorization", self.metadata['auth'])
+
+ if self.metadata.get('cookie'):
+ h.putheader("Cookie", self.metadata['cookie'])
+
+ h.endheaders()
+ h.send(body)
+ return h.getresponse()
+ except:
+ # On error return a null response with error info
+ class NullResponse:
+ def getheader(self, n, d=None):
+ return d
+
+ def read(self):
+ return '(No Response From Server)'
+
+ response = NullResponse()
+ response.reason = sys.exc_info()[1]
+
+ try:
+ response.status, response.reason = response.reason
+ except ValueError:
+ response.status = 0
+
+ if response.reason == 'EOF occurred in violation of protocol':
+ # Ignore this protocol error as a workaround for
+ # broken ssl server implementations
+ response.status = 200
+
+ return response
+
+ def __del__(self):
+ """Let's clean up after ourselves, shall we?"""
+ if self.lock_token:
+ self.unlock(interactive=0)
+
+ os.remove(self.getContentFile())
Property changes on: Zem/trunk/ZopeDocument.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Zem/trunk/images/mozilla_config.png
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/images/mozilla_config.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Added: Zem/trunk/images/zem_files_prefs.png
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/images/zem_files_prefs.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Added: Zem/trunk/images/zem_helper_apps_prefs.png
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/images/zem_helper_apps_prefs.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Added: Zem/trunk/images/zem_screenshot_1.png
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/images/zem_screenshot_1.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Added: Zem/trunk/images/zem_screenshot_2.png
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/images/zem_screenshot_2.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Added: Zem/trunk/images/zem_webdav_prefs.png
===================================================================
(Binary files differ)
Property changes on: Zem/trunk/images/zem_webdav_prefs.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Added: Zem/trunk/setup.py
===================================================================
--- Zem/trunk/setup.py 2006-12-20 14:18:52 UTC (rev 71615)
+++ Zem/trunk/setup.py 2006-12-20 14:23:16 UTC (rev 71616)
@@ -0,0 +1,45 @@
+from distutils.core import setup
+import py2app
+
+plist = dict(
+ CFBundleName = "Zem",
+ CFBundleIdentifier = "com.urbanape.zopeeditmanager",
+ CFBundleShortVersionString = "Version 0.9.8",
+ CFBundleGetInfoString = ("Zem version 0.9.8, "
+ "Copyright 2003-2006 Zope Corporation"),
+ NSHumanReadableCopyright = "Copyright 2003-2006 Zope Corporation",
+ CFBundleIconFile = "ZEM.icns",
+ CFBundleInfoDictionaryVersion = "6.0",
+ CFBundlePackageType = "APPL",
+ CFBundleSignature = "ZEDM",
+ CFBundleVersion = "0.9.8",
+ NSMainNibFile = "MainMenu",
+ NSPrincipalClass = "NSApplication",
+ CFBundleDevelopmentRegion = "English",
+ CFBundleDocumentTypes = [
+ dict(CFBundleTypeExtensions = ["zem"],
+ CFBundleTypeOSTypes = ["ZEMD"],
+ CFBundleTypeMIMETypes = ["application/x-zope-edit"],
+ CFBundleTypeRole = "Viewer",
+ CFBundleTypeIconFile = "ZEMDocument.icns")])
+
+setup(
+ data_files = ["Nibs/MainMenu.nib",
+ "Nibs/Preferences.nib",
+ "Resources/Files.png",
+ "Resources/HelperApps.png",
+ "Resources/WebDAV.png",
+ "Resources/ZEM.icns",
+ "Resources/ZEMDocument.icns",
+ "Resources/add_disabled.png",
+ "Resources/add_idle.png",
+ "Resources/add_pressed.png",
+ "Resources/remove_disabled.png",
+ "Resources/remove_idle.png",
+ "Resources/remove_pressed.png",
+ "Resources/com.urbanape.zopeeditmanager.plist"
+ ],
+ app = [dict(
+ script="ZemAppDelegate.py", plist=plist),
+ ],
+ )
Property changes on: Zem/trunk/setup.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
More information about the Checkins
mailing list