| Home | Trees | Indices | Help |
|---|
|
|
1 ##
2 # Copyright (c) 2007-2016 Apple Inc. All rights reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 ##
16
17 """
18 Code based on PyObjC examples included with Apple Developer tools.
19 """
20
21 import Foundation, AppKit, WebKit #@UnusedImport
22
23 from AppKit import * #@UnusedWildImport
24 from AppKit import NSApplication #@UnresolvedImport
25 from AppKit import NSImage #@UnresolvedImport
26 from AppKit import NSMenuItem #@UnresolvedImport
27 from AppKit import NSObject #@UnresolvedImport
28 from AppKit import NSPlainFileType #@UnresolvedImport
29 from AppKit import NSSize #@UnresolvedImport
30 from AppKit import NSToolbar #@UnresolvedImport
31 from AppKit import NSToolbarCustomizeToolbarItemIdentifier #@UnresolvedImport
32 from AppKit import NSToolbarFlexibleSpaceItemIdentifier #@UnresolvedImport
33 from AppKit import NSToolbarItem #@UnresolvedImport
34 from AppKit import NSToolbarPrintItemIdentifier #@UnresolvedImport
35 from AppKit import NSToolbarSeparatorItemIdentifier #@UnresolvedImport
36 from AppKit import NSToolbarSpaceItemIdentifier #@UnresolvedImport
37 from AppKit import NSURL #@UnresolvedImport
38 from AppKit import NSUserDefaults #@UnresolvedImport
39 from AppKit import NSWorkspace #@UnresolvedImport
40
41 from Foundation import * #@UnusedWildImport
42
43 from PyObjCTools import NibClassBuilder, AppHelper
44
45 import objc
46
47 from caldavclientlibrary.protocol.utils import xmlhelpers
48 from caldavclientlibrary.ui.session import Session
49 from xml.etree.ElementTree import _ElementInterface
50 import types
51
52 NibClassBuilder.extractClasses("WebDAVBrowser")
53
54 kServerToolbarItemIdentifier = "WDB: Server Toolbar Identifier"
55 kRefreshToolbarItemIdentifier = "WDB: Refresh Toolbar Identifier"
56 kBrowserViewToolbarItemIdentifier = "WDB: Browser View Toolbar Identifier"
57 kDataViewToolbarItemIdentifier = "WDB: Data View Toolbar Identifier"
58
59 -def addToolbarItem(aController, anIdentifier, aLabel, aPaletteLabel,
60 aToolTip, aTarget, anAction, anItemContent, aMenu):
61 """
62 Add a toolbar button of some kind.
63 """
64 toolbarItem = NSToolbarItem.alloc().initWithItemIdentifier_(anIdentifier)
65
66 toolbarItem.setLabel_(aLabel)
67 toolbarItem.setPaletteLabel_(aPaletteLabel)
68 toolbarItem.setToolTip_(aToolTip)
69 toolbarItem.setTarget_(aTarget)
70 if anAction:
71 toolbarItem.setAction_(anAction)
72
73 if type(anItemContent) == NSImage:
74 toolbarItem.setImage_(anItemContent)
75 else:
76 toolbarItem.setView_(anItemContent)
77 bounds = anItemContent.bounds()
78 minSize = (bounds[1][0], bounds[1][1])
79 maxSize = (bounds[1][0], bounds[1][1])
80 toolbarItem.setMinSize_( minSize )
81 toolbarItem.setMaxSize_( maxSize )
82
83 if aMenu:
84 menuItem = NSMenuItem.alloc().init()
85 menuItem.setSubmenu_(aMenu)
86 menuItem.setTitle_( aMenu.title() )
87 toolbarItem.setMenuFormRepresentation_(menuItem)
88
89 aController._toolbarItems[anIdentifier] = toolbarItem
90
91 WRAPPED={}
93 """
94 NSOutlineView doesn't retain values, which means we cannot use normal
95 python values as values in an outline view.
96 """
100
102 return '<Wrapper for %s>' % self.value
103
105 return str(self)
106
108 if WRAPPED.has_key(obj):
109 return WRAPPED[obj]
110 else:
111 WRAPPED[obj] = Wrapper.alloc().init_(obj)
112 return WRAPPED[obj]
113
118
120 """
121 Class defined in NIB file. This acts as the delegate and responder
122 for the various NSViews and toolbar items. It basically our controller.
123 """
124
125 list = objc.IBOutlet()
126
127 listView = objc.IBOutlet()
128
129 mainSplitterView = objc.IBOutlet()
130
131 passwordText = objc.IBOutlet()
132
133 pathLabel = objc.IBOutlet()
134
135 pathText = objc.IBOutlet()
136
137 progress = objc.IBOutlet()
138
139 propertiesView = objc.IBOutlet()
140
141 serverText = objc.IBOutlet()
142
143 startupSheet = objc.IBOutlet()
144
145 table = objc.IBOutlet()
146
147 text = objc.IBOutlet()
148
149 toolbarBrowserViewButton = objc.IBOutlet()
150
151 toolbarDataViewButton = objc.IBOutlet()
152
153 userText = objc.IBOutlet()
154
155 webView = objc.IBOutlet()
156
157 window = objc.IBOutlet()
158
159 browser = objc.IBOutlet()
160
161 columnView = objc.IBOutlet()
162
163 dataView = objc.IBOutlet()
164
165 BROWSERVIEW_COLUMNS = 0
166 BROWSERVIEW_LIST = 1
167
168 DATAVIEW_PROPERTIES = 0
169 DATAVIEW_DATA = 1
170 #DATAVIEW_DELEGATES = 2
171 #DATAVIEW_ACLS = 3
172
173 selectedDetails = None
174
176 # Initialise our session and selected state parameters
177 self.session = None
178 self.columns = [[]]
179 self.selectedResource = None
180 self.selectedDetails = None
181 self.selectedData = None
182
183 # Cache some useful icons
184 self.fileImage = NSWorkspace.sharedWorkspace().iconForFileType_(NSPlainFileType)
185 self.fileImage.setSize_(NSSize(16, 16))
186 self.directoryImage = NSWorkspace.sharedWorkspace().iconForFile_("/usr/")
187 self.directoryImage.setSize_(NSSize(16, 16))
188
189 # Initialise the toolbar
190 self._toolbarItems = {}
191 self._toolbarDefaultItemIdentifiers = []
192 self._toolbarAllowedItemIdentifiers = []
193 self.createToolbar()
194
195 # Set up browser view
196 container = self.mainSplitterView.subviews()[0]
197 container.addSubview_(self.columnView)
198 container.addSubview_(self.listView)
199 self.currentBrowserView = None
200 self.setBrowserView(self.BROWSERVIEW_COLUMNS)
201 self.browser.setMaxVisibleColumns_(7)
202 self.browser.setMinColumnWidth_(150)
203
204 # Set up data view
205 container = self.mainSplitterView.subviews()[1]
206 container.addSubview_(self.propertiesView)
207 container.addSubview_(self.dataView)
208 self.currentDataView = None
209 self.setDataView(self.DATAVIEW_PROPERTIES)
210 self.text.setString_("")
211
212 self.pathLabel.setStringValue_("No server specified")
213
214 # Get preferences
215 lastServer = NSUserDefaults.standardUserDefaults().stringForKey_("LastServer")
216 if lastServer and len(lastServer):
217 self.serverText.setStringValue_(lastServer)
218 lastPath = NSUserDefaults.standardUserDefaults().stringForKey_("LastPath")
219 if lastPath and len(lastPath):
220 self.pathText.setStringValue_(lastPath)
221 else:
222 self.pathText.setStringValue_("/")
223 lastUser = NSUserDefaults.standardUserDefaults().stringForKey_("LastUser")
224 if lastUser and len(lastUser):
225 self.userText.setStringValue_(lastUser)
226
228 """
229 Create the toolbar for our app.
230 """
231 toolbar = NSToolbar.alloc().initWithIdentifier_("Toolbar")
232 toolbar.setDelegate_(self)
233 toolbar.setAllowsUserCustomization_(YES)
234 toolbar.setAutosavesConfiguration_(YES)
235
236 self.createToolbarItems()
237
238 self.window.setToolbar_(toolbar)
239
241 """
242 Create the toolbar item and define the default and allowed set.
243 """
244 addToolbarItem(self, kServerToolbarItemIdentifier,
245 "Server", "Server", "Reset Server", self,
246 "resetServer:", NSImage.imageNamed_("NSNetwork"), None,)
247
248 addToolbarItem(self, kRefreshToolbarItemIdentifier,
249 "Refresh", "Refresh", "Refresh Display", self,
250 "refreshData:", NSImage.imageNamed_("NSRefresh"), None,)
251
252 addToolbarItem(self, kBrowserViewToolbarItemIdentifier,
253 "Browser", "Browser", "Browser View", self,
254 "changeBrowserView:", self.toolbarBrowserViewButton, None,)
255
256 addToolbarItem(self, kDataViewToolbarItemIdentifier,
257 "View", "View", "Data View", self,
258 "changeDataView:", self.toolbarDataViewButton, None,)
259
260 self._toolbarDefaultItemIdentifiers = [
261 kServerToolbarItemIdentifier,
262 kBrowserViewToolbarItemIdentifier,
263 kDataViewToolbarItemIdentifier,
264 NSToolbarFlexibleSpaceItemIdentifier,
265 kRefreshToolbarItemIdentifier,
266 ]
267
268 self._toolbarAllowedItemIdentifiers = [
269 kServerToolbarItemIdentifier,
270 kBrowserViewToolbarItemIdentifier,
271 kDataViewToolbarItemIdentifier,
272 kRefreshToolbarItemIdentifier,
273 NSToolbarSeparatorItemIdentifier,
274 NSToolbarSpaceItemIdentifier,
275 NSToolbarFlexibleSpaceItemIdentifier,
276 NSToolbarPrintItemIdentifier,
277 NSToolbarCustomizeToolbarItemIdentifier,
278 ]
279
281 """
282 Return the default set of toolbar items.
283 """
284 return self._toolbarDefaultItemIdentifiers
285
287 """
288 Return the allowed set of toolbar items.
289 """
290 return self._toolbarAllowedItemIdentifiers
291
292 - def toolbar_itemForItemIdentifier_willBeInsertedIntoToolbar_(self,
293 toolbar,
294 itemIdentifier, flag):
295 """
296 Delegate method fired when the toolbar is about to insert an
297 item into the toolbar. Item is identified by itemIdentifier.
298
299 Effectively makes a copy of the cached reference instance of
300 the toolbar item identified by itemIdentifier.
301 """
302 newItem = NSToolbarItem.alloc().initWithItemIdentifier_(itemIdentifier)
303 item = self._toolbarItems[itemIdentifier]
304
305 newItem.setLabel_( item.label() )
306 newItem.setPaletteLabel_( item.paletteLabel() )
307 if item.view():
308 newItem.setView_( item.view() )
309 else:
310 newItem.setImage_( item.image() )
311
312 newItem.setToolTip_( item.toolTip() )
313 newItem.setTarget_( item.target() )
314 newItem.setAction_( item.action() )
315 newItem.setMenuFormRepresentation_( item.menuFormRepresentation() )
316
317 if newItem.view():
318 newItem.setMinSize_( item.minSize() )
319 newItem.setMaxSize_( item.maxSize() )
320
321 return newItem
322
324 """
325 Change the browser view pane to the specified list type.
326 """
327 newView = {
328 self.BROWSERVIEW_COLUMNS: self.columnView,
329 self.BROWSERVIEW_LIST : self.listView,
330 }.get(view, None)
331 if self.currentBrowserView != newView:
332 if self.currentBrowserView:
333 self.currentBrowserView.setHidden_(YES)
334 self.currentBrowserView = newView
335 if self.currentBrowserView:
336 self.currentBrowserView.setHidden_(NO)
337 self.browserview = view
338 self.refreshView()
339
340 @objc.IBAction
342 """
343 User clicked a browser toolbar button.
344 """
345 self.setBrowserView(sender.selectedSegment())
346
348 """
349 Change the data view pane to the specified type.
350 """
351 newView = {
352 self.DATAVIEW_PROPERTIES: self.propertiesView,
353 self.DATAVIEW_DATA : self.dataView,
354 }.get(view, None)
355 if self.currentDataView != newView:
356 if self.currentDataView:
357 self.currentDataView.setHidden_(YES)
358 self.currentDataView = newView
359 if self.currentDataView:
360 self.currentDataView.setHidden_(NO)
361 self.dataview = view
362 self.refreshView()
363
364 @objc.IBAction
366 """
367 User clicked a view toolbar button.
368 """
369 self.setDataView(sender.selectedSegment())
370
371 @objc.IBAction
373 """
374 Display the sheet asking for server details.
375 """
376 NSApplication.sharedApplication().beginSheet_modalForWindow_modalDelegate_didEndSelector_contextInfo_(
377 self.startupSheet,
378 self.window,
379 None, None, 0
380 )
381
383 """
384 Force a refresh of the data for the current selected resource.
385 """
386 if self.selectedResource:
387 self.selectedResource.clear()
388
389 self.progress.startAnimation_(self)
390 resources = self.selectedResource.listChildren()
391 self.columns[-1] = resources
392 self.progress.stopAnimation_(self)
393
394 self.refreshView()
395
397 """
398 Refresh the actual data view for the selected resource.
399 """
400 if self.selectedResource:
401 self.progress.startAnimation_(self)
402 if self.dataview == self.DATAVIEW_PROPERTIES:
403 self.selectedDetails = self.selectedResource.getAllDetails()
404 self.table.reloadData()
405 self.table.deselectAll_(self)
406 self.text.setString_("")
407 elif self.dataview == self.DATAVIEW_DATA:
408 self.selectedData = self.selectedResource.getDataAsHTML()
409 url = NSURL.alloc().initWithString_(self.serverText.stringValue())
410 self.webView.mainFrame().loadHTMLString_baseURL_(self.selectedData, url)
411 self.progress.stopAnimation_(self)
412
413 @objc.IBAction
415 """
416 User clicked OK in the server setup sheet.
417 """
418
419 # Create the actual session.
420 server = self.serverText.stringValue()
421 path = self.pathText.stringValue()
422 user = self.userText.stringValue()
423 pswd = self.passwordText.stringValue()
424 self.session = Session(server, path, user, pswd, logging=False)
425 self.window.setTitle_(self.serverText.stringValue())
426 self.pathLabel.setStringValue_(self.session.path)
427 NSUserDefaults.standardUserDefaults().setObject_forKey_(server, "LastServer")
428 NSUserDefaults.standardUserDefaults().setObject_forKey_(path, "LastPath")
429 NSUserDefaults.standardUserDefaults().setObject_forKey_(user, "LastUser")
430
431 # List the root resource.
432 self.progress.startAnimation_(self)
433 resources = self.session.getRoot().listChildren()
434 self.progress.stopAnimation_(self)
435 self.columns = [resources]
436
437 # Done with the sheet.
438 self.startupSheet.close()
439 NSApplication.sharedApplication().endSheet_(self.startupSheet)
440
441 # Force reload of browser pane views.
442 self.browser.loadColumnZero()
443 self.list.reloadItem_(None)
444
445 @objc.IBAction
447 """
448 User clicked the cancel button in the server sheet.
449 """
450 self.startupSheet.close()
451 NSApplication.sharedApplication().endSheet_(self.startupSheet)
452
453 @objc.IBAction
455 """
456 Something changed in the column browser.
457 """
458
459 # Update current path.
460 self.pathLabel.setStringValue_((self.session.path if len(self.session.path) > 1 else "") + browser.path())
461
462 # Get new selected resource and refresh the data view.
463 self.selectedResource = None
464 self.selectedDetails = None
465 col = len(self.columns)
466 row = -1
467 while row == -1:
468 col -= 1
469 if col < 0:
470 break
471 row = self.browser.selectedRowInColumn_(col)
472 if row >= 0:
473 self.selectedResource = self.columns[col][row]
474
475 self.refreshView()
476
478 """
479 Delegate method to set the actual stuff displayed in a column view row.
480 """
481 isLeaf = not self.columns[col][row].isCollection()
482 cell.setLeaf_(isLeaf)
483 cell.setStringValue_(self.columns[col][row].getName())
484 cell.setImage_(self.fileImage if isLeaf else self.directoryImage)
485
487 """
488 Delegate method that returns the number of rows in a column view column.
489 """
490 if col == 0:
491 return len(self.columns[0])
492 del self.columns[col:]
493 resource = self.columns[col - 1][browser.selectedRowInColumn_(col - 1)]
494 self.progress.startAnimation_(self)
495 resources = resource.listChildren()
496 self.progress.stopAnimation_(self)
497 self.columns.append(resources)
498 return len(resources)
499
501 """
502 Delegate method called when the selection in the outline view changes.
503 """
504
505 # Get the new selected resource and refresh the data view.
506 row = self.list.selectedRow()
507 if row == -1:
508 self.selectedResource = None
509 self.pathLabel.setStringValue_("Nothing Selected")
510 else:
511 self.selectedResource = unwrap_object(self.list.itemAtRow_(row))
512 self.pathLabel.setStringValue_(self.selectedResource.getPath())
513
514 self.refreshView()
515
517 """
518 Delegate method to return the number of children of an item in the outline view.
519 """
520 if self.session is None:
521 return 0
522 if item is None:
523 resource = self.session.getRoot()
524 else:
525 resource = unwrap_object(item)
526 self.progress.startAnimation_(self)
527 resources = resource.listChildren()
528 self.progress.stopAnimation_(self)
529 return len(resources)
530
532 """
533 Delegate method to return the whether an item in the outline view is expandable.
534 """
535 if item is None:
536 return YES
537 else:
538 resource = unwrap_object(item)
539 return YES if resource.isCollection() else NO
540
542 """
543 Delegate method to return the item associated with a row in the outline view.
544 """
545 if item is None:
546 resource = self.session.getRoot()
547 else:
548 resource = unwrap_object(item)
549 self.progress.startAnimation_(self)
550 resources = resource.listChildren()
551 self.progress.stopAnimation_(self)
552 return wrap_object(resources[index])
553
555 """
556 Delegate method to return the data displayed in the outline view.
557 """
558 if item is None:
559 resource = self.session.getRoot()
560 else:
561 resource = unwrap_object(item)
562 return {
563 "Name" : resource.getName(),
564 "Size" : resource.getSize(),
565 "Modified": resource.getLastMod(),
566 }[tableColumn.identifier()]
567
568 @objc.IBAction
570 """
571 Called when the selection in the properties list changes.
572 """
573
574 # Get the selected property and display its value.
575 row = self.table.selectedRow()
576 if row >= 0:
577 value = self.selectedDetails[row][1]
578 if type(value) in (types.ListType, types.TupleType,):
579 if len(value) == 1:
580 text = self.propValueToText(value[0])
581 else:
582 sorted = [self.propValueToText(v) for v in value]
583 sorted.sort()
584 text = "\r".join(sorted)
585 else:
586 text = self.propValueToText(value)
587 else:
588 text = ""
589 self.text.setString_(text)
590
592 """
593 Delegate method to return the number of rows in the list.
594 @param tableView:
595 @type tableView:
596 """
597 if self.selectedDetails is None:
598 return 0
599 return len(self.selectedDetails)
600
602 """
603 Delegate method to return the text for a list cell.
604 """
605 return str(self.selectedDetails[row][0])
606
612
614 """
615 Do a sensible print of a property value taking type into account.
616 """
617 if type(value) in (types.StringType, types.UnicodeType, types.IntType):
618 text = str(value)
619 elif isinstance(value, _ElementInterface):
620 text = xmlhelpers.elementToString(value).replace("\n", "")
621 else:
622 text = str(value)
623 return text
624
625 if __name__ == "__main__":
626 AppHelper.runEventLoop()
627
| Home | Trees | Indices | Help |
|---|
| Generated by Epydoc 3.0.1 on Thu Jul 7 15:01:49 2011 | http://epydoc.sourceforge.net |