PageRenderTime 120ms CodeModel.GetById 5ms RepoModel.GetById 0ms app.codeStats 1ms

/core/externals/update-engine/externals/gdata-objectivec-client/Examples/SpreadsheetTableSample/SpreadsheetTableSampleWindowController.m

http://macfuse.googlecode.com/
Objective C | 898 lines | 610 code | 208 blank | 80 comment | 96 complexity | f44c5a650f41f1b1941ebf9e2b3b11d8 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, GPL-2.0
  1. /* Copyright (c) 2009 Google Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. //
  16. // SpreadsheetTableSampleWindowController.m
  17. //
  18. #import "SpreadsheetTableSampleWindowController.h"
  19. @interface SpreadsheetTableSampleWindowController (PrivateMethods)
  20. - (void)updateUI;
  21. - (void)fetchFeedOfSpreadsheets;
  22. - (void)fetchSelectedSpreadsheet;
  23. - (void)fetchSelectedTable;
  24. - (void)addTableToSelectedWorksheet;
  25. - (void)deleteSelectedTable;
  26. - (void)randomizeSelectedTable;
  27. - (GDataServiceGoogleSpreadsheet *)spreadsheetService;
  28. - (GDataEntrySpreadsheet *)selectedSpreadsheet;
  29. - (GDataEntryWorksheet *)selectedWorksheet;
  30. - (GDataEntrySpreadsheetTable *)selectedTable;
  31. - (GDataEntrySpreadsheetRecord *)selectedRecord;
  32. - (GDataFeedSpreadsheet *)spreadsheetFeed;
  33. - (void)setSpreadsheetFeed:(GDataFeedSpreadsheet *)feed;
  34. - (NSError *)spreadsheetFetchError;
  35. - (void)setSpreadsheetFetchError:(NSError *)error;
  36. - (GDataServiceTicket *)spreadsheetFeedTicket;
  37. - (void)setSpreadsheetFeedTicket:(GDataServiceTicket *)obj;
  38. - (GDataFeedWorksheet *)worksheetFeed;
  39. - (void)setWorksheetFeed:(GDataFeedWorksheet *)feed;
  40. - (NSError *)worksheetFetchError;
  41. - (void)setWorksheetFetchError:(NSError *)error;
  42. - (GDataServiceTicket *)worksheetFeedTicket;
  43. - (void)setWorksheetFeedTicket:(GDataServiceTicket *)obj;
  44. - (GDataFeedSpreadsheetTable *)tableFeed;
  45. - (void)setTableFeed:(GDataFeedSpreadsheetTable *)feed;
  46. - (NSError *)tableFetchError;
  47. - (void)setTableFetchError:(NSError *)error;
  48. - (GDataServiceTicket *)tableFeedTicket;
  49. - (void)setTableFeedTicket:(GDataServiceTicket *)obj;
  50. - (GDataFeedSpreadsheetRecord *)recordFeed;
  51. - (void)setRecordFeed:(GDataFeedSpreadsheetRecord *)feed;
  52. - (NSError *)recordFetchError;
  53. - (void)setRecordFetchError:(NSError *)error;
  54. - (GDataServiceTicket *)recordFeedTicket;
  55. - (void)setRecordFeedTicket:(GDataServiceTicket *)obj;
  56. @end
  57. @implementation SpreadsheetTableSampleWindowController
  58. + (SpreadsheetTableSampleWindowController *)sharedWindowController {
  59. static SpreadsheetTableSampleWindowController* gWindowController = nil;
  60. if (!gWindowController) {
  61. gWindowController = [[SpreadsheetTableSampleWindowController alloc] init];
  62. }
  63. return gWindowController;
  64. }
  65. - (id)init {
  66. return [self initWithWindowNibName:@"SpreadsheetTableSampleWindow"];
  67. }
  68. - (void)windowDidLoad {
  69. }
  70. - (void)awakeFromNib {
  71. // Set the result text fields to have a distinctive color and mono-spaced font
  72. [mSpreadsheetResultTextField setTextColor:[NSColor darkGrayColor]];
  73. [mWorksheetResultTextField setTextColor:[NSColor darkGrayColor]];
  74. [mTableResultTextField setTextColor:[NSColor darkGrayColor]];
  75. [mRecordResultTextField setTextColor:[NSColor darkGrayColor]];
  76. NSFont *resultTextFont = [NSFont fontWithName:@"Monaco" size:9];
  77. [mSpreadsheetResultTextField setFont:resultTextFont];
  78. [mWorksheetResultTextField setFont:resultTextFont];
  79. [mTableResultTextField setFont:resultTextFont];
  80. [mRecordResultTextField setFont:resultTextFont];
  81. // add notifications so we can track global starts and stops of fetching
  82. NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
  83. [nc addObserver:self
  84. selector:@selector(fetchStateChanged:)
  85. name:kGTMHTTPFetcherStartedNotification
  86. object:nil];
  87. [nc addObserver:self
  88. selector:@selector(fetchStateChanged:)
  89. name:kGTMHTTPFetcherStoppedNotification
  90. object:nil];
  91. [self updateUI];
  92. }
  93. - (void)dealloc {
  94. [mSpreadsheetFeed release];
  95. [mSpreadsheetFeedTicket release];
  96. [mSpreadsheetFetchError release];
  97. [mWorksheetFeed release];
  98. [mWorksheetFeedTicket release];
  99. [mWorksheetFetchError release];
  100. [mTableFeed release];
  101. [mTableFeedTicket release];
  102. [mTableFetchError release];
  103. [mRecordFeed release];
  104. [mRecordFeedTicket release];
  105. [mRecordFetchError release];
  106. [mRecordUpdateTickets release];
  107. [super dealloc];
  108. }
  109. #pragma mark -
  110. - (void)updateUI {
  111. // spreadsheet list display
  112. [mSpreadsheetTable reloadData];
  113. if (mSpreadsheetFeedTicket != nil) {
  114. [mSpreadsheetProgressIndicator startAnimation:self];
  115. } else {
  116. [mSpreadsheetProgressIndicator stopAnimation:self];
  117. }
  118. // spreadsheet fetch result or selected item
  119. NSString *spreadsheetResultStr = @"";
  120. if (mSpreadsheetFetchError) {
  121. spreadsheetResultStr = [mSpreadsheetFetchError description];
  122. } else {
  123. GDataEntrySpreadsheet *spreadsheet = [self selectedSpreadsheet];
  124. if (spreadsheet) {
  125. spreadsheetResultStr = [spreadsheet description];
  126. }
  127. }
  128. [mSpreadsheetResultTextField setString:spreadsheetResultStr];
  129. // worksheets list display
  130. [mWorksheetTable reloadData];
  131. if (mWorksheetFeedTicket != nil) {
  132. [mWorksheetProgressIndicator startAnimation:self];
  133. } else {
  134. [mWorksheetProgressIndicator stopAnimation:self];
  135. }
  136. // worksheet fetch result or selected item
  137. NSString *worksheetResultStr = @"";
  138. if (mWorksheetFetchError) {
  139. worksheetResultStr = [mWorksheetFetchError description];
  140. } else {
  141. GDataEntryWorksheet *worksheet = [self selectedWorksheet];
  142. if (worksheet) {
  143. worksheetResultStr = [worksheet description];
  144. }
  145. }
  146. [mWorksheetResultTextField setString:worksheetResultStr];
  147. // tables list display
  148. [mTableTable reloadData];
  149. if (mTableFeedTicket != nil) {
  150. [mTableProgressIndicator startAnimation:self];
  151. } else {
  152. [mTableProgressIndicator stopAnimation:self];
  153. }
  154. // table fetch result or selected item
  155. NSString *tableResultStr = @"";
  156. if (mTableFetchError) {
  157. tableResultStr = [mTableFetchError description];
  158. } else {
  159. GDataEntrySpreadsheetTable *table = [self selectedTable];
  160. if (table) {
  161. tableResultStr = [table description];
  162. }
  163. }
  164. [mTableResultTextField setString:tableResultStr];
  165. // record display
  166. [mRecordTable reloadData];
  167. if (mRecordFeedTicket != nil || [mRecordUpdateTickets count] > 0) {
  168. [mRecordProgressIndicator startAnimation:self];
  169. } else {
  170. [mRecordProgressIndicator stopAnimation:self];
  171. }
  172. // record fetch result or selected item
  173. NSString *recordResultStr = @"";
  174. if (mRecordFetchError) {
  175. recordResultStr = [mRecordFetchError description];
  176. } else {
  177. GDataEntrySpreadsheetRecord *record = [self selectedRecord];
  178. if (record) {
  179. recordResultStr = [record description];
  180. }
  181. }
  182. [mRecordResultTextField setString:recordResultStr];
  183. BOOL isWorksheetSelected = ([self selectedWorksheet] != nil);
  184. BOOL canPostToTable = ([mTableFeed postLink] != nil);
  185. BOOL canAddTableToWorksheet = (isWorksheetSelected && canPostToTable);
  186. [mAddTableButton setEnabled:canAddTableToWorksheet];
  187. BOOL isTableSelected = ([self selectedTable] != nil);
  188. [mDeleteTableButton setEnabled:isTableSelected];
  189. BOOL hasEditableRecordFeed = ([mRecordFeed postLink] != nil);
  190. [mRandomizeTableButton setEnabled:hasEditableRecordFeed];
  191. }
  192. #pragma mark IBActions
  193. - (IBAction)getSpreadsheetClicked:(id)sender {
  194. NSCharacterSet *wsSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
  195. NSString *username = [mUsernameField stringValue];
  196. username = [username stringByTrimmingCharactersInSet:wsSet];
  197. if ([username rangeOfString:@"@"].location == NSNotFound) {
  198. // if no domain was supplied, add @gmail.com
  199. username = [username stringByAppendingString:@"@gmail.com"];
  200. }
  201. [mUsernameField setStringValue:username];
  202. [self fetchFeedOfSpreadsheets];
  203. }
  204. - (IBAction)addTableClicked:(id)sender {
  205. [self addTableToSelectedWorksheet];
  206. }
  207. - (IBAction)deleteTableClicked:(id)sender {
  208. GDataEntrySpreadsheetTable *table = [self selectedTable];
  209. NSBeginAlertSheet(@"Delete", nil, @"Cancel", nil,
  210. [self window], self,
  211. @selector(deleteSheetDidEnd:returnCode:contextInfo:),
  212. nil, nil, @"Delete table \"%@\"?",
  213. [[table title] stringValue]);
  214. }
  215. - (void)deleteSheetDidEnd:(NSWindow *)sheet
  216. returnCode:(int)returnCode
  217. contextInfo:(void *)contextInfo {
  218. if (returnCode == NSOKButton) {
  219. [self deleteSelectedTable];
  220. }
  221. }
  222. - (IBAction)randomizeTableClicked:(id)sender {
  223. GDataEntrySpreadsheetTable *table = [self selectedTable];
  224. NSBeginAlertSheet(@"Randomize", nil, @"Cancel", nil,
  225. [self window], self,
  226. @selector(randomizeSheetDidEnd:returnCode:contextInfo:),
  227. nil, nil, @"Load random data into table \"%@\"?",
  228. [[table title] stringValue]);
  229. }
  230. - (void)randomizeSheetDidEnd:(NSWindow *)sheet
  231. returnCode:(int)returnCode
  232. contextInfo:(void *)contextInfo {
  233. if (returnCode == NSOKButton) {
  234. [self randomizeSelectedTable];
  235. }
  236. }
  237. - (IBAction)loggingCheckboxClicked:(id)sender {
  238. [GTMHTTPFetcher setLoggingEnabled:[sender state]];
  239. }
  240. #pragma mark -
  241. // get a spreadsheet service object with the current username/password
  242. //
  243. // A "service" object handles networking tasks. Service objects
  244. // contain user authentication information as well as networking
  245. // state information (such as cookies and the "last modified" date for
  246. // fetched data.)
  247. - (GDataServiceGoogleSpreadsheet *)spreadsheetService {
  248. static GDataServiceGoogleSpreadsheet* service = nil;
  249. if (!service) {
  250. service = [[GDataServiceGoogleSpreadsheet alloc] init];
  251. [service setShouldCacheResponseData:YES];
  252. [service setServiceShouldFollowNextLinks:YES];
  253. // iPhone apps will typically disable caching dated data or will call
  254. // clearLastModifiedDates after done fetching to avoid wasting
  255. // memory.
  256. }
  257. // username/password may change
  258. NSString *username = [mUsernameField stringValue];
  259. NSString *password = [mPasswordField stringValue];
  260. [service setUserAgent:@"MyCompany-SampleSpreadsheetApp-1.0"]; // set this to yourName-appName-appVersion
  261. [service setUserCredentialsWithUsername:username
  262. password:password];
  263. return service;
  264. }
  265. // get the spreadsheet selected in the top list, or nil if none
  266. - (GDataEntrySpreadsheet *)selectedSpreadsheet {
  267. NSArray *spreadsheets = [mSpreadsheetFeed entries];
  268. int rowIndex = [mSpreadsheetTable selectedRow];
  269. if ([spreadsheets count] > 0 && rowIndex > -1) {
  270. GDataEntrySpreadsheet *spreadsheet = [spreadsheets objectAtIndex:rowIndex];
  271. return spreadsheet;
  272. }
  273. return nil;
  274. }
  275. // get the worksheet selected in the second list, or nil if none
  276. - (GDataEntryWorksheet *)selectedWorksheet {
  277. NSArray *worksheets = [mWorksheetFeed entries];
  278. int rowIndex = [mWorksheetTable selectedRow];
  279. if ([worksheets count] > 0 && rowIndex > -1) {
  280. GDataEntryWorksheet *worksheet = [worksheets objectAtIndex:rowIndex];
  281. return worksheet;
  282. }
  283. return nil;
  284. }
  285. // get the table selected in the third list, or nil if none
  286. - (GDataEntrySpreadsheetTable *)selectedTable {
  287. NSArray *tables = [mTableFeed entries];
  288. int rowIndex = [mTableTable selectedRow];
  289. if ([tables count] > 0 && rowIndex > -1) {
  290. GDataEntrySpreadsheetTable *table = [tables objectAtIndex:rowIndex];
  291. return table;
  292. }
  293. return nil;
  294. }
  295. // get the record selected in the bottom list
  296. - (GDataEntrySpreadsheetRecord *)selectedRecord {
  297. NSArray *records = [mRecordFeed entries];
  298. int rowIndex = [mRecordTable selectedRow];
  299. if ([records count] > 0 && rowIndex > -1) {
  300. GDataEntrySpreadsheetRecord *record = [records objectAtIndex:rowIndex];
  301. return record;
  302. }
  303. return nil;
  304. }
  305. #pragma mark Fetch feed of all of the user's spreadsheets
  306. // begin retrieving the list of the user's spreadsheets
  307. - (void)fetchFeedOfSpreadsheets {
  308. [self setSpreadsheetFeed:nil];
  309. [self setSpreadsheetFetchError:nil];
  310. [self setWorksheetFeed:nil];
  311. [self setWorksheetFeedTicket:nil];
  312. [self setWorksheetFetchError:nil];
  313. [self setTableFeed:nil];
  314. [self setTableFeedTicket:nil];
  315. [self setTableFetchError:nil];
  316. [self setRecordFeed:nil];
  317. [self setRecordFeedTicket:nil];
  318. [self setRecordFetchError:nil];
  319. GDataServiceGoogleSpreadsheet *service = [self spreadsheetService];
  320. NSURL *feedURL = [NSURL URLWithString:kGDataGoogleSpreadsheetsPrivateFullFeed];
  321. GDataServiceTicket *ticket;
  322. ticket = [service fetchFeedWithURL:feedURL
  323. delegate:self
  324. didFinishSelector:@selector(spreadsheetsTicket:finishedWithFeed:error:)];
  325. [self setSpreadsheetFeedTicket:ticket];
  326. [self updateUI];
  327. }
  328. // spreadsheet feed fetch callback
  329. - (void)spreadsheetsTicket:(GDataServiceTicket *)ticket
  330. finishedWithFeed:(GDataFeedSpreadsheet *)feed
  331. error:(NSError *)error {
  332. [self setSpreadsheetFeed:feed];
  333. [self setSpreadsheetFetchError:error];
  334. [self setSpreadsheetFeedTicket:nil];
  335. [self updateUI];
  336. }
  337. #pragma mark Fetch a spreadsheet's worksheets and tables
  338. // for the spreadsheet selected in the top list, begin retrieving the lists of
  339. // worksheets and tables
  340. - (void)fetchSelectedSpreadsheet {
  341. GDataEntrySpreadsheet *spreadsheet = [self selectedSpreadsheet];
  342. if (spreadsheet) {
  343. GDataServiceGoogleSpreadsheet *service = [self spreadsheetService];
  344. // fetch the feed of worksheets
  345. NSURL *worksheetsFeedURL = [spreadsheet worksheetsFeedURL];
  346. if (worksheetsFeedURL) {
  347. [self setWorksheetFeed:nil];
  348. [self setWorksheetFetchError:nil];
  349. GDataServiceTicket *ticket;
  350. ticket = [service fetchFeedWithURL:worksheetsFeedURL
  351. delegate:self
  352. didFinishSelector:@selector(worksheetsTicket:finishedWithFeed:error:)];
  353. [self setWorksheetFeedTicket:ticket];
  354. }
  355. // fetch the feed of tables
  356. NSURL *tablesFeedURL = [[spreadsheet tablesFeedLink] URL];
  357. // TODO - temporary code -
  358. // rely just on the link to the tables feed once that finally is available
  359. if (tablesFeedURL == nil) {
  360. NSString *key = [[spreadsheet identifier] lastPathComponent];
  361. NSString *template = @"http://spreadsheets.google.com/feeds/%@/tables";
  362. NSString *tableFeedURLString = [NSString stringWithFormat:template, key];
  363. tablesFeedURL = [NSURL URLWithString:tableFeedURLString];
  364. }
  365. if (tablesFeedURL) {
  366. [self setTableFeed:nil];
  367. [self setTableFetchError:nil];
  368. // clear the record feed, since the user will need to select a table again
  369. // and the record feed will be refetched
  370. [self setRecordFeed:nil];
  371. [self setRecordFetchError:nil];
  372. GDataServiceTicket *ticket;
  373. ticket = [service fetchFeedWithURL:tablesFeedURL
  374. delegate:self
  375. didFinishSelector:@selector(tablesTicket:finishedWithFeed:error:)];
  376. [self setTableFeedTicket:ticket];
  377. }
  378. [self updateUI];
  379. }
  380. }
  381. // worksheets feed fetch callback
  382. - (void)worksheetsTicket:(GDataServiceTicket *)ticket
  383. finishedWithFeed:(GDataFeedWorksheet *)feed
  384. error:(NSError *)error {
  385. [self setWorksheetFeed:feed];
  386. [self setWorksheetFetchError:error];
  387. [self setWorksheetFeedTicket:nil];
  388. [self updateUI];
  389. }
  390. // tables feed fetch callback
  391. - (void)tablesTicket:(GDataServiceTicket *)ticket
  392. finishedWithFeed:(GDataFeedSpreadsheetTable *)feed
  393. error:(NSError *)error {
  394. [self setTableFeed:feed];
  395. [self setTableFetchError:error];
  396. [self setTableFeedTicket:nil];
  397. [self updateUI];
  398. }
  399. #pragma mark Fetch a table's records
  400. - (void)fetchSelectedTable {
  401. GDataEntrySpreadsheetTable *table = [self selectedTable];
  402. if (table) {
  403. GDataServiceGoogleSpreadsheet *service = [self spreadsheetService];
  404. // fetch the feed of records
  405. NSURL *recordFeedURL = [table recordFeedURL];
  406. if (recordFeedURL) {
  407. [self setRecordFeed:nil];
  408. [self setRecordFetchError:nil];
  409. GDataServiceTicket *ticket;
  410. ticket = [service fetchFeedWithURL:recordFeedURL
  411. delegate:self
  412. didFinishSelector:@selector(recordsTicket:finishedWithFeed:error:)];
  413. [self setRecordFeedTicket:ticket];
  414. [self updateUI];
  415. }
  416. }
  417. }
  418. // records feed fetch callback
  419. - (void)recordsTicket:(GDataServiceTicket *)ticket
  420. finishedWithFeed:(GDataFeedSpreadsheetRecord *)feed
  421. error:(NSError *)error {
  422. [self setRecordFeed:feed];
  423. [self setRecordFetchError:error];
  424. [self setRecordFeedTicket:nil];
  425. [self updateUI];
  426. }
  427. #pragma mark Add a table to the selected worksheet
  428. - (void)addTableToSelectedWorksheet {
  429. GDataEntryWorksheet *selectedWorksheet = [self selectedWorksheet];
  430. NSString *worksheetName = [[selectedWorksheet title] stringValue];
  431. NSURL *postURL = [[mTableFeed postLink] URL];
  432. if (worksheetName != nil && postURL != nil) {
  433. // add a 2-column, 3-row table to the selected worksheet
  434. GDataEntrySpreadsheetTable *newEntry;
  435. newEntry = [GDataEntrySpreadsheetTable tableEntry];
  436. NSString *title = [NSString stringWithFormat:@"Table Created %@",
  437. [NSDate date]];
  438. [newEntry setTitleWithString:title];
  439. [newEntry setWorksheetNameWithString:worksheetName];
  440. [newEntry setSpreadsheetHeaderWithRow:3];
  441. GDataSpreadsheetData *spData;
  442. spData = [GDataSpreadsheetData spreadsheetDataWithStartIndex:4
  443. numberOfRows:3
  444. insertionMode:kGDataSpreadsheetModeInsert];
  445. [spData addColumn:[GDataSpreadsheetColumn columnWithIndexString:@"A"
  446. name:@"Column Alpha"]];
  447. [spData addColumn:[GDataSpreadsheetColumn columnWithIndexString:@"B"
  448. name:@"Column Beta"]];
  449. [newEntry setSpreadsheetData:spData];
  450. GDataServiceGoogleSpreadsheet *service = [self spreadsheetService];
  451. GDataServiceTicket *ticket;
  452. ticket = [service fetchEntryByInsertingEntry:newEntry
  453. forFeedURL:postURL
  454. delegate:self
  455. didFinishSelector:@selector(addTableTicket:finishedWithEntry:error:)];
  456. }
  457. }
  458. - (void)addTableTicket:(GDataServiceTicket *)ticket
  459. finishedWithEntry:(GDataEntrySpreadsheetTable *)entry
  460. error:(NSError *)error {
  461. if (error == nil) {
  462. NSBeginAlertSheet(@"Table added", nil, nil, nil,
  463. [self window], nil, nil,
  464. nil, nil, @"Added table \"%@\"",
  465. [[entry title] stringValue]);
  466. [self fetchSelectedSpreadsheet];
  467. } else {
  468. NSBeginAlertSheet(@"Add Table Error", nil, nil, nil,
  469. [self window], nil, nil,
  470. nil, nil, @"%@", error);
  471. }
  472. }
  473. #pragma mark Delete the selected table
  474. - (void)deleteSelectedTable {
  475. GDataEntrySpreadsheetTable *selectedTable = [self selectedTable];
  476. if (selectedTable) {
  477. GDataServiceGoogleSpreadsheet *service = [self spreadsheetService];
  478. GDataServiceTicket *ticket;
  479. ticket = [service deleteEntry:selectedTable
  480. delegate:self
  481. didFinishSelector:@selector(deleteTableTicket:finishedWithNil:error:)];
  482. // save the name in the ticket
  483. [ticket setProperty:[[selectedTable title] stringValue]
  484. forKey:@"tableName"];
  485. }
  486. }
  487. - (void)deleteTableTicket:(GDataServiceTicket *)ticket
  488. finishedWithNil:(GDataObject *)nilObj
  489. error:(NSError *)error {
  490. if (error == nil) {
  491. // succeeded
  492. NSString *tableName = [ticket propertyForKey:@"tableName"];
  493. NSBeginAlertSheet(@"Table deleted", nil, nil, nil,
  494. [self window], nil, nil,
  495. nil, nil, @"Deleted table \"%@\"", tableName);
  496. [self fetchSelectedSpreadsheet];
  497. } else {
  498. // failed
  499. NSBeginAlertSheet(@"Delete Table Error", nil, nil, nil,
  500. [self window], nil, nil,
  501. nil, nil, @"%@", error);
  502. }
  503. }
  504. #pragma mark Randomize the data in the records of the selected table
  505. - (void)randomizeSelectedTable {
  506. if (mRecordFeed != nil) {
  507. NSArray *words = [NSArray arrayWithObjects:@"cat", @"dog", @"unicycle",
  508. @"airplane", @"boat", @"treehouse", @"doghouse",
  509. @"clouds", @"moon", @"sun", @"mars", @"venus", nil];
  510. // for each field in each record, assign a random word
  511. for (GDataEntrySpreadsheetRecord *recordEntry in mRecordFeed) {
  512. for (GDataSpreadsheetField *field in [recordEntry fields]) {
  513. NSString *word = [words objectAtIndex:(random() % [words count])];
  514. [field setValue:word];
  515. }
  516. // if this API supported batch updates, we wouldn't have to fetch
  517. // once per record here
  518. GDataServiceGoogleSpreadsheet *service = [self spreadsheetService];
  519. GDataServiceTicket *ticket;
  520. ticket = [service fetchEntryByUpdatingEntry:recordEntry
  521. delegate:self
  522. didFinishSelector:@selector(editRecordTicket:finishedWithEntry:error:)];
  523. if (mRecordUpdateTickets == nil) {
  524. mRecordUpdateTickets = [[NSMutableArray alloc] init];
  525. }
  526. [mRecordUpdateTickets addObject:ticket];
  527. }
  528. }
  529. }
  530. - (void)editRecordTicket:(GDataServiceTicket *)ticket
  531. finishedWithEntry:(GDataEntrySpreadsheetTable *)entry
  532. error:(NSError *)error {
  533. [mRecordUpdateTickets removeObject:ticket];
  534. if (error == nil) {
  535. // succeeded
  536. if ([mRecordUpdateTickets count] == 0) {
  537. // no more udpate tickets pending, so refresh the table's list of records
  538. [self fetchSelectedTable];
  539. }
  540. } else {
  541. // failed
  542. NSLog(@"record update error: %@", error);
  543. }
  544. [self updateUI];
  545. }
  546. #pragma mark Global fetch progress indicator
  547. - (void)fetchStateChanged:(NSNotification *)note {
  548. // This notification observer is invoked whenever fetching starts or stops.
  549. //
  550. // If we turn on fetch retries in the service or the ticket, we can also
  551. // display an indicator of fetch retry delays by observing
  552. // kGTMHTTPFetcherRetryDelayStartedNotification and
  553. // kGTMHTTPFetcherRetryDelayStoppedNotification
  554. static int gCounter = 0;
  555. if ([[note name] isEqual:kGTMHTTPFetcherStartedNotification]) {
  556. // started
  557. ++gCounter;
  558. } else {
  559. // stopped
  560. --gCounter;
  561. }
  562. if (gCounter > 0) {
  563. [mGlobalFetchProgressIndicator startAnimation:self];
  564. } else {
  565. [mGlobalFetchProgressIndicator stopAnimation:self];
  566. }
  567. }
  568. #pragma mark TableView delegate and data source methods
  569. - (void)tableViewSelectionDidChange:(NSNotification *)notification {
  570. id obj = [notification object];
  571. if (obj == mSpreadsheetTable) {
  572. // the user clicked on a spreadsheet, so fetch its worksheets and tables
  573. [self fetchSelectedSpreadsheet];
  574. } else if (obj == mTableTable) {
  575. // the user clicked on a table, so fetch its records
  576. [self fetchSelectedTable];
  577. } else {
  578. // just update the results view for the selected item
  579. [self updateUI];
  580. }
  581. }
  582. // table view data source methods
  583. - (GDataFeedBase *)feedForTableView:(NSTableView *)tableView {
  584. if (tableView == mSpreadsheetTable) return mSpreadsheetFeed;
  585. if (tableView == mWorksheetTable) return mWorksheetFeed;
  586. if (tableView == mTableTable) return mTableFeed;
  587. if (tableView == mRecordTable) return mRecordFeed;
  588. return nil;
  589. }
  590. - (int)numberOfRowsInTableView:(NSTableView *)tableView {
  591. GDataFeedBase *feed = [self feedForTableView:tableView];
  592. return [[feed entries] count];
  593. }
  594. - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row {
  595. GDataFeedBase *feed = [self feedForTableView:tableView];
  596. GDataEntryBase *entry = [[feed entries] objectAtIndex:row];
  597. if (tableView == mRecordTable) {
  598. // for records, return the content, since it conveniently summarizes all
  599. // fields of the record
  600. return [[entry content] stringValue];
  601. } else {
  602. return [[entry title] stringValue];
  603. }
  604. }
  605. #pragma mark Setters and Getters
  606. - (GDataFeedSpreadsheet *)spreadsheetFeed {
  607. return mSpreadsheetFeed;
  608. }
  609. - (void)setSpreadsheetFeed:(GDataFeedSpreadsheet *)feed {
  610. [mSpreadsheetFeed autorelease];
  611. mSpreadsheetFeed = [feed retain];
  612. }
  613. - (NSError *)spreadsheetFetchError {
  614. return mSpreadsheetFetchError;
  615. }
  616. - (void)setSpreadsheetFetchError:(NSError *)error {
  617. [mSpreadsheetFetchError release];
  618. mSpreadsheetFetchError = [error retain];
  619. }
  620. - (GDataServiceTicket *)spreadsheetFeedTicket {
  621. return mSpreadsheetFeedTicket;
  622. }
  623. - (void)setSpreadsheetFeedTicket:(GDataServiceTicket *)obj {
  624. [mSpreadsheetFeedTicket autorelease];
  625. mSpreadsheetFeedTicket = [obj retain];
  626. }
  627. - (GDataFeedWorksheet *)worksheetFeed {
  628. return mWorksheetFeed;
  629. }
  630. - (void)setWorksheetFeed:(GDataFeedWorksheet *)feed {
  631. [mWorksheetFeed autorelease];
  632. mWorksheetFeed = [feed retain];
  633. }
  634. - (NSError *)worksheetFetchError {
  635. return mWorksheetFetchError;
  636. }
  637. - (void)setWorksheetFetchError:(NSError *)error {
  638. [mWorksheetFetchError release];
  639. mWorksheetFetchError = [error retain];
  640. }
  641. - (GDataServiceTicket *)worksheetFeedTicket {
  642. return mWorksheetFeedTicket;
  643. }
  644. - (void)setWorksheetFeedTicket:(GDataServiceTicket *)obj {
  645. [mWorksheetFeedTicket autorelease];
  646. mWorksheetFeedTicket = [obj retain];
  647. }
  648. - (GDataFeedSpreadsheetTable *)tableFeed {
  649. return mTableFeed;
  650. }
  651. - (void)setTableFeed:(GDataFeedSpreadsheetTable *)feed {
  652. [mTableFeed autorelease];
  653. mTableFeed = [feed retain];
  654. }
  655. - (NSError *)tableFetchError {
  656. return mTableFetchError;
  657. }
  658. - (void)setTableFetchError:(NSError *)error {
  659. [mTableFetchError release];
  660. mTableFetchError = [error retain];
  661. }
  662. - (GDataServiceTicket *)tableFeedTicket {
  663. return mTableFeedTicket;
  664. }
  665. - (void)setTableFeedTicket:(GDataServiceTicket *)obj {
  666. [mTableFeedTicket autorelease];
  667. mTableFeedTicket = [obj retain];
  668. }
  669. - (GDataFeedSpreadsheetRecord *)recordFeed {
  670. return mRecordFeed;
  671. }
  672. - (void)setRecordFeed:(GDataFeedSpreadsheetRecord *)feed {
  673. [mRecordFeed autorelease];
  674. mRecordFeed = [feed retain];
  675. }
  676. - (NSError *)recordFetchError {
  677. return mRecordFetchError;
  678. }
  679. - (void)setRecordFetchError:(NSError *)error {
  680. [mRecordFetchError release];
  681. mRecordFetchError = [error retain];
  682. }
  683. - (GDataServiceTicket *)recordFeedTicket {
  684. return mRecordFeedTicket;
  685. }
  686. - (void)setRecordFeedTicket:(GDataServiceTicket *)obj {
  687. [mRecordFeedTicket autorelease];
  688. mRecordFeedTicket = [obj retain];
  689. }
  690. @end