accesspane.js
Go to the documentation of this file.
1 /* accesspane.js
2  * This will be loaded into the main FolderSync control tab. It conncts to
3  * all central controllers and performs all UI-related stuff in the tab.
4  */
5 // Make a namespace.
6 if (typeof foldersync == 'undefined') {
7  var foldersync = {};
8 };
9 
10 /* Accesspane controller
11  * Performs all UI-related stuff in the tab.
12  */
13 foldersync.accesspane = {
14  // If this is true our listeners may cancel the current sync
15  _cancel: false,
16 
17  // The error message for the last failed sync, see foldersync.sync
18  _details: null,
19 
20  /* Show the current box with given text / buttons
21  * text (string): the current message text
22  * progress (int): the current progress in % or null for undetermined
23  * sync (bool): weather we're in sync or not
24  * fail (bool): weather we got details to display or not
25  */
26  _updateCrt: function(text,progress,sync,fail){
27  // Show status box
28  document.getElementById("foldersync-current-box").setAttribute("style","");
29  // Show cancel button in sync
30  document.getElementById("foldersync-current-cancel").
31  setAttribute("style",sync ? "" : "display:none");
32  // Show details button on failed syncs
33  document.getElementById("foldersync-current-details").
34  setAttribute("style",fail ? "" : "display:none");
35  // Update text / progress bar
36  document.getElementById("foldersync-current-state").value = text;
37  document.getElementById("foldersync-current-progress").
38  setAttribute("mode",progress ? "determined" :
39  "undetermined");
40  document.getElementById("foldersync-current-progress").
41  value = progress ? progress : 0;
42  },
43 
44  // Update the queue field
45  _updateQueue: function(){
46  var numQueued = foldersync.sync.getQueue().length;
47  if (numQueued){
48  // Show queue
49  document.getElementById("foldersync-queue-box").
50  setAttribute("style", "");
51  // Display number of queued items
52  var msg = foldersync.central.getLocaleString("status.queued");
53  msg = msg.replace("%d", numQueued);
54  document.getElementById("foldersync-queue-state").value = msg;
55  } else {
56  // Hide queue
57  document.getElementById("foldersync-queue-box").
58  setAttribute("style", "display:none");
59  }
60  },
61 
62  // the tab listener
63  _listener: function(state, object) {
64  // Update queue status box
65  if ((state.event == "added") || (state.event == "removed") ||
66  (state.event == "started"))
67  foldersync.accesspane._updateQueue();
68  // Update status box
69  var msg = "";
70  if ((state.event == "started") ||
71  (state.event == "initing")){
72  msg = foldersync.central.getLocaleString("status.init");
73  msg += ": " + object.sync.targetFolder;
74  foldersync.accesspane._updateCrt(msg, null, true, false);
75  }
76  if ((state.event == "started-sync")||
77  (state.event == "status-update")){
78  msg = foldersync.central.getLocaleString("status.sync");
79  msg += ": " + object.sync.targetFolder;
80  foldersync.accesspane._updateCrt(msg, state.value, true, false);
81  }
82  if (state.event == "completed"){
83  msg = foldersync.central.getLocaleString("status.completed");
84  msg += ": " + object.sync.targetFolder;
85  foldersync.accesspane._updateCrt(msg, state.value, false, false);
86  }
87  if (state.event == "cancelled"){
88  msg = foldersync.central.getLocaleString("status.cancelled");
89  msg += ": " + object.sync.targetFolder;
90  foldersync.accesspane._updateCrt(msg, state.value, false, false);
91  // Make sure cancel button is not disabled, if we cancelled
92  document.getElementById("foldersync-current-cancel").
93  setAttribute("disabled","false");
94  // Make sure it does not look like we're working
95  document.getElementById("foldersync-current-progress").
96  setAttribute("mode", "determined");
97  }
98  var error = foldersync.sync.generateErrorMessage(state);
99  if (error){
100  msg = error.error + ": " + object.sync.targetFolder;
101  foldersync.accesspane._updateCrt(msg, 100, false, true);
102  // Save error details
103  foldersync.accesspane._details = error;
104  }
105 
106  // Cancel if user set cancel
107  if (foldersync.accesspane._cancel)
108  if ((state.event == "started-sync") ||
109  (state.event == "status-update")){
110  object.cancel = true;
111  foldersync.accesspane._cancel = false;
112  }
113 
114  // Show notification above the "normal" status if we finished the sync
115  if (!(error || (state.event == "completed")))
116  return;
117  var fNotify = document.getElementById("foldersync-current-notification");
118  if (!fNotify)
119  return;
120  var level = error ? (error.fatal ? 8 : 5) : 2;
121  fNotify.appendNotification(msg,
122  level,
123  "chrome://foldersync/skin/node.png",
124  level,
125  error ? [{
126  accessKey: null,
127  callback: function(){
128  foldersync.accesspane.
129  showDetails(error);
130  },
131  label: foldersync.central.
132  getLocaleString(
133  "notification.details"),
134  popup: null,
135  }] : []);
136  },
137 
138  // Startup code for the tab
139  onLoad: function(e){
140  foldersync.central.logEvent("accesspane", "Accesspane controller " +
141  "initialisation started.", 5);
142  // Register tab listener
143  foldersync.sync.addListener(this._listener);
144  // Refister at central controller
145  foldersync.central.registerUI();
146  // Get UI prefs
147  var ui = foldersync.preferences.getUIPrefs();
148  // Helper for hiding XUL elements
149  var hide = function(id){
150  document.getElementById(id).setAttribute("style","display:none");
151  };
152  if (ui.show.favorites)
153  // Init the Favorite list
154  this.favorite._init();
155  else {
156  // Hide Favorite list
157  hide("foldersync-favorite-box");
158  hide("foldersync-direct-add");
159  hide("foldersync-direct-update");
160  }
161  if (!ui.show.help)
162  // Hide help section
163  hide("foldersync-help-box");
164  // Init the Profile list
165  this.profile._init();
166  // Init the Playlist list
167  this.playlists._init();
168  // Load data from prior session, if any
169  if (ui.lastUI){
170  this.target.setFolder(ui.lastUI.target);
171  this.playlists.setGUIDs(ui.lastUI.playlists);
172  var profile = foldersync.preferences.getProfileByGUID(ui.lastUI.profile);
173  if (profile)
174  this.profile.setProfile(profile);
175  else
176  foldersync.central.logEvent("accesspane",
177  "There is no valid Profile avaiable " +
178  "for last UI. Skip Profile restore. ", 2,
179  "chrome://foldersync/content/" +
180  "accesspane.js");
181  }
182  // Show the user the sync thread is running, if so
183  if (foldersync.sync.isSyncing()){
184  // Display sync box, without text and without determined progress
185  this._updateCrt("", null, true, false);
186  // Update queue status
187  this._updateQueue();
188  }
189  foldersync.central.logEvent("accesspane",
190  "Accesspane controller started.", 4);
191  },
192 
193  // Shutdown code for the tab
194  onUnload: function(e){
195  foldersync.central.logEvent("accesspane", "Accesspane controller " +
196  "shutdown started.", 5);
197  // Remove tab listener
198  foldersync.sync.removeListener(this._listener);
199 
200  // Store UI data for next time the user opens the tab
201  var ui = foldersync.preferences.getUIPrefs();
202  if (!ui.lastUI)
203  ui.lastUI = {};
204  // delete old temporary profile if there was a custom profile last time
205  var oProfile = foldersync.preferences.getProfileByGUID(ui.lastUI.profile);
206  if (oProfile && !oProfile.visible)
207  foldersync.preferences.removeProfile(oProfile);
208  // Save data
209  ui.lastUI.target = this.target.getFolder();
210  ui.lastUI.playlists = this.playlists.getGUIDs();
211  ui.lastUI.profile = this.profile.getGUID();
212  foldersync.preferences.
213  getProfileByGUID(ui.lastUI.profile).temporary = false;
214 
215  // Unregister at central controller
216  foldersync.central.unregisterUI();
217  foldersync.central.logEvent("accesspane",
218  "Accesspane controller stopped.", 4);
219  },
220 
221  // Cancel current sync
222  cancelSync: function(){
223  this._cancel = true;
224  document.getElementById("foldersync-current-cancel").
225  setAttribute("disabled","true");
226  },
227 
228  // Cancels the whole sync queue
229  cancelQueue: function(){
230  try {
231  var queue = foldersync.sync.getQueue();
232  for each (var e in queue)
233  foldersync.sync.removeFromQueue(e);
234  } catch (e){
235  foldersync.central.logEvent("accesspane",
236  "Cancelling queue failed:\n\n" + e, 1,
237  "chrome://foldersync/content/accesspane.js",
238  e.lineNumber);
239  }
240  },
241 
242  /* Shows details on error
243  * error (error message): the error message to show, or null for the last one
244  */
245  showDetails: function(error){
246  var aError = error;
247  if (!aError)
248  aError = this._details;
249  if (aError)
250  foldersync.central.showDialog(aError.error,
251  aError.message);
252  else
253  foldersync.central.logEvent("accesspane",
254  "showDetails has no details to show", 2,
255  "chrome://foldersync/content/accesspane.js");
256  },
257 
258  // Start a Sync with currently entered values
259  startSync: function(){
260  try {
261  var sync = this.getSync();
262  foldersync.sync.performSync(sync);
263  } catch(e){
264  foldersync.central.logEvent("accesspane",
265  "Starting Sync failed:\n\n" + e, 1,
266  "chrome://foldersync/content/accesspane.js",
267  e.lineNumber);
268  }
269  },
270 
271  // Get the current data as sync object
272  getSync: function(){
273  try {
274  return foldersync.sync.generateSync(this.target.getFolder(),
275  this.profile.getGUID(),
276  this.playlists.getGUIDs());
277  } catch(e){
278  foldersync.central.logEvent("accesspane",
279  "Generating Sync failed:\n\n" + e, 1,
280  "chrome://foldersync/content/accesspane.js",
281  e.lineNumber);
282  }
283  },
284 
285  // All profile related things
286  profile: {
287  // displays profile preferences
288  show: function(){
289  document.getElementById("foldersync-profile-box").
290  setAttribute("style", "");
291  document.getElementById("foldersync-profile-collapse").
292  selectedIndex = 1;
293  },
294 
295  // displays profile preferences
296  hide: function(){
297  document.getElementById("foldersync-profile-box").
298  setAttribute("style", "display:none");
299  document.getElementById("foldersync-profile-collapse").
300  selectedIndex = 0;
301  },
302 
303  // set to changed profile, called on any change
304  onChange: function(){
305  document.getElementById("foldersync-profile").selectedIndex = 0;
306  this.changeProfile();
307 
308  // notify favorite controller of change
309  foldersync.accesspane.favorite.onChange();
310  },
311 
312  // Open non-modal dialog showing available expressions in schema
313  openAvailableTags: function(){
314  try{
315  window.openDialog("chrome://foldersync/content/dialogs/" +
316  "availabletags.xul",
317  "foldersync-availabletags-dialog",
318  "dialog=yes,modal=no,alwaysLowered=no," +
319  "centerscreen=yes,resizable=yes,dependent=yes");
320  } catch (e){
321  foldersync.central.logEvent("accesspane-profile",
322  "Open Available Tag Dialog failed:\n\n" +
323  e, 1, "chrome://foldersync/content/" +
324  "accesspane.js", e.lineNumber);
325  }
326  },
327 
328  /* Enable or disable a node and all its child nodes
329  * area (node): the xul node
330  * enabled (bool): the element should get enabled
331  */
332  _enableArea: function(area, enabled){
333  // Exclude captions because they look... in disabled state.
334  if (area.nodeName != "caption")
335  area.disabled = !enabled;
336  for each (var child in area.childNodes)
337  this._enableArea(child, enabled);
338  },
339 
340  // make sure areas that should be inactive are disabled
341  updateArea: function(){
342  // helper
343  var ea = function(id, cid){
344  var self = foldersync.accesspane.profile;
345  self._enableArea(document.getElementById(id),
346  document.getElementById(cid).checked);
347  };
348  ea("foldersync-structure", "foldersync-basic-struct");
349  ea("foldersync-tab-structure", "foldersync-basic-struct");
350  ea("foldersync-playlists", "foldersync-basic-plists");
351  ea("foldersync-tab-playlists", "foldersync-basic-plists");
352  ea("foldersync-structure-cover-box", "foldersync-structure-covers");
353  ea("foldersync-playlists-sort-box", "foldersync-playlists-sort");
354  },
355 
356  /* Load Profiles in menupopup of profile combo box; restore selection
357  * selection (string): the GUID of the profile to select or null for crt
358  */
359  reloadProfiles: function(selection){
360  try {
361  // Get the current selection, if any
362  var cSelection = selection;
363  var cIndex = document.getElementById("foldersync-profile").
364  selectedIndex;
365  var popup = document.getElementById("foldersync-profile-popup");
366  if ((!selection) && (cIndex > 0))
367  cSelection = popup.childNodes[cIndex].value;
368  // Clear popup, except changed entry
369  while (popup.childNodes.length > 1)
370  popup.removeChild(popup.childNodes[1]);
371  // Add all profiles
372  var selected = false; // we selected the prior selected profile?
373  var profiles = foldersync.preferences.getProfiles();
374  for each (var profile in profiles){
375  if (!profile.visible)
376  continue; // We don't want to show invisible profiles ;)
377  var node = document.createElement("menuitem");
378  node.value = profile.GUID;
379  node.setAttribute("label", profile.name);
380  popup.appendChild(node);
381  // Restore selection
382  if (cSelection == node.value){
383  document.getElementById("foldersync-profile").selectedItem = node;
384  selected = true;
385  }
386  }
387  // Select changed entry if we don't have a fitting profile
388  if (!selected)
389  document.getElementById("foldersync-profile").selectedIndex = 0;
390  // Selection might have changed
391  this.changeProfile();
392  } catch (e){
393  foldersync.central.logEvent("accesspane-profile",
394  "Loading Profiles failed:\n\n" + e, 1,
395  "chrome://foldersync/content/" +
396  "accesspane.js", e.lineNumber);
397  }
398  },
399 
400  // Initialize profile stuff
401  _init: function(){
402  try {
403  // Load available playlist formats
404  var pflist = document.
405  getElementById("foldersync-playlists-format-popup");
406  var pfs = foldersync.sync.getPFormats();
407  for each (var pf in pfs){
408  var node = pflist.appendChild(document.createElement("menuitem"));
409  node.value = pf.internalName;
410  node.setAttribute("label", foldersync.central.
411  getLocaleString(pf.name));
412  }
413  // Load available profiles
414  this.reloadProfiles();
415  // Select first profile, fallback to default if there is no profile
416  document.getElementById("foldersync-profile").selectedIndex = 1;
417  if (document.getElementById("foldersync-profile").selectedIndex == -1){
418  // Create new Default Profile (should not happen)
419  foldersync.preferences.createProfile(foldersync.central.
420  getLocaleString("profile.defaultname"));
421  // Select it
422  this.reloadProfiles();
423  document.getElementById("foldersync-profile").selectedIndex = 1;
424  }
425  this.changeProfile();
426  // Update enabled/disabled state
427  this.updateArea();
428  } catch (e){
429  foldersync.central.logEvent("accesspane-profile",
430  "Init Profiles failed:\n\n" + e, 1,
431  "chrome://foldersync/content/" +
432  "accesspane.js", e.lineNumber);
433  }
434  },
435 
436  /* Loads the given profile into UI
437  * profile (profile): the profile to load
438  */
439  _readProfile: function(profile){
440  try {
441  // helper for checkboxes
442  var ck = function (id, value){
443  document.getElementById(id).checked = value;
444  };
445  // helper for textboxes
446  var tx = function (id, value){
447  document.getElementById(id).value = value;
448  };
449  // helper for menulists
450  var ml = function(id, value){
451  for each (var node in document.getElementById(id).childNodes[0].
452  childNodes)
453  if (node.value == value)
454  document.getElementById(id).selectedItem = node;
455  }
456 
457  // Basic sync feature box
458  ck("foldersync-basic-update", profile.flags.doUpdate);
459  ck("foldersync-basic-delete", profile.flags.doDelete);
460  ck("foldersync-basic-rockbox", profile.flags.doRockbox);
461  ck("foldersync-basic-struct", profile.structure.isEnabled);
462  ck("foldersync-basic-plists", profile.playlists.isEnabled);
463 
464  // Structure box
465  tx("foldersync-structure-schema", profile.structure.schema);
466  tx("foldersync-structure-tndigits", profile.structure.tnDigits);
467  ck("foldersync-structure-covers", profile.structure.doCovers);
468  tx("foldersync-structure-cover-schema", profile.structure.
469  coverSchema);
470  tx("foldersync-structure-cover-file", profile.structure.coverFile);
471 
472  // Playlists box
473  ml("foldersync-playlists-format", profile.playlists.format);
474  ml("foldersync-playlists-encoding", profile.playlists.encoding);
475  tx("foldersync-playlists-target", profile.playlists.toFolder);
476  ck("foldersync-playlists-relpoint", profile.playlists.
477  doRelativePoint);
478  tx("foldersync-playlists-split", profile.playlists.splitChar);
479  ck("foldersync-playlists-sort", profile.playlists.isSorted);
480  tx("foldersync-playlists-sortingscheme", profile.playlists.
481  sortingScheme);
482 
483  // Advanced sync feature box
484  ck("foldersync-advanced-case", profile.advanced.compareCase);
485  tx("foldersync-advanced-blocked", profile.advanced.blockedChars);
486  tx("foldersync-advanced-replace", profile.advanced.replaceChar);
487  ck("foldersync-advanced-cutReplace", profile.advanced.cutReplaced);
488  ck("foldersync-advanced-cutSpaces", profile.advanced.cutSpaces);
489  tx("foldersync-advanced-length", profile.advanced.fMaxLength);
490  } catch(e){
491  foldersync.central.logEvent("accesspane-profile",
492  "Reading data from Profile failed:" +
493  "\n\n" + e, 1, "chrome://foldersync/" +
494  "content/accesspane.js", e.lineNumber);
495  }
496  },
497 
498  // Load the selected profile, called on changes in profile combo box
499  changeProfile: function(){
500  try{
501  var profileNode = document.getElementById("foldersync-profile");
502  var popup = document.getElementById("foldersync-profile-popup");
503  // Update UI
504  var customized = profileNode.selectedIndex > 0 ? false : true;
505  document.getElementById("foldersync-profile-savedelete").
506  selectedIndex = customized ? 0 : 1;
507  var dProf = profileNode.selectedIndex == 1;
508  document.getElementById("foldersync-profile-delete").disabled = dProf;
509  if (!customized){
510  // Load Profile
511  var guid = profileNode.selectedItem.value;
512  var profile = foldersync.preferences.getProfileByGUID(guid);
513 
514  // Load it
515  this._readProfile(profile);
516  }
517  // ensure area en-/ disabled states
518  this.updateArea();
519 
520  // ensure area en-/ disabled states
521  this.updateArea();
522  } catch (e){
523  foldersync.central.logEvent("accesspane-profile",
524  "Changing Profile failed:\n\n" + e, 1,
525  "chrome://foldersync/content/" +
526  "accesspane.js", e.lineNumber);
527  }
528  },
529 
530  // delete the selected profile, if user agreed a warning
531  delete: function(){
532  try{
533  var profileNode = document.getElementById("foldersync-profile");
534  var popup = document.getElementById("foldersync-profile-popup");
535  var customized = !(profileNode.selectedIndex > 0);
536  if (customized)
537  throw Components.Exception("Custom Profile can't get deleted");
538  var defaultProfile = profileNode.selectedIndex == 1;
539  if (defaultProfile)
540  throw Components.Exception("Default Profile can't get deleted");
541  var guid = profileNode.selectedItem.value;
542  var profile = foldersync.preferences.getProfileByGUID(guid);
543 
544  var msg = foldersync.central.getLocaleString("delete.sure");
545  msg = msg.replace("%s", profile.name);
546  if (!confirm(msg))
547  return;
548 
549  // Mark as temporary, so syncs in queue won't have a missing profile
550  profile.temporary = true;
551  profile.visible = false;
552  // Update profile list
553  this.reloadProfiles();
554  } catch (e){
555  foldersync.central.logEvent("accesspane-profile",
556  "Marking Profile for deletion failed:" +
557  "\n\n" + e, 1, "chrome://foldersync/" +
558  "content/accesspane.js", e.lineNumber);
559  }
560  },
561 
562  /* Write current data in a given profile
563  * profile (profile): the profile to write the data to
564  */
565  _writeProfile: function(profile){
566  try{
567  // helper for checkboxes
568  var ck = function (id){
569  return document.getElementById(id).checked;
570  };
571  // helper for textboxes
572  var tx = function (id){
573  return document.getElementById(id).value;
574  };
575  // helper for textboxes with integers
576  var ti = function(id){
577  return document.getElementById(id).value*1;
578  };
579  // helper for menulists
580  var ml = function(id){
581  return document.getElementById(id).selectedItem.value;
582  }
583 
584  // Basic sync feature box
585  profile.flags.doUpdate = ck("foldersync-basic-update");
586  profile.flags.doDelete = ck("foldersync-basic-delete");
587  profile.flags.doRockbox = ck("foldersync-basic-rockbox");
588  profile.structure.isEnabled = ck("foldersync-basic-struct");
589  profile.playlists.isEnabled = ck("foldersync-basic-plists");
590 
591  // Structure box
592  profile.structure.schema = tx("foldersync-structure-schema");
593  profile.structure.tnDigits = ti("foldersync-structure-tndigits");
594  profile.structure.doCovers = ck("foldersync-structure-covers");
595  profile.structure.coverSchema = tx("foldersync-structure-cover-" +
596  "schema");
597  profile.structure.coverFile = tx("foldersync-structure-cover-file");
598 
599  // Playlists box
600  profile.playlists.format = ml("foldersync-playlists-format");
601  profile.playlists.encoding = ml("foldersync-playlists-encoding");
602  profile.playlists.toFolder = tx("foldersync-playlists-target");
603  profile.playlists.doRelativePoint = ck("foldersync-playlists-" +
604  "relpoint");
605  profile.playlists.splitChar = tx("foldersync-playlists-split");
606  profile.playlists.isSorted = ck("foldersync-playlists-sort");
607  profile.playlists.sortingScheme = tx("foldersync-playlists-" +
608  "sortingscheme");
609 
610  // Advanced sync feature box
611  profile.advanced.compareCase = ck("foldersync-advanced-case");
612  profile.advanced.blockedChars = tx("foldersync-advanced-blocked");
613  profile.advanced.replaceChar = tx("foldersync-advanced-replace");
614  profile.advanced.cutReplaced = ck("foldersync-advanced-cutReplace");
615  profile.advanced.cutSpaces = ck("foldersync-advanced-cutSpaces");
616  profile.advanced.fMaxLength = ti("foldersync-advanced-length");
617  } catch(e){
618  foldersync.central.logEvent("accesspane-profile",
619  "Writing data to Profile failed:" +
620  "\n\n" + e, 1, "chrome://foldersync/" +
621  "content/accesspane.js", e.lineNumber);
622  }
623  },
624 
625  // update a existing profile or add a new profile with current data
626  save: function(){
627  var result={};
628  window.openDialog('chrome://foldersync/content/dialogs/saveprofile.xul',
629  'foldersync-saveprofile-dialog',
630  'dialog=yes,modal=yes,centerscreen=yes,resizable=no,' +
631  'dependent=yes', result);
632  if (result.action){
633  var profile = null;
634  if (result.action == "new"){
635  profile = foldersync.preferences.createProfile(result.name);
636  } else { // Update
637  profile = foldersync.preferences.getProfileByGUID(result.profile);
638  }
639  // Write to profile
640  this._writeProfile(profile);
641  // Select the new / updated profile
642  this.reloadProfiles(profile.GUID);
643  }
644  },
645 
646  /* set the current active profile
647  * profile (profile): the profile to set
648  */
649  setProfile:function(profile){
650  // Search the profile
651  var list = document.getElementById("foldersync-profile");
652  var popup = document.getElementById("foldersync-profile-popup");
653  for each (var node in popup.childNodes)
654  if (profile.GUID == node.value){
655  list.selectedItem = node;
656  this.changeProfile();
657  return;
658  }
659  // if it is not available, load it as custom
660  this._readProfile(profile);
661  list.selectedIndex = 0;
662  this.changeProfile();
663  },
664 
665  // get the currently active profile's GUID
666  getGUID: function(){
667  var cIndex = document.getElementById("foldersync-profile").selectedIndex;
668  if (cIndex > 0){ // we have a profile
669  return document.getElementById("foldersync-profile").
670  selectedItem.value;
671  } else { // custom profile
672  try {
673  foldersync.central.logEvent("accesspane-profile",
674  "Create temporary Profile", 4);
675  // create a temporary profile with the current data
676  var profile = foldersync.preferences.createProfile("Internal");
677  profile.temporary = true;
678  profile.visible = false;
679  this._writeProfile(profile);
680  return profile.GUID;
681  } catch(e){
682  foldersync.central.logEvent("accesspane-profile",
683  "Creating temporary Profile failed:" +
684  "\n\n" + e, 1, "chrome://foldersync/" +
685  "content/accesspane.js", e.lineNumber);
686  }
687  }
688  },
689  },
690 
691  // All target folder related things
692  target: {
693  // get the current target folder
694  getFolder: function(){
695  return document.getElementById("foldersync-target").value;
696  },
697 
698  // Called on any change in target folder box
699  onChange: function(){
700  // notify favorite controller of change
701  foldersync.accesspane.favorite.onChange();
702  },
703 
704  /* Set the current target folder
705  * folder (string): the new target folder
706  */
707  setFolder: function(folder){
708  document.getElementById("foldersync-target").value = folder;
709  this.onChange();
710  },
711 
712  // open Browse dialog and fill textbox
713  browse: function(){
714  // Create FilePicker and set GetFolder-Mode
715  var fp = Components.classes["@mozilla.org/filepicker;1"].
716  createInstance(Components.interfaces.nsIFilePicker);
717  fp.init(window, foldersync.central.getLocaleString("browse.info"),
718  Components.interfaces.nsIFilePicker.modeGetFolder);
719  // Show Dialog
720  var ret = fp.show();
721  // check for OK input by user
722  if ((ret == Components.interfaces.nsIFilePicker.returnOK) ||
723  (ret == Components.interfaces.nsIFilePicker.returnReplace)) {
724  var file = fp.file;
725  // fill textbox
726  this.setFolder(file.path);
727  }
728  },
729  },
730 
731  // All playlist-list related things
732  playlists: {
733  // get array of playlist GUIDs
734  getGUIDs: function(){
735  var list = document.getElementById("foldersync-playlists-list");
736  var result = [];
737  // Add all GUIDs that are selected...
738  for (var i = 0; i < list.childNodes.length; i++){
739  var node = list.childNodes[i];
740  if (node.getAttribute("checked") == "true")
741  result.push(node.value);
742  }
743  return result;
744  },
745 
746  /* select array of playlist GUIDs, unselect others
747  * guids (array of string): the guids to get selected
748  */
749  setGUIDs: function(guids){
750  var list = document.getElementById("foldersync-playlists-list");
751  for (var i = 0; i < list.childNodes.length; i++){
752  var node = list.childNodes[i];
753  node.setAttribute("checked", "false");
754  for each (var guid in guids)
755  if (guid == node.value)
756  node.setAttribute("checked", "true");
757  }
758  // Re-calculate Size
759  this.calcSize();
760  },
761 
762  // Reload list of playlists, restore old selection
763  reload: function(){
764  // Get old selection, to restore it later
765  var oldSelection = this.getGUIDs();
766  // Clear list
767  var list = document.getElementById("foldersync-playlists-list");
768  while (list.childNodes.length > 0)
769  list.removeChild(list.childNodes[0]);
770  // Get all playlists the user could want, add them to list
771  var plists = foldersync.central.getPlaylists(true, true);
772  for each (var plist in plists){
773  var node = list.appendChild(document.createElement("listitem"));
774  node.setAttribute("label", plist.name);
775  node.value = plist.guid;
776  node.setAttribute("type", "checkbox");
777  }
778  // Restore old selection
779  for each (var node in list.childNodes)
780  for each (var guid in oldSelection)
781  if (node.value == guid)
782  node.setAttribute("checked", "true");
783  // Re-calc Size
784  this.calcSize();
785  },
786 
787  // Called on any change
788  onChange: function(){
789  // notify favorite controller of change
790  foldersync.accesspane.favorite.onChange();
791  // recalculate site
792  this.calcSize();
793  },
794 
795  // Calculate and display file size of current selection
796  calcSize: function(){
797  try{
798  // Make sure Modules we'll use are loaded
799  if (!window.SBProperties)
800  Components.utils.import("resource://app/jsmodules/sbProperties.jsm");
801  // Get playlist GUIDs
802  var playlistGUIDs = foldersync.accesspane.playlists.getGUIDs();
803  // Detect if we should count files in more than one playlists twice
804  var useAll = (document.getElementById("foldersync-basic-struct").
805  checked) &&
806  (document.getElementById("foldersync-structure-schema").
807  value.split("%playlist%").length > 1);
808  // Go through playlists and calculate size
809  var size = 0;
810  var hadFiles = [];
811  for each (var guid in playlistGUIDs){
812  var playlist = foldersync.central.getPlaylistByGUID(guid);
813  if (useAll)
814  hadFiles = [];
815  for (var i = 0; i < playlist.length; i++){
816  var track = playlist.getItemByIndex(i);
817  // Look if we had this already
818  var trackURL = track.getProperty(SBProperties.contentURL);
819  var found = false;
820  for each (var had in hadFiles)
821  if (had == trackURL)
822  found = true;
823  if (found)
824  continue;
825  // Add to size and push into had already array
826  hadFiles.push(trackURL);
827  size += track.getProperty(SBProperties.contentLength)*1;
828 
829  }
830  }
831 
832  // Calculate MB
833  size = size / 1024 / 1024;
834  // Switch MB / GB -> get the Text
835  var text = foldersync.central.getLocaleString("playlists.size");
836  if (size < 1024) {
837  text = text.replace("%s", size.toFixed(2)+" MB");
838  } else {
839  text = text.replace("%s", (size/1024).toFixed(2)+" GB");
840  }
841 
842  // Display
843  var label = document.getElementById("foldersync-space");
844  while (label.childNodes.length > 0)
845  label.removeChild(label.childNodes[0]);
846  label.appendChild(document.createTextNode(text));
847  } catch(e){
848  foldersync.central.logEvent("accesspane-playlists",
849  "Calculating Size failed:\n\n" + e,
850  1, "chrome://foldersync/content/" +
851  "accesspane.js", e.lineNumber);
852  }
853  },
854 
855  // initialisation
856  _init: function(){
857  this.reload();
858  },
859  },
860 
861  // All favorite-sync-list related things
862  favorite: {
863  /* Load Favorites in menupopup of favorite combo box; restore old selection
864  * selection (string): the GUID of the favorite to select or null for crt
865  */
866  reloadFavorites: function(selection){
867  try {
868  // Get the current selection, if any
869  var cSelection = selection;
870  var cIndex = document.getElementById("foldersync-favorites").
871  selectedIndex;
872  var popup = document.getElementById("foldersync-favorites-popup");
873  if ((!selection) && (cIndex > 0))
874  cSelection = popup.childNodes[cIndex].value;
875  // Clear popup, except changed entry
876  while (popup.childNodes.length > 1)
877  popup.removeChild(popup.childNodes[1]);
878  // Add all profiles
879  var selected = false; // we selected the prior selected favorite?
880  var favorites = foldersync.preferences.getFavorites();
881  for each (var fav in favorites){
882  var node = document.createElement("menuitem");
883  node.value = fav.GUID;
884  node.setAttribute("label", fav.name);
885  popup.appendChild(node);
886  // Restore selection
887  if (cSelection == node.value){
888  document.getElementById("foldersync-favorites").
889  selectedItem = node;
890  selected = true;
891  }
892  }
893  // Select changed entry if we don't have a fitting profile
894  if (!selected)
895  document.getElementById("foldersync-favorites").selectedIndex = 0;
896  // Selection might have changed, but not due to a user input
897  this.changeFavorite(!document.getElementById("foldersync-favorites").
898  selectedIndex, true);
899  } catch (e){
900  foldersync.central.logEvent("accesspane-favorite",
901  "Loading Favorites failed:\n\n" + e, 1,
902  "chrome://foldersync/content/" +
903  "accesspane.js", e.lineNumber);
904  }
905  },
906 
907  // Initialize favorite things
908  _init: function(){
909  this.reloadFavorites();
910  },
911 
912  // Called on a change of any profile-related control except profile box
913  onChange: function(){
914  // Enable load button, if we have a favorite selected
915  if (this.getGUID())
916  document.getElementById("foldersync-favorite-load").
917  disabled = false;
918  },
919 
920  /* Disable perform button, and load Favorite into UI
921  * empty (bool): if we have a favorite selected (false) or not (true).
922  * dontload (bool): true if the user hasn't selected the favorite yet
923  */
924  changeFavorite: function(empty, dontload){
925  document.getElementById("foldersync-favorite-start").
926  setAttribute("disabled", empty ? "true" : "false");
927  document.getElementById("foldersync-favorite-delete").
928  setAttribute("disabled", empty ? "true" : "false");
929  document.getElementById("foldersync-direct-update").
930  setAttribute("disabled", empty ? "true" : "false");
931 
932  if (empty)
933  document.getElementById("foldersync-favorite-load").
934  disabled = true;
935  else if (!dontload){
936  // display button to load into ui
937  document.getElementById("foldersync-favorite-load").
938  disabled = false;
939  }
940  },
941 
942  // Delete selected favorite, if user agreed a warning
943  delete: function(){
944  try{
945  // Get Favorite
946  var guid = this.getGUID()
947  if (!guid)
948  throw Components.Exception("There is not favorite selected");
949  var fav = foldersync.preferences.getFavoriteByGUID(guid);
950 
951  // Ensure the user is sure
952  var msg = foldersync.central.getLocaleString("delete.sure");
953  msg = msg.replace("%s", fav.name);
954  if (!confirm(msg))
955  return;
956 
957  // Delete profile associated with this favorite, if it is not a user defined profile
958  var profile = foldersync.preferences.getProfileByGUID(fav.sync.profileGUID);
959  if (!profile.visible)
960  foldersync.preferences.removeProfile(profile);
961  // Delete favorite
962  foldersync.preferences.removeFavorite(fav);
963  // Update favorite list
964  this.reloadFavorites();
965  } catch (e){
966  foldersync.central.logEvent("accesspane-favorite",
967  "Deleting Favorite failed:\n\n" + e, 1,
968  "chrome://foldersync/" +
969  "content/accesspane.js", e.lineNumber);
970  }
971  },
972 
973  // Perform the selected favorite
974  start: function(){
975  try{
976  // Get Favorite
977  var guid = this.getGUID();
978  if (!guid)
979  throw Components.Exception("There is not favorite selected");
980  var fav = foldersync.preferences.getFavoriteByGUID(guid);
981  // Start the sync in the Favorite
982  foldersync.sync.performSync(fav.sync);
983  } catch(e){
984  foldersync.central.logEvent("accesspane-favorite",
985  "Starting Favorite Sync failed:\n\n" + e,
986  1, "chrome://foldersync/" +
987  "content/accesspane.js", e.lineNumber);
988  }
989  },
990 
991  // Add a favorite with the selected values, asks user for name
992  add: function(){
993  try {
994  var res = {};
995  window.openDialog('chrome://foldersync/content/dialogs/addfav.xul',
996  'foldersync-addfav-dialog',
997  'dialog=yes,modal=yes,centerscreen=yes,' +
998  'resizable=no,dependent=yes', res);
999  if (!res.name)
1000  return; // user cancelled
1001  var sync = foldersync.accesspane.getSync();
1002  // Ensure the profile is not temporary
1003  foldersync.preferences.getProfileByGUID(sync.profileGUID).
1004  temporary = false;
1005  var favorite = foldersync.preferences.createFavorite(res.name, sync);
1006  this.reloadFavorites();
1007  } catch(e){
1008  foldersync.central.logEvent("accesspane-favorite",
1009  "Adding Favorite failed:\n\n" + e, 1,
1010  "chrome://foldersync/" +
1011  "content/accesspane.js", e.lineNumber);
1012  }
1013  },
1014 
1015  // Update current favorite with the selected values, asks user for name
1016  update: function(){
1017  try {
1018  // Get Favorite
1019  var guid = this.getGUID()
1020  if (!guid)
1021  throw Components.Exception("There is not favorite selected");
1022  var fav = foldersync.preferences.getFavoriteByGUID(guid);
1023 
1024  // Ensure the user is sure
1025  var msg = foldersync.central.getLocaleString("update.sure");
1026  msg = msg.replace("%s", fav.name);
1027  if (!confirm(msg))
1028  return;
1029 
1030  // Delete profile associated with this favorite, if it is not a user
1031  // defined profile
1032  var profile = foldersync.preferences.
1033  getProfileByGUID(fav.sync.profileGUID);
1034  if (!profile){
1035  foldersync.central.logEvent("accesspane-favorite",
1036  "There is no valid Profile avaiable " +
1037  "for Favorite " + guid + ". Skip old " +
1038  "Profile deletion.", 3,
1039  "chrome://foldersync/content/" +
1040  "accesspane.js");
1041  } else
1042  if (!profile.visible)
1043  foldersync.preferences.removeProfile(profile);
1044 
1045  // Fill profile with new data
1046  fav.sync = foldersync.accesspane.getSync();
1047  // Ensure the new profile is not temporary
1048  foldersync.preferences.getProfileByGUID(fav.sync.profileGUID).
1049  temporary = false;
1050  } catch(e){
1051  foldersync.central.logEvent("accesspane-favorite",
1052  "Updating Favorite failed:\n\n" + e, 1,
1053  "chrome://foldersync/" +
1054  "content/accesspane.js", e.lineNumber);
1055  }
1056  },
1057 
1058  // Load current favorite into UI
1059  load: function(){
1060  try{
1061  // Get favorite
1062  var guid = this.getGUID();
1063  if (!guid)
1064  throw Components.Exception("There is not favorite selected");
1065  var fav = foldersync.preferences.getFavoriteByGUID(guid);
1066  // Update UI
1067  foldersync.accesspane.target.setFolder(fav.sync.targetFolder);
1068  foldersync.accesspane.playlists.setGUIDs(fav.sync.playlists);
1069  var profile = foldersync.preferences.
1070  getProfileByGUID(fav.sync.profileGUID);
1071  if (profile)
1072  foldersync.accesspane.profile.setProfile(profile);
1073  else
1074  foldersync.central.logEvent("accesspane-favorite",
1075  "There is no valid Profile avaiable " +
1076  "for Favorite " + guid + ". Skip " +
1077  "Profile loading.", 2,
1078  "chrome://foldersync/content/" +
1079  "accesspane.js");
1080  // Disable load button
1081  document.getElementById("foldersync-favorite-load").
1082  disabled = true;
1083  } catch(e){
1084  foldersync.central.logEvent("accesspane-favorite",
1085  "Loading Favorite failed:\n\n" + e, 1,
1086  "chrome://foldersync/" +
1087  "content/accesspane.js", e.lineNumber);
1088  }
1089  },
1090 
1091  // Get the currently selected Favorite's GUID
1092  getGUID: function(){
1093  var favNode = document.getElementById("foldersync-favorites");
1094  var hasOne = favNode.selectedIndex > 0;
1095  if (!hasOne)
1096  return null;
1097  return favNode.selectedItem.value;
1098  },
1099  },
1100 
1101  // All help-related things
1102  help: {
1103  // Open preferences
1104  preferences: function(){
1105  window.openDialog("chrome://foldersync/content/dialogs/options.xul",
1106  "foldersync-options",
1107  "chrome,titlebar,toolbar,centerscreen,modal=no");
1108  },
1109 
1110  /* Open given URL in a new tab (foreground)
1111  * url (string): the url to open
1112  */
1113  openURL: function(url){
1114  try {
1115  // Get the main window
1116  var mainWindow = window.QueryInterface(Components.interfaces.
1118  getInterface(Components.interfaces.
1120  QueryInterface(Components.interfaces.
1122  rootTreeItem.
1123  QueryInterface(Components.interfaces.
1125  getInterface(Components.interfaces.
1126  nsIDOMWindow);
1127  mainWindow.gBrowser.selectedTab = mainWindow.gBrowser.
1128  addTab(url);
1129  } catch (e){
1130  foldersync.central.logEvent("accesspane",
1131  "Opening of '" + url + "' failed:\n\n" + e,
1132  1, "chrome://foldersync/content/" +
1133  "accesspane.js", e.lineNumber);
1134  }
1135  },
1136  },
1137 };
1138 
1139 // load / unload accesspane controller with accesspane
1140 window.addEventListener("load",
1141  function(e){
1142  foldersync.accesspane.onLoad(e);
1143  },
1144  false);
1145 window.addEventListener("unload",
1146  function(e){
1147  foldersync.accesspane.onUnload(e);
1148  },
1149  false);
function start(ch)
function fail(aMessage)
menuItem id
Definition: FeedWriter.js:971
const nsIDocShellTreeItem
playlistfolders preferences
Definition: preferences.js:13
document getElementById("theimagecontainer").collapsed
foldersync sync
Definition: sync.js:14
sidebarFactory createInstance
Definition: nsSidebar.js:351
sbOSDControlService prototype QueryInterface
ui plugin add("draggable","cursor",{start:function(e, ui){var t=$('body');if(t.css("cursor")) ui.options._cursor=t.css("cursor");t.css("cursor", ui.options.cursor);}, stop:function(e, ui){if(ui.options._cursor)$('body').css("cursor", ui.options._cursor);}})
let window
const nsIDOMWindow
this _contentSandbox label
Definition: FeedWriter.js:814
const nsIWebNavigation
Definition: browser.js:71
function getGUIDs(aNode)
var selectedItem
Definition: FeedWriter.js:1261
Lastfm onLoad
Definition: mini.js:36
Element Properties load
grep callback
return null
Definition: FeedWriter.js:1143
return ret
menuItem setAttribute("handlerType","client")
let node
RDFHelper help
Definition: RDFHelper.jsm:170
inst dpDiv empty().append(this._generateHTML(inst)).find('iframe.ui-datepicker-cover').css(
function url(spec)
countRef value
Definition: FeedWriter.js:1423
function msg
function onUnload()
onUnload - called when the cover preview window unloads.
Definition: coverPreview.js:36
const nsIInterfaceRequestor
_getSelectedPageStyle s i
var file
function openURL(target)
Definition: pageInfo.js:645