← Back to team overview

deja-dup-team team mailing list archive

[Merge] lp:~urbans/deja-dup/deja-dup.nautilus into lp:deja-dup

 

Urban Skudnik has proposed merging lp:~urbans/deja-dup/deja-dup.nautilus into lp:deja-dup.

Requested reviews:
  Michael Terry (mterry): proposals bugreports testing ideas


This branch addresses 'restore missing files' bug [https://bugs.launchpad.net/deja-dup/+bug/540590] by adding assistant for scanning through duplicity's archive and searching for files that were deleted.

ATM Deja Dup has to be manually ran with command --dir-history [directory] to test the new assistant.
-- 
https://code.launchpad.net/~urbans/deja-dup/deja-dup.nautilus/+merge/29723
Your team Déjà Dup Maintainers is subscribed to branch lp:deja-dup.
=== modified file 'common/Backend.vala'
--- common/Backend.vala	2010-06-05 01:30:41 +0000
+++ common/Backend.vala	2010-07-12 16:58:42 +0000
@@ -37,6 +37,7 @@
   public virtual bool is_ready(out string when) {when = null; return true;} // must be callable when nothing is mounted, nothing is prepared
 
   public virtual async void get_envp() throws Error {
+    stdout.printf("get_envp\n");
     envp_ready(true, new List<string>());
   }
 

=== modified file 'common/BackendFile.vala'
--- common/BackendFile.vala	2010-06-01 11:17:19 +0000
+++ common/BackendFile.vala	2010-07-12 16:58:42 +0000
@@ -261,6 +261,7 @@
   public override async void get_envp() throws Error
   {
     try {
+      stdout.printf("get_envp mount file\n");
       yield mount_file();
     }
     catch (Error e) {

=== modified file 'common/Duplicity.vala'
--- common/Duplicity.vala	2010-06-12 22:06:51 +0000
+++ common/Duplicity.vala	2010-07-12 16:58:42 +0000
@@ -24,12 +24,23 @@
 
 public class Duplicity : Object
 {
+  /*
+   * Vala implementation of various methods for accessing duplicity
+   *
+   * Vala implementation of various methods for accessing duplicity from
+   * vala withot the need of manually running duplicity command.
+   */
+
   public signal void done(bool success, bool cancelled);
   public signal void raise_error(string errstr, string? detail);
   public signal void action_desc_changed(string action);
   public signal void action_file_changed(File file, bool actual);
   public signal void progress(double percent);
+  /*
+   * Signal emmited when collection dates are retrieved from duplicity
+   */
   public signal void collection_dates(List<string>? dates);
+  public signal void listed_current_files(string date, string file);
   public signal void question(string title, string msg);
   public signal void secondary_desc_changed(string msg);
   
@@ -208,6 +219,7 @@
   }
   
   public void cancel() {
+    stdout.printf("\n\nCanceling duplicity\n\n");
     var prev_mode = mode;
     mode = Operation.Mode.INVALID;
     
@@ -694,6 +706,9 @@
   void handle_message(DuplicityInstance inst, string[] control_line,
                       List<string>? data_lines, string user_text)
   {
+    /*
+     * Based on duplicity's output handle message as either process data as error, info or warning
+     */
     if (control_line.length == 0)
       return;
     
@@ -884,6 +899,9 @@
   protected virtual void process_info(string[] firstline, List<string>? data,
                                       string text)
   {
+    /*
+     * Pass message to appropriate function considering the type of output
+     */
     if (firstline.length > 1) {
       switch (firstline[1].to_int()) {
       case INFO_DIFF_FILE_NEW:
@@ -909,13 +927,13 @@
           set_status(_("Uploading…"));
         break;
       case INFO_FILE_STAT:
-        process_file_stat(firstline[2], firstline[3]);
+        process_file_stat(firstline[2], firstline[3], data, text);
         break;
       }
     }
   }
   
-  void process_file_stat(string date, string file)
+  void process_file_stat(string date, string file, List<string> data, string text)
   {
     if (mode != Operation.Mode.LIST)
       return;
@@ -929,6 +947,7 @@
           !gfile.has_prefix(slash_home))
         has_non_home_contents = true;
     }
+    listed_current_files(date, file);
   }
   
   void process_diff_file(string file) {
@@ -981,11 +1000,15 @@
   
   void process_collection_status(List<string>? lines)
   {
-    // Collection status is a bunch of lines, some of which are indented,
-    // which contain information about specific chains.  We gather this all up
-    // and report back to caller via a signal.
-    // We're really only interested in the list of entries in the complete chain,
-    // though.
+    stdout.printf("duplicity.process_collection_status\n");
+    /*
+     * Collect output of collection status and return list of dates as strings via a signal
+     *
+     * Duplicity returns collection status as a bunch of lines, some of which are
+     * indented which contain information about specific chains. We gather
+     * this all up and report back to caller via a signal.
+     * We're really only interested in the list of entries in the complete chain.
+     */
     
     var timeval = TimeVal();
     var dates = new List<string>();
@@ -1022,7 +1045,7 @@
     collection_info = new List<DateInfo?>();
     foreach (DateInfo s in infos)
       collection_info.append(s); // we want to keep our own copy too
-    
+
     collection_dates(dates);
   }
   
@@ -1083,6 +1106,7 @@
 
   void disconnect_inst()
   {
+    /* Disconnect signals and cancel call to duplicity instance */
     if (inst != null) {
       inst.done.disconnect(handle_done);
       inst.message.disconnect(handle_message);
@@ -1095,13 +1119,21 @@
                          List<string>? envp_extra = null,
                          List<string>? argv_entire = null,
                          File? custom_local = null)
-  {
+  { 
+    /*
+     * For passed arguments start a new duplicity instance, set duplicity in the right mode and execute command
+     */
+    /* Disconnect instance */
     disconnect_inst();
-
+    
+    /* Start new duplicity instance */
     inst = new DuplicityInstance();
     inst.done.connect(handle_done);
+
+    /* As duplicity's data is returned via a signal, handle_message begins post-raw stream processing*/
     inst.message.connect(handle_message);
-    
+
+    /* Set arguments for call to duplicity */
     weak List<string> master_argv = argv_entire == null ? saved_argv : argv_entire;
     weak File local_arg = custom_local == null ? local : custom_local;
     
@@ -1109,7 +1141,8 @@
     foreach (string s in master_argv) argv.append(s);
     foreach (string s in argv_extra) argv.append(s);
     foreach (string s in this.backend_argv) argv.append(s);
-    
+
+    /* Set duplicity into right mode */
     if (argv_entire == null) {
       // add operation, local, and remote args
       switch (mode) {
@@ -1136,11 +1169,13 @@
         break;
       }
     }
-    
+
+    /* Set enviormental parameters */
     var envp = new List<string>();
     foreach (string s in saved_envp) envp.append(s);
     foreach (string s in envp_extra) envp.append(s);
-    
+
+    /* Start duplicity instance */
     try {
       inst.start(argv, envp, needs_root);
     }

=== modified file 'common/DuplicityInstance.vala'
--- common/DuplicityInstance.vala	2010-06-12 22:13:57 +0000
+++ common/DuplicityInstance.vala	2010-07-12 16:58:42 +0000
@@ -276,6 +276,12 @@
   
   async void read_log_lines()
   {
+    /*
+     * Process data from stream that is returned by read_log
+     *
+     * As reader returns lines that are outputed by duplicity, read_log_lines makes sure
+     * that data is processed at right speed and passes that data along the chain of functions. 
+     */
     List<string> stanza = new List<string>();
     while (reader != null) {
       try {
@@ -324,6 +330,11 @@
 
   async void read_log()
   {
+   /*
+    * Asynchronous reading of duplicity's log via stream
+    *
+    * Stream initiated either from log file or pipe
+    */
     try {
       InputStream stream;
       
@@ -509,6 +520,10 @@
   
   void process_stanza(List<string> stanza)
   {
+    /*
+     * Split the line/stanza that was echoed by stream and pass it forward in a 
+     * more structured way via a signal.
+     */
     string[] control_line;
     split_line(stanza.data, out control_line);
     
@@ -522,6 +537,9 @@
   
   List<string> grab_stanza_data(List<string> stanza)
   {
+    /*
+     * Return only data from stanza that was returned by stream
+     */
     var list = new List<string>();
     stanza = stanza.next; // skip first control line
     foreach (string line in stanza) {

=== modified file 'common/Makefile.am'
--- common/Makefile.am	2010-03-25 21:40:33 +0000
+++ common/Makefile.am	2010-07-12 16:58:42 +0000
@@ -47,6 +47,7 @@
 	OperationBackup.vala \
 	OperationRestore.vala \
 	OperationStatus.vala \
+	OperationFiles.vala \
 	RecursiveDelete.vala \
 	RecursiveMove.vala \
 	RecursiveOp.vala

=== modified file 'common/Operation.vala'
--- common/Operation.vala	2010-02-05 13:44:45 +0000
+++ common/Operation.vala	2010-07-12 16:58:42 +0000
@@ -23,6 +23,15 @@
 
 public abstract class Operation : Object
 {
+  /**
+   * Abstract class that abstracts low level operations of duplicity
+   * with specific classes for specific operations
+   *
+   * Abstract class that defines methods and properties that have to be defined
+   * by classes that abstract operations from duplicity. It is generally unnecessary
+   * but it is provided to provide easier development and an abstraction layer
+   * in case Deja Dup project ever replaces its backend.
+   */
   public signal void done(bool success, bool cancelled);
   public signal void raise_error(string errstr, string? detail);
   public signal void action_desc_changed(string action);
@@ -35,13 +44,21 @@
   public uint xid {get; construct;}
   public bool needs_password {get; private set;}
   public Backend backend {get; private set;}
-  
+    
   public enum Mode {
+    /*
+   * Mode of operation of instance
+   *
+   * Every instance of class that inherit its methods and properties from
+   * this class must define in which mode it operates. Based on this Duplicity
+   * attaches appropriate argument.
+   */
     INVALID,
     BACKUP,
     RESTORE,
     STATUS,
     LIST,
+    FILEHISTORY
   }
   public Mode mode {get; construct; default = Mode.INVALID;}
   
@@ -81,7 +98,6 @@
   construct
   {
     dup = new Duplicity(mode);
-
     try {
       backend = Backend.get_default();
     }
@@ -92,8 +108,8 @@
   
   public virtual void start() throws Error
   {
-    action_desc_changed(_("Preparing…"));
-
+    stdout.printf("\nbase Operation.start()\n\n");
+    action_desc_changed(_("Preparing…"));    
     if (backend == null) {
       done(false, false);
       return;
@@ -105,16 +121,19 @@
       done(false, false);
       return;
     }
+    stdout.printf("setting session, encryption needed?\n");
     set_session_inhibited(true);
-    
     // Get encryption passphrase if needed
     var client = get_gconf_client();
     if (client.get_bool(ENCRYPT_KEY) && passphrase == null) {
+      stdout.printf("nimam passa, lets get it!\n");
       needs_password = true;
       passphrase_required(); // will call continue_with_passphrase when ready
     }
-    else
+    else {
+      stdout.printf("nadaljujemo z continue_with_passphrase");
       continue_with_passphrase(passphrase);
+    }
   }
   
   public void cancel()
@@ -129,6 +148,9 @@
   
   protected virtual void connect_to_dup()
   {
+    /*
+     * Connect Deja Dup to signals
+     */
     dup.done.connect(operation_finished);
     dup.raise_error.connect((d, s, detail) => {raise_error(s, detail);});
     dup.action_desc_changed.connect((d, s) => {action_desc_changed(s);});
@@ -141,6 +163,10 @@
   
   public void continue_with_passphrase(string? passphrase)
   {
+   /*
+    * Continues with operation after passphrase has been acquired.
+    */
+    stdout.printf("\ncontinue_with_passphrase\n");
     needs_password = false;
     this.passphrase = passphrase;
     try {
@@ -153,6 +179,12 @@
   }
   
   void continue_with_envp(DejaDup.Backend b, bool success, List<string>? envp, string? error) {
+    /*
+     * Starts Duplicity backup with added enviroment variables
+     * 
+     * Start Duplicity backup process with costum values for enviroment variables.
+     */
+    stdout.printf("continue_with_envp\n");
     if (!success) {
       if (error != null)
         raise_error(error, null);
@@ -200,6 +232,12 @@
   
   protected virtual List<string>? make_argv() throws Error
   {
+  /**
+   * Abstract method that prepares arguments that will be sent to duplicity
+   *
+   * Abstract method that will prepare arguments that will be sent to duplicity
+   * and return a list of those arguments.
+   */
     return null;
   }
   

=== modified file 'common/OperationBackup.vala'
--- common/OperationBackup.vala	2010-05-29 17:44:34 +0000
+++ common/OperationBackup.vala	2010-07-12 16:58:42 +0000
@@ -34,6 +34,7 @@
   
   protected override void operation_finished(Duplicity dup, bool success, bool cancelled)
   {
+    /* If successfully completed, update time of last backup and run base operation_finished */
     if (success) {
       try {DejaDup.update_last_run_timestamp();}
       catch (Error e) {warning("%s\n", e.message);}

=== added file 'common/OperationFiles.vala'
--- common/OperationFiles.vala	1970-01-01 00:00:00 +0000
+++ common/OperationFiles.vala	2010-07-12 16:58:42 +0000
@@ -0,0 +1,46 @@
+using GLib;
+
+namespace DejaDup {
+
+public class OperationFiles : Operation {
+	public signal void listed_current_files(string date, string file);
+	public Time time {public get; public set;}
+	public File source {get; construct;}
+		
+	public OperationFiles(uint xid = 0,
+	    									Time time_in,
+	    									File source_in) {
+		Object(xid: xid, mode: Mode.LIST, source: source_in);
+		this.time = time_in;
+	}
+
+	protected override void connect_to_dup()
+  {
+    dup.listed_current_files.connect((d, date, file) => {listed_current_files(date, file);});
+    base.connect_to_dup();
+  }
+
+	protected override List<string>? make_argv() throws Error
+	{
+    	List<string> argv = new List<string>();
+    	//if (time != null) - no need, we don't allow null anyway
+      argv.append("--time=%s".printf(time.format("%s")));
+
+			dup.local = source;
+			
+			return argv;
+	}
+
+	public override void start() throws Error
+  {
+		//stdout.printf("operation files.start() with epoch time %s\n", time.format("%c"));
+		stdout.printf("operation files start()\n");
+		base.start();
+  }
+
+	protected override void operation_finished(Duplicity dup, bool success, bool cancelled)
+	{
+		base.operation_finished(dup, success, cancelled);
+	}
+}
+}
\ No newline at end of file

=== modified file 'common/OperationRestore.vala'
--- common/OperationRestore.vala	2010-01-18 23:31:22 +0000
+++ common/OperationRestore.vala	2010-07-12 16:58:42 +0000
@@ -25,6 +25,15 @@
 {
   public string dest {get; construct;} // Directory user wants to put files in
   public string time {get; construct;} // Date user wants to restore to
+
+  /*public Queue<string> restore_queue {
+      get {
+        return this.restore_queue;
+      }
+      set construct {
+        this.restore_queue = value.copy();
+      }}*/
+  
   string source; // Directory duplicity puts files in
   List<string> errors;
   private List<File> _restore_files;
@@ -32,7 +41,7 @@
     get {
       return this._restore_files;
     }
-    construct {
+    set construct {
       foreach (File f in this._restore_files)
         f.unref();
       this._restore_files = value.copy();
@@ -40,7 +49,9 @@
         f.ref();
     }
   }
-  
+
+  //Queue<string>? queue_in = null
+  //, restore_queue: queue_in.copy()
   public OperationRestore(string dest_in,
                           string? time_in = null,
                           List<File>? files_in = null,
@@ -51,6 +62,7 @@
   
   public override void start() throws Error
   {
+    //stdout.printf("mode: %s", this.mode);
     action_desc_changed(_("Restoring files…"));
     dup.restore_files = restore_files;
     base.start();
@@ -70,12 +82,30 @@
       argv.append("--restore-time=%s".printf(time));
     
     dup.local = File.new_for_path(source);
-    
     return argv;
   }
   
   protected override void operation_finished(Duplicity dup, bool success, bool cancelled)
   {
+    /*if (this.restore_queue.get_length() > 0) {
+      var restore_file = this.restore_queue.pop_head();
+      
+      //var _restore_files = new GLib.List<File>(); 
+		  //restore_files.append(File.new_for_path(restore_file.split(" ")[0]));
+      //this.restore_files.remove(this.restore_files.nth_data(0));
+      var _restore_files = new GLib.List<File>();
+      _restore_files.append(File.new_for_path(restore_file.split(" ")[0]));
+        
+      //this.restore_files = _restore_files.copy();
+      dup.restore_files = _restore_files;
+      
+      //this.restore_files.append(File.new_for_path(restore_file.split(" ")[0]));
+      this.time = restore_file.split(" ")[1];
+      base.start();
+      return;
+    }*/      
+      
+      
     if (success) {
       fixup_home_dir();
       if (!mv_source_to_dest())

=== modified file 'common/OperationStatus.vala'
--- common/OperationStatus.vala	2009-11-12 21:33:25 +0000
+++ common/OperationStatus.vala	2010-07-12 16:58:42 +0000
@@ -32,8 +32,16 @@
   protected override void connect_to_dup()
   {
     dup.collection_dates.connect((d, dates) => {collection_dates(dates);});
+    dup.collection_dates.connect((d, dates) => {
+      stdout.printf("collection_dates was called\n");
+    });
     base.connect_to_dup();
   }
+
+  protected override void operation_finished(Duplicity dup, bool success, bool cancelled) {
+    stdout.printf("Operation status.operation_finished\n");
+    base.operation_finished(dup, success, cancelled);
+  }
 }
 
 } // end namespace

=== modified file 'configure.ac'
--- configure.ac	2010-06-14 01:06:33 +0000
+++ configure.ac	2010-07-12 16:58:42 +0000
@@ -74,7 +74,9 @@
                   gio-2.0 >= $GIO_REQ_VER
                   gconf-2.0
                   dbus-glib-1
-                  gnome-keyring-1)
+                  gnome-keyring-1
+                  gmodule-2.0 >= $GLIB_REQ_VER
+                  gee-1.0)
 AC_SUBST(DUP_CFLAGS)
 AC_SUBST(DUP_LIBS)
 
@@ -82,7 +84,8 @@
                   gtk+-2.0 >= $GTK_REQ_VER
                   gio-2.0 >= $GIO_REQ_VER
                   gconf-2.0
-                  unique-1.0)
+                  unique-1.0
+                  gmodule-2.0 >= $GLIB_REQ_VER)
 AC_SUBST(PREF_CFLAGS)
 AC_SUBST(PREF_LIBS)
 
@@ -91,13 +94,15 @@
                   gio-unix-2.0 >= $GIO_REQ_VER
                   gconf-2.0
                   dbus-glib-1
-                  gnome-keyring-1)
+                  gnome-keyring-1
+                  gmodule-2.0 >= $GLIB_REQ_VER)
 AC_SUBST(COMMON_CFLAGS)
 AC_SUBST(COMMON_LIBS)
 
 PKG_CHECK_MODULES(WIDGETS,
                   gtk+-2.0 >= $GTK_REQ_VER
-                  gconf-2.0)
+                  gconf-2.0
+                  gmodule-2.0 >= $GLIB_REQ_VER)
 AC_SUBST(WIDGETS_CFLAGS)
 AC_SUBST(WIDGETS_LIBS)
 

=== modified file 'deja-dup/Assistant.vala'
--- deja-dup/Assistant.vala	2010-06-14 01:06:33 +0000
+++ deja-dup/Assistant.vala	2010-07-12 16:58:42 +0000
@@ -61,7 +61,7 @@
   bool interrupted_from_hidden = false;
   weak List<PageInfo> interrupted;
 
-  weak List<PageInfo> current;
+  public weak List<PageInfo> current;
   List<PageInfo> infos;
 
   static const int APPLY = 1;

=== added file 'deja-dup/AssistantDirectoryHistory.vala'
--- deja-dup/AssistantDirectoryHistory.vala	1970-01-01 00:00:00 +0000
+++ deja-dup/AssistantDirectoryHistory.vala	2010-07-12 16:58:42 +0000
@@ -0,0 +1,809 @@
+using GLib;
+using Gee;
+
+public class DeletedFile {
+		/*
+		 * Class whose instances hold information and track status of deleted file.
+		 *
+		 * After providing full file path and time of when was file last seen, instances
+		 * can access pretty file name and mark file for restore.
+		 * 
+		 * @param //string// ''name'' Full path name of file
+		 * @param //Time// ''deleted'' Information when was file deleted
+		 */
+		public string name {get; set;}
+		public Time deleted {get; set;}
+		public bool restore {get; set; default = false;}
+
+		public DeletedFile(string name, Time deleted) {
+			this.name = name;
+			this.deleted = deleted;
+		}
+
+		public string filename() {
+			var splited_fn = this.name.split("/");
+			stdout.printf("filename: %s\n", splited_fn[splited_fn.length-1]);
+			return splited_fn[splited_fn.length-1];
+		}
+
+		public string queue_format() {
+			var file = this.name;
+			var time = this.deleted.format("%s");
+			return @"$file $time";
+		}
+}
+
+public class AssistantDirectoryHistory : AssistantOperation {
+	/*
+	 * Assistant for showing deleted files
+	 *
+	 * Assistant for showing deleted files. Execution flow goes as follows:
+	 * 
+	 * 1. AssistantDirectoryHistory is called with //File// ''list_dir'' directory
+	 * 2. //void// do_prepare prepares listfiles_page and runs do_query_collection_dates that initializes query operation for collections dates. Results of query operation are returned to handle_collection_dates in one batch.
+	 * 3. handle_collection_dates fills the //PriorityQueue// ''backups_queue'' with //Time// values of backup dates, scans provided //File// ''list_dir'' with files that are currently located in directory and runs do_query_files_at_date
+	 * 4. do_query_files_at_date begins query operation for list-current-files at specific times and returns the results to handle_listed_files.  
+	 * 5. handle_listed_files appends files to the list of deleted files with appropriate controls.
+	 * 6. When OperationFiles finishes, query_files_finished releases variables and, if required, calls do_query_files_at_date. 
+	 * 7. After user selects files that he wishes to restore, he moves to confirmation page and starts the restore operation
+	 * 
+	 * 
+	 * 
+	 * 
+	 * 
+	 * 
+	 * 
+	 * 
+	 * @param //File// ''list_dir'' Directory whose deleted files will be shown.
+	 */
+	private File list_directory;
+
+	private bool backups_queue_filled = false;
+	private static int compare_time(Time a, Time b) {
+		/*
+		 * Compare function for backups queue
+		 *
+		 * Default comparing for queue goes from oldest to newest so we use our own
+		 * compare function to reverse that ordering and proceed from newest to oldest
+		 * since it is far more likely that user deleted file in recent history.
+		 *
+		 * @param //Time// ''a'', ''b'' Time objects
+		 */
+		var a_epoch = a.format("%s").to_int();
+		var b_epoch = b.format("%s").to_int();
+		if (a_epoch < b_epoch)
+			return 1;
+		else if (a_epoch == b_epoch)
+			return 0;
+		else
+			return -1;
+	}
+
+	/*
+		If user moves forward while OperationFiles is runing, code cleanup stops the current operation
+		and stops recursive loop without the need to clear backups_queue. If user decides to go back, 
+		OperationFiles will continue with NEXT item in backups_queue.
+	*/
+	private bool scan_queue = true;
+	private bool cancel_assistant = false;
+	private PriorityQueue<Time?> backups_queue = new PriorityQueue<Time?>((CompareFunc) compare_time);
+	private PriorityQueue<DeletedFile?> restore_queue = new PriorityQueue<DeletedFile?>();
+
+	private ArrayList<string> allfiles_prev = new ArrayList<string>();
+	private ArrayList<DeletedFile?>	file_status = new ArrayList<DeletedFile?>();
+
+	DejaDup.OperationFiles query_op_files;
+	DejaDup.OperationStatus query_op_collection_dates;
+  DejaDup.Operation.State op_state;
+
+	Gtk.Widget page;
+	Gtk.Widget listfiles_page;
+	Gtk.TreeIter deleted_iter;
+	Gtk.TreeIter restoreiter;
+	Gtk.ListStore listmodel;
+	Gtk.ListStore restoremodel;
+
+	/* List files page */
+	Gtk.Label current_scan_date = new Gtk.Label(_("Starting..."));
+	Gtk.Spinner spinner = new Gtk.Spinner();
+	
+	/* Confirmation page related widgets */
+	Gtk.Label label;
+	Gtk.Table restore_files_table;
+	/*
+		Gtk.Table in Glade needs to be set at least to 1 at start. When we update
+		our table we start from 0 so that we always resize table to correct size without the need for special case.
+	 */
+	int restore_files_table_rows = 0;
+	
+	public AssistantDirectoryHistory(File list_dir) {
+			list_directory = list_dir;
+	}
+
+	private ArrayList<string>? files_in_directory() {
+		/*
+		 * Function lists all files that are currently located in the directory.
+		 *
+		 * Function scans directory that was provided to it through
+		 * command line children and returns an array of strings populated
+		 * by file names of folder and files.
+		 */
+		//File directory = File.new_for_path(dirlocation);
+		var file_list = new ArrayList<string> ();
+
+		try {
+			var enumerator = this.list_directory.enumerate_children(FILE_ATTRIBUTE_STANDARD_NAME, 0, null);
+			FileInfo fileinfo;
+			while ((fileinfo = enumerator.next_file(null)) != null){
+				file_list.add(this.list_directory.get_path() + "/" + fileinfo.get_name());
+			}
+			return file_list;
+		} catch(Error err){
+			warning("Error: %s\n", err.message);
+			return null;
+		}
+	}
+
+	/*[CCode (instance_pos = -1)]
+	public void on_restoretoggle(Gtk.CellRendererToggle checkbox, int path) {
+		checkbox.set_active(true);
+	}*/
+
+	Gtk.Widget? make_listfiles_page() {
+			/*
+			 * Build list files (introduction) page which shows deleted files.
+			 *
+			 * Build list files page from a Glade template and attach various dynamic
+			 * components to it. Deleted files are dynamically added on-the-fly by
+			 * applicable functions.
+			 */
+
+			// Hack; we need ''page'' because window needs to be reparented to be shown.
+			var page = new Gtk.Table(1, 1, false);
+			page.name = "listfiles_page";
+			var builder = new Gtk.Builder();
+			try {
+				builder.add_from_file("interface/listfiles-crt-out.ui");
+				builder.connect_signals(this);
+				
+				var window = builder.get_object("viewport") as Gtk.Widget;
+				var filelistwindow = builder.get_object("filelistwindow") as Gtk.ScrolledWindow;
+				var status_table = builder.get_object("backup_table") as Gtk.Table;
+				var progress_table = builder.get_object("progress_table") as Gtk.Table;
+
+				/* Add backup and scan information */
+				/* Backup source */
+				Gtk.Widget w = new DejaDup.ConfigLabelLocation();
+				status_table.attach(w, 1, 2, 0, 1, Gtk.AttachOptions.FILL, 0, 0, 0);
+
+				/* Spinner */
+				progress_table.attach(this.spinner, 1, 2, 0, 1, Gtk.AttachOptions.FILL, 0, 0, 0);
+
+				/* Current date of scan */
+				progress_table.attach(this.current_scan_date, 2, 3, 0, 1, Gtk.AttachOptions.FILL, 0, 0, 0);
+				
+				this.listmodel = new Gtk.ListStore (3, typeof (bool), typeof (string), typeof (string));
+				var treeview = new Gtk.TreeView.with_model (this.listmodel);
+				//treeview.set_model(this.listmodel);
+
+				/* Toggle code for checkbox */
+				var toggle = new Gtk.CellRendererToggle();
+				toggle.toggled.connect ((toggle, path) => {
+					stdout.printf("%s\n",this.file_status[path.to_int()].name);
+					
+					if (!this.file_status[path.to_int()].restore)
+						this.file_status[path.to_int()].restore = true;
+					else
+						this.file_status[path.to_int()].restore = false;
+					
+					var tree_path = new Gtk.TreePath.from_string (path);
+          this.listmodel.get_iter (out this.deleted_iter, tree_path);
+          this.listmodel.set(this.deleted_iter, 0, !toggle.active);
+        });
+
+				treeview.insert_column_with_attributes(-1, "", toggle, "active", 0);
+				treeview.insert_column_with_attributes(-1, "File name", new Gtk.CellRendererText(), "text", 1);
+				treeview.insert_column_with_attributes(-1, "Deleted", new Gtk.CellRendererText(), "text", 2);
+ 
+        treeview.set_headers_visible (true);
+
+				filelistwindow.add_with_viewport(treeview);
+
+				/*
+					we have do_prepare, stupid!
+					this.forward.connect((assist) => {
+					uint pathlenght;
+					string path;
+					string pathr;
+					uint pathlenght2;
+					string path2;
+					string pathr2;
+					assist.current.data.page.path(out pathlenght, out path, out pathr);
+					listfiles_page.path(out pathlenght2, out path2, out pathr2);
+					//stdout.printf("\nFORWARD! name: %s\n %s \n %s\n\n", assist.current.data.page.name, path, path2);
+					if (assist.current.data.page.name == "confirm_page") {
+						stdout.printf("\n\n\nlistfilespage mamo! do magic misko!\n");
+						foreach(var delfile in this.file_status) {
+							if (delfile.restore)
+							{
+								stdout.printf("OFFERING: %s\n\n", delfile.name);
+								//this.restore_queue.push_tail(delfile.queue_format());
+								this.restore_queue.offer(delfile);
+								
+								this.restoremodel.append (out this.restoreiter);
+        				this.restoremodel.set(this.restoreiter, 0, delfile.name);
+							}
+						}
+						this.backups_queue.clear();
+					}
+				});*/						
+				window.reparent(page);
+				return page;
+			} catch (Error err) {
+				warning("Error: %s", err.message);
+				return null;
+			}
+	}
+
+	void add_listfiles_page() {
+		var page = make_listfiles_page();
+		append_page(page);
+		set_page_title(page, _("Deleted Files"));
+		listfiles_page = page;
+		//selectfiles_page = page;
+	}		
+
+	//private void deleted_files(Gtk.ListStore listmodel) {
+	//	stdout.printf("\n\ndeleted files\n\n");
+
+		// First, the simples - files from directory
+		//var fid = files_in_directory();
+
+		// Second - get collection dates
+		/*if (backup_dates == null) {
+			stdout.printf("backup_dates == null");
+			if (!collection_dates_query_in_progress) {
+					stdout.printf("collection_dates_query_in_progress = false");
+					do_query_collection_dates();
+			}*/
+			
+			/*foreach(string date in this.backup_dates) {
+				stdout.printf("%s\n", date);
+			}	*/										 
+		//	stdout.printf("gremo naprej, timeout ker ni podatkov");
+			/*Timeout.add_seconds(1, () => {
+					deleted_files(listmodel, true);
+					return false;
+			});*/
+			/*return;
+		} else {
+			stdout.printf("we have backup_dates!");
+			foreach(string date in backup_dates){
+				stdout.printf("datum: %s\n", date);
+			}
+		}*/
+
+		// Third
+	//}
+
+	protected override void add_setup_pages() {
+		add_listfiles_page();
+		//add_restorefiles_page();
+	}
+
+	/*void add_restorefiles_page() {
+		var page = make_restorefiles_page();
+		append_page(page);
+		set_page_title(page, _("About to restore"));
+		//selectfiles_page = page;
+	}*/
+
+	protected override void do_prepare(Assistant assist, Gtk.Widget page) {
+		stdout.printf("do_prepare");
+		base.do_prepare(assist, page);
+
+		if (page == listfiles_page) {
+			stdout.printf("listfiles_page");
+
+			if (!scan_queue) {
+				do_query_files_at_date();
+				scan_queue = true;
+			}
+			else {
+				if (op != null && op.needs_password){
+					provide_password();
+				}	
+				else if (op == null) {
+					do_query_collection_dates();
+				}
+			}
+		}
+		
+		else if (page == confirm_page) {
+			stdout.printf("\nconfirm page\n");
+			scan_queue = false;
+			
+			foreach(var delfile in this.file_status) {
+				if (delfile.restore)
+				{
+					stdout.printf("OFFERING: %s\n\n", delfile.name);
+					//stdout.printf("number of relevent rows: %u", this.restore_files_table.nrows);
+					//this.restore_queue.push_tail(delfile.queue_format());
+					this.restore_queue.offer(delfile);
+					stdout.printf("rowz: %u\n", this.restore_files_table.nrows);
+					//stdout.printf(restore_files_table);
+					this.restore_files_table_rows++;
+					this.restore_files_table.resize(this.restore_files_table_rows, 1);
+					
+					label = new Gtk.Label(delfile.filename());
+					label.set("xalign", 0.0f);
+					label.show();
+					this.restore_files_table.attach(label, 0, 1, this.restore_files_table_rows-1, this.restore_files_table_rows, Gtk.AttachOptions.FILL, 0, 0, 0);
+					/*this.restoremodel.append (out this.restoreiter);
+        	this.restoremodel.set(this.restoreiter, 0, delfile.name);*/
+				}
+			}
+			//this.backups_queue.clear();
+		}
+		else if (page == summary_page) {
+			if (error_occurred)
+        set_page_title(page, _("Restore Failed"));
+      else {
+        set_page_title(page, _("Restore Finished"));
+
+				/* Count the number of files that had to be restored */
+				var numdels = 0; // Number of deleted files
+				foreach(var delfile in this.file_status) {
+					if (delfile.restore) {
+						numdels++;
+					}
+				}
+
+				summary_label.label = ngettext("Your file was successfully restored.",
+                                         "Your files were successfully restored.",
+                                         numdels);
+			}
+		}
+	}
+
+	protected void handle_listed_files(DejaDup.OperationFiles op, string date, string file) {
+		  /*
+			 * Handler for each line returned by duplicity individually
+			 *
+			 * Duplicity returns each file as a separate line that has to be handled individually.
+			 * We therefore check if file in path of directory, if it exists and whether or not it has not been seen before
+			 * and attach it to our TreeView model if all conditions are met.
+			 *
+			 * @param //DejaDup.OperationFiles// ''op'' Operation that is currently running
+			 * @param //string// ''date'' Time of last change of file 
+			 * @param //string// ''file'' Full path of file 
+			 */
+		string filestr = @"/$file";
+		if (this.list_directory.get_path() in filestr && this.list_directory.get_path() != filestr) {
+			var fileobj = File.new_for_path(filestr);
+
+			if (!fileobj.query_exists(null) && !this.allfiles_prev.contains(filestr)) {
+				if(fileobj.has_parent(this.list_directory)) {
+					var fs = new DeletedFile(filestr, op.time);
+
+					this.file_status.add(fs);
+					//var fileinfoobj = fileobj.query_info("standard::*", FileQueryInfoFlags.NONE, null);
+					//stdout.printf("basename: %s", fileinfoobj.get_display_name());
+					
+					this.listmodel.append (out this.deleted_iter);
+        	this.listmodel.set (this.deleted_iter, 0, false, 1, fs.filename(), 2, op.time.format("%c"));
+				
+					this.allfiles_prev.add(filestr);
+				}
+				/*if (file.query_file_type(0, null) == FileType.DIRECTORY) {
+
+				}
+				else if {
+					
+				}*/
+			}
+
+			/*if (!this.allfiles_prev.contains(filestr)) {
+				//[this.list_directory.get_path().length:filestr.length]]
+				
+				var fs = new DeletedFile(filestr, op.time);
+				this.file_status.add(fs);
+					
+				this.listmodel.append (out this.deleted_iter);
+        this.listmodel.set (this.deleted_iter, 0, false, 1, fs.filename(), 2, op.time.format("%c"));
+				
+				this.allfiles_prev.add(filestr);
+			}*/
+		}
+
+		/*if (this.files_at_epoch.has_key(op.time)) {
+				//stdout.printf("%d", this.files_at_epoch.get(op.time));
+				var flist = this.files_at_epoch.get(op.time);
+				flist.add(datefilestr);
+				//this.files_at_epoch.set(op.time, flist);
+		} else {
+			var nlist = new ArrayList<string>();
+			nlist.add(datefilestr);
+			this.files_at_epoch.set(op.time, nlist);
+		}*/
+	}
+
+	protected void handle_collection_dates(DejaDup.OperationStatus op, GLib.List<string>? dates){
+			/*
+			 * Handle collection dates
+			 *
+			 * Collection dates are returned as a single list of strings file timestamps of backup.
+			 * Timestamps are in ISO 8601 format and are first read and converted to //Time// objects and then
+			 * added to backups_queue.
+			 *
+			 * @param //DejaDup.OperationStatus// ''op'' Operation currently being run
+			 * @param //GLib.List<string>?// ''dates'' ISO 8601 dates of backups.
+			 */
+		stdout.printf("\nhandle collection_dates\n");
+    TimeVal tv = TimeVal();
+
+		if (!this.backups_queue_filled) {
+			//foreach(string date in dates){
+			for(var i=dates.length()-1;i > 0;i--){
+				if (tv.from_iso8601(dates.nth(i).data)) {
+					Time t = Time.local(tv.tv_sec);
+					stdout.printf("time of backup: d: %s, tse: %s, cd: %s\n", dates.nth(i).data, t.format("%s"), t.format("%c"));
+					this.backups_queue.offer(t);
+				}
+			}
+		}
+
+		this.allfiles_prev = files_in_directory();
+		this.backups_queue_filled = true;
+
+		this.spinner.start();
+		do_query_files_at_date();
+	}
+
+	protected void do_query_collection_dates() {
+			/*
+			 * Initialize query operation for collection dates.
+			 *
+			 * Initializes query operation and links appropriate signals for when operation
+			 * finishes and when it receives duplicity's output.
+			 */
+		stdout.printf("\ndo_query_collection_dates\n");
+		realize();
+    var xid = Gdk.x11_drawable_get_xid(this.window);
+			
+		query_op_collection_dates = new DejaDup.OperationStatus((uint)xid);
+		query_op_collection_dates.collection_dates.connect(handle_collection_dates);
+		query_op_collection_dates.done.connect(query_collection_dates_finished);
+		
+		if (mount_op == null)
+      mount_op = new MountOperationAssistant(this);
+
+		op = query_op_collection_dates;
+		op.backend.mount_op = mount_op;
+    op.passphrase_required.connect(get_passphrase);
+    op.raise_error.connect((o, e, d) => {show_error(e, d);});
+
+		try {
+			stdout.printf("query_collection_dates start\n");
+      query_op_collection_dates.start();
+    }
+    catch (Error e) {
+      warning("%s\n", e.message);
+      show_error(e.message, null); // not really user-friendly text, but ideally this won't happen
+      query_collection_dates_finished(query_op_collection_dates, false, false);
+    }
+	}
+		
+	protected void do_query_files_at_date(){
+		  /*
+		   * Initializes query operation for list-current-files at specific date 
+			 *
+			 * Initializes query operation, updates list files page with current date of scan
+			 * in human semi-friendly form and connect appropriate signals. 
+		   */
+		if (cancel_assistant) {
+			do_close();
+			return;
+		}
+		Time etime = backups_queue.poll();
+
+		/* Update progress */
+		int tepoch = etime.format("%s").to_int();
+		TimeVal ttoday = TimeVal();
+		ttoday.get_current_time();
+		int ttodayi = (int) ttoday.tv_sec;
+
+		string worddiff;
+		int tdiff =  (ttodayi - tepoch)/60/60; // Hours
+		if (tdiff / 24 == 0 ) {
+			worddiff = _("Last day");
+		}
+		else if (tdiff / 24 / 7 == 0) {
+			worddiff = _("Last week");
+		}
+		else if (tdiff / 24 / 30 == 0) {
+			worddiff = _("Last month");
+		}
+		else if (tdiff / 24 / 30 > 1 && tdiff / 24 / 30 < 12) {
+			int n = tdiff / 24 / 30;
+			worddiff = _(@"About $n months ago");
+		}
+		else {
+			int n = tdiff / 24 / 30 / 12;
+			worddiff = _(@"About $n years ago");
+		}
+		//stdout.printf("\n\ntepch: %i, ttodayi: %i, tdiff: %i\n\n", tepoch, ttodayi, tdiff);
+		this.current_scan_date.set_text(worddiff);
+		
+		stdout.printf("ADH do query, at epoch time: %s\n", etime.format("%c"));
+		if (mount_op == null)
+      mount_op = new MountOperationAssistant(this);
+
+		realize();
+    var xid = Gdk.x11_drawable_get_xid(this.window);
+
+		/* Time object does not support GObject-style construction */
+		query_op_files = new DejaDup.OperationFiles((uint)xid, etime, list_directory);
+		//query_op_files.time = etime;
+		query_op_files.listed_current_files.connect(handle_listed_files);
+    query_op_files.done.connect(query_files_finished);
+		
+    op = query_op_files;
+    op.backend.mount_op = mount_op;
+    op.passphrase_required.connect(get_passphrase);
+    op.raise_error.connect((o, e, d) => {show_error(e, d);});
+    
+    try {
+      query_op_files.start();
+    }
+    catch (Error e) {
+      warning("%s\n", e.message);
+      show_error(e.message, null); // not really user-friendly text, but ideally this won't happen
+      query_files_finished(query_op_files, false, false);
+    }
+	}
+
+	protected void query_collection_dates_finished(DejaDup.Operation op, bool success, bool cancelled) {
+    op_state = op.get_state();
+    //this.query_op_files = null;
+		query_op_collection_dates = null;
+    op = null;
+    
+    if (cancelled) {
+      do_close();
+			//stdout.printf("fail\n");
+		}
+    else if (success)
+      //go_forward();
+			stdout.printf("success\n");
+	}
+
+	protected void query_wrapup() {
+		stdout.printf("\nQUERY WRAPUP\n");
+		//var deleted = new ArrayList<string>();
+
+		/*var iterator = files_at_epoch.map_iterator();
+		var has_next = iterator.first();
+
+		allfiles_prev = iterator.get_value();
+		has_next = iterator.next();
+		while (has_next == true) {
+			allfiles_cur = iterator.get_value();
+			foreach(string pfile in allfiles_prev) {
+				if (!allfiles_cur.contains(pfile)) {
+					deleted.add(pfile);
+				}
+			}
+			allfiles_prev = allfiles_cur;
+			has_next = iterator.next();
+		}
+
+		foreach(var elem in deleted) {
+			stdout.printf("%s", elem);
+		}*/
+		//printlist(deleted);
+		//foreach(var edate in files_at_epoch){
+			//stdout.printf("%s %s\n", edate.key,edate.value[3]);
+
+			
+			
+			/*foreach(string file in edate.value) {
+				stdout.printf("%s %s\n", edate.key,file);
+			}*/
+		//}
+	}
+
+	protected override void do_cancel() {
+			/*
+			 * Mark cancel_assistant as true so that all other operations are blocked.
+			 *
+			 * do_cancel kills current operation but because we are still running recursion
+			 * and at the end of each operation still check if we have anything to deleted,
+			 * we need to manually mark entire assistant as canceled so that no further
+			 * operations are called.
+			 */
+		cancel_assistant = true;
+		base.do_cancel();
+	}
+
+	protected override void apply_finished(DejaDup.Operation op, bool success, bool cancelled)
+  {
+			/*
+			 * Ran after assistant finishes applying restore operation.
+			 *
+			 * After assistant finishes with initial OperationRestore, apply_finished is called. Afterwards we
+			 * check if restore_queue is empty and if not, rerun apply function. If it is, we move to
+			 * summary page.
+			 */
+    //status_icon = null; PRIV PARAMETER - FIXIT!
+    op = null;
+
+		stdout.printf("\n\napply_finished\n\n");
+
+    if (cancelled) {
+      if (success) // stop (resume later) vs cancel
+        Gtk.main_quit();
+      else {
+				stdout.printf("do close!\n");
+				do_close();
+			}
+    }
+    else {
+      if (success) {
+        succeeded = true;
+				stdout.printf("restore queue size: %u", this.restore_queue.size);
+				stdout.printf("what to restore: %s\n", this.restore_queue.peek().name);
+				if (this.restore_queue.size > 0) {
+					stdout.printf("apply finished v ADH; we need more restoring!");
+					base.do_apply();
+				} else {
+					stdout.printf("no more files to restore");
+					go_to_page(summary_page);
+				}
+      }
+      else // show error
+        force_visible(false);
+    }
+  }
+	
+	protected void query_files_finished(DejaDup.Operation op, bool success, bool cancelled)
+  {
+		op_state = op.get_state();
+    query_op_files = null;
+		//this.query_op_collection_dates = null;
+    op = null;
+		
+		if (backups_queue.size == 0) {
+			this.spinner.stop();
+			this.spinner.destroy();
+			this.current_scan_date.set_text("Done!");
+			scan_queue = false;
+		}
+		else {
+			if (scan_queue)
+				do_query_files_at_date();
+		}
+    
+    if (cancelled) {
+      do_close();
+			stdout.printf("fail\n");
+		}
+    else if (success)
+      //go_forward();
+			stdout.printf("success\n");
+  }
+
+	protected override Gtk.Widget? make_confirm_page(){
+			/*
+			 * Build confirmation page and add various dynamic elements to Glade template
+			 */
+		var page = new Gtk.Table(1, 1, false);
+		page.name = "confirm_page";
+		var builder = new Gtk.Builder();
+		try {
+			//builder.add_from_file("interface/restorefiles.glade");
+			builder.add_from_file("interface/directory_history_confirmation_page.glade");
+			//builder.connect_signals(this);
+			
+			var window = builder.get_object("viewport") as Gtk.Widget;
+			var backup_source_properties = builder.get_object("backup_properties") as Gtk.Table;
+			restore_files_table = builder.get_object("restore_files") as Gtk.Table;
+			Gtk.Widget w;
+
+			w = new DejaDup.ConfigLabelLocation();
+			backup_source_properties.attach(w, 1, 2, 0, 1, Gtk.AttachOptions.FILL, 0, 0, 0);
+
+			w = new DejaDup.ConfigLabelBool(DejaDup.ENCRYPT_KEY);
+			backup_source_properties.attach(w, 1, 2, 1, 2, Gtk.AttachOptions.FILL, 0, 0, 0);
+
+			//var label = new Gtk.Label("make_confirm_page");
+			//label.set("xalign", 0.0f);
+			//restore_files_table.attach(label, 0, 1, 0, 1, Gtk.AttachOptions.FILL, 0, 0, 0);
+			/*label = new Gtk.Label("meh 2");
+			label.set("xalign", 0.0f);
+			restore_files_table.attach(label, 0, 1, 1, 2, Gtk.AttachOptions.FILL, 0, 0, 0);*/
+
+			//int rows = 2;
+			/*for (var i=0; i<50; i++){
+				label = new Gtk.Label("row %d".printf(rows));
+				label.set("xalign", 0.0f);
+				rows++;
+				restore_files_table.resize(rows, 1);
+				restore_files_table.attach(label, 0, 1, rows, rows+1, Gtk.AttachOptions.FILL, 0, 0, 0);
+			}*/
+    	
+			//stdout.printf(restore_files_table);
+			
+    	//label.set("xalign", 0.0f);
+			//restore_files_table.attach(label, 0, 1, 1, 2, Gtk.AttachOptions.FILL, 0, 0, 0);
+			//int rows = 0;
+			//confirm_table = new Gtk.Table(rows, 1, false);
+			
+
+			/*var restorefiles = builder.get_object("restorefileswindow") as Gtk.ScrolledWindow;
+			
+			this.restoremodel = new Gtk.ListStore(1, typeof(string));
+			var _tree_view = new Gtk.TreeView.with_model(this.restoremodel);
+			
+			_tree_view.insert_column_with_attributes(-1, "File name", new Gtk.CellRendererText(), "text", 0);
+
+			_tree_view.set_headers_visible (true);	
+			restorefiles.add_with_viewport(_tree_view);*/
+
+			window.reparent(page);
+			return page;
+		} catch (Error err) {
+			warning("Error: %s", err.message);
+			return null;
+		}
+	}
+
+	/*protected override DejaDup.Operation create_op() {
+		realize();
+		stdout.printf("create_op");
+		var xid = Gdk.x11_drawable_get_xid(this.window);
+		return new DejaDup.OperationFiles((uint)xid);
+	}*/
+	protected override DejaDup.Operation create_op()
+  {
+			/*
+			 * Creates operation that is then called by do_apply.
+			 */
+		stdout.printf("create_op\n");
+    realize();
+    var xid = Gdk.x11_drawable_get_xid(this.window);
+		/*	var rest_op = new DejaDup.OperationRestore(restore_location, date,
+                                               restore_files, (uint)xid);*/
+
+		stdout.printf("resture queue before length: %x\n", this.restore_queue.size);
+
+		var restore_file = this.restore_queue.poll();
+		stdout.printf("resture queue before after: %x\n", this.restore_queue.size);
+		//var restore_file = restore_queue.nth(0);
+		//var restore_file = restore_queue.pop_head();
+		//restore_queue.remove(restore_file);
+		/*
+		OperationRestore usually takes list of file so restore. Since it is high 
+		probability that if we will restore multiple files, they will be from different dates,
+		we simply call OperationRestore multiple times with singel date and file.
+		*/
+		
+		var restore_files = new GLib.List<File>(); 
+		//restore_files.append(File.new_for_path(restore_file.split(" ")[0]));
+		restore_files.append(File.new_for_path(restore_file.name));
+		//2001-07-15T04:09:38-07:00
+		//restore_file.deleted.format("%FT%T%z"))
+		//stdout.printf("name:%s time: %s", restore_file, restore_file.deleted.format("%FT%T%z"));
+		//restore_file.split(" ")[1]]
+		
+		var rest_op = new DejaDup.OperationRestore("/", 
+		    																			 restore_file.deleted.format("%s"),
+		    																			 restore_files,
+		    																			 (uint)xid);
+		return rest_op;
+  }
+		
+	protected override string get_progress_file_prefix(){
+		return _("Restoring");
+	}
+}
\ No newline at end of file

=== modified file 'deja-dup/AssistantOperation.vala'
--- deja-dup/AssistantOperation.vala	2010-06-14 01:06:33 +0000
+++ deja-dup/AssistantOperation.vala	2010-07-12 16:58:42 +0000
@@ -21,6 +21,23 @@
 
 public abstract class AssistantOperation : Assistant
 {
+  /*
+   * Abstract class for implementation of various common pages in assistant
+   *
+   * Abstract class that provides various methods that serve as pages in
+   * assistant. Required methods that all classes that inherit from this
+   * class must implement are create_op, make_confirm_page and
+   * get_progress_file_prefix.
+   *
+   * Pages are shown in the following order:
+   * 1. (Optional) Custom configuration pages
+   * 2. Setup pages
+   * 3. Confirmation page
+   * 4. Password page
+   * 5. Question page
+   * 6. (Required) Progress page
+   * 7. Summary
+   */
   protected Gtk.Widget confirm_page {get; private set;}
   public signal void closing(bool success);
   
@@ -79,10 +96,23 @@
     closed.connect(do_close);
     prepare.connect(do_prepare);
   }
-  
+
+  /*
+   * Creates confirmation page for particular assistant
+   *
+   * Creates confirmation page that should create confirm_page widget that
+   * is presented for final confirmation.
+   */
   protected abstract Gtk.Widget? make_confirm_page();
   protected virtual void add_setup_pages() {}
-  protected virtual void add_custom_config_pages() {}
+  protected virtual void add_custom_config_pages(){}
+  /*
+   * Creates and calls appropriate operation
+   *
+   * Creates and calls appropriate operation (Backup, Restore, Status, Files)
+   * that is then used to perform various defined tasks on backend. It is
+   * also later connected to various signals.
+   */
   protected abstract DejaDup.Operation create_op();
   protected abstract string get_progress_file_prefix();
   protected virtual void set_op_icon_name() {}
@@ -111,6 +141,11 @@
   
   void show_progress(DejaDup.Operation op, double percent)
   {
+    /*
+     * Updates prograss bar
+     *
+     * Updates progress bar with percet provided.
+     */
     progress_bar.fraction = percent;
     gives_progress = true;
   }
@@ -324,6 +359,11 @@
   
   void add_config_pages_if_needed()
   {
+    /*
+     * Creates configure pages if required
+     *
+     * 
+     */
     var client = DejaDup.get_gconf_client();
     string val;
     try {
@@ -341,6 +381,11 @@
   
   void add_confirm_page()
   {
+    /*
+     * Adds confirm page to the sequence of pages
+     *
+     * Adds confirm_page widget to the sequence of pages in assistant.
+     */
     var page = make_confirm_page();
     if (page == null)
       return;
@@ -378,10 +423,10 @@
     summary_page = page;
   }
   
-  void apply_finished(DejaDup.Operation op, bool success, bool cancelled)
+  protected virtual void apply_finished(DejaDup.Operation op, bool success, bool cancelled)
   {
     status_icon = null;
-    this.op = null;
+    op = null;
 
     if (cancelled) {
       if (success) // stop (resume later) vs cancel
@@ -399,8 +444,15 @@
     }
   }
   
-  void do_apply()
+  protected void do_apply()
   {
+    /*
+     * Applies/starts operation that was configured during assistant process and
+     * connect appropriate signals
+     *
+     * Mounts appropriate backend, creates child operation, connects signals to
+     * handler functions and starts operation.
+     */
     if (mount_op == null)
       mount_op = new MountOperationAssistant(this);
 
@@ -432,6 +484,17 @@
 
   protected virtual void do_prepare(Assistant assist, Gtk.Widget page)
   {
+    /*
+     * Prepare page in assistant
+     *
+     * Prepares every page in assistant for various operations. For example, if 
+     * user returns to confirmation page from progress page, it is necessary
+     * to kill running operation. If user advances to progress page, it runs
+     * do_apply and runs the needed operation.
+     *
+     * do_prepare is run when user switches pages and not when pages are built.
+     */
+
     if (timeout_id > 0) {
       Source.remove(timeout_id);
       timeout_id = 0;
@@ -464,11 +527,14 @@
     status_icon = null; // hide immediately to seem responsive
   }
 
-  void do_cancel()
+  protected virtual void do_cancel()
   {
+    stdout.printf("\n\ndo_cancel\n\n");
     hide_everything();
-    if (op != null)
+    if (op != null) {
+      stdout.printf("\nop != null => op.cancel\n");
       op.cancel(); // do_close will happen in done() callback
+    }
     else
       do_close();
   }
@@ -532,24 +598,32 @@
 
   void found_passphrase(GnomeKeyring.Result result, string? str)
   {
-    if (str != null)
+    stdout.printf("found_passphrase\n");
+    if (str != null) {
+      stdout.printf("mam passphrase\n");
       op.continue_with_passphrase(str);
-    else
+    }
+    else {
+      stdout.printf("sprasujem za passphrase\n");
       ask_passphrase();
+    }
   }
 
   protected void get_passphrase()
   {
+    stdout.printf("\nget_passphrase\n");
     // DEJA_DUP_TESTING only set when we are in test suite
     var testing = Environment.get_variable("DEJA_DUP_TESTING");
     if (testing == null || testing == "") {
       // First, try user's keyring
+      stdout.printf("pass v keyringu\n");
       GnomeKeyring.find_password(PASSPHRASE_SCHEMA,
                                  found_passphrase,
                                  "owner", Config.PACKAGE,
                                  "type", "passphrase");
     }
     else {
+      stdout.printf("\nasking user\n");
       // just jump straight to asking user
       ask_passphrase();
     }
@@ -582,7 +656,7 @@
       }
     }
     
-    op.continue_with_passphrase(passphrase);
+    //op.continue_with_passphrase(passphrase);
   }
 
   void stop_question(Gtk.Dialog dlg, int resp)

=== modified file 'deja-dup/AssistantRestore.vala'
--- deja-dup/AssistantRestore.vala	2010-06-14 01:06:33 +0000
+++ deja-dup/AssistantRestore.vala	2010-07-12 16:58:42 +0000
@@ -315,6 +315,13 @@
 
   protected void handle_collection_dates(DejaDup.OperationStatus op, List<string>? dates)
   {
+    /*
+     * Receives list of dates of backups and shows them to user
+     *
+     * After receiving list of dates at which backups were performed function
+     * converts dates to TimeVal structures and later converts them to Time to
+     * time to show them in nicely formate local form.
+     */
     var timevals = new List<TimeVal?>();
     TimeVal tv = TimeVal();
     

=== modified file 'deja-dup/Makefile.am'
--- deja-dup/Makefile.am	2010-03-25 21:40:33 +0000
+++ deja-dup/Makefile.am	2010-07-12 16:58:42 +0000
@@ -23,6 +23,8 @@
 	--vapidir $(top_srcdir)/widgets \
 	--vapidir $(top_srcdir)/vapi \
 	--pkg gtk+-2.0 \
+	--pkg gee-1.0 \
+	--pkg gmodule-2.0 \
 	--pkg gdk-x11-2.0 \
 	--pkg gio-2.0 \
 	--pkg gconf-2.0 \
@@ -46,6 +48,7 @@
 	Assistant.vala \
 	AssistantBackup.vala \
 	AssistantOperation.vala \
+	AssistantDirectoryHistory.vala \
 	AssistantRestore.vala \
 	MainWindow.vala \
 	MountOperationAssistant.vala \

=== modified file 'deja-dup/main.vala'
--- deja-dup/main.vala	2010-05-10 09:54:06 +0000
+++ deja-dup/main.vala	2010-07-12 16:58:42 +0000
@@ -27,12 +27,14 @@
   static bool show_version = false;
   static bool restore_mode = false;
   static bool backup_mode = false;
+  static bool dirhistory_mode = false;
   static string[] filenames = null;
   static const OptionEntry[] options = {
     {"version", 0, 0, OptionArg.NONE, ref show_version, N_("Show version"), null},
     {"restore", 0, 0, OptionArg.NONE, ref restore_mode, N_("Restore given files"), null},
     {"backup", 0, 0, OptionArg.NONE, ref backup_mode, N_("Immediately start a backup"), null},
-    {"", 0, 0, OptionArg.FILENAME_ARRAY, ref filenames, null, null}, // remaining
+    {"dir-history", 0, 0, OptionArg.NONE, ref dirhistory_mode, N_("Directory history"), null},
+    {"", 0, 0, OptionArg.FILENAME_ARRAY, ref filenames, null, null}, // remaining    
     {null}
   };
   
@@ -52,6 +54,19 @@
         return false;
       }
     }
+
+    if (dirhistory_mode) {
+      if (filenames == null) {
+        printerr("%s\n", _("No directory provided"));
+        status = 1;
+        return false;
+      }
+      else if (filenames.length > 1) {
+        printerr("%s\n", _("Only one directory can be shown at once"));
+        status = 1;
+        return false;
+      }
+    }
     
     return true;
   }
@@ -110,6 +125,30 @@
       toplevel.destroy.connect((t) => {Gtk.main_quit();});
       // specifically don't show
     }
+    else if (dirhistory_mode){
+      //try {
+        //toplevel = new AssistantDirectoryHistory();
+        /*var assdirhist = new AssistantDirectoryHistory();
+        var intdirhist = new InterfaceDirectoryHistory();
+        var builder = new Gtk.Builder();
+        builder.add_from_file("/home/urbans/Documents/dev/deja-dup.nautilus/interface/sample.ui");
+        builder.connect_signals(assdirhist);
+        //builder.connect_signals(null);
+        var window = builder.get_object("window") as Gtk.Window;*/
+        
+        //List<File> file_list = new List<File>();
+        
+        //file_list.append(File.new_for_commandline_arg(filenames[i++]));
+        File list_directory = File.new_for_commandline_arg(filenames[0]);
+
+        //return 1;
+        toplevel = new AssistantDirectoryHistory(list_directory);
+        toplevel.destroy.connect((t) => {Gtk.main_quit();});
+        toplevel.show_all();
+      /*} catch (Error e) {
+        stderr.printf("ni ni interfejsa: %s\n", e.message);
+      }*/
+    }
     else {
       toplevel = new MainWindow();
       toplevel.show_all();

=== added directory 'interface'
=== added file 'interface/directory_history_confirmation_page.glade'
--- interface/directory_history_confirmation_page.glade	1970-01-01 00:00:00 +0000
+++ interface/directory_history_confirmation_page.glade	2010-07-12 16:58:42 +0000
@@ -0,0 +1,109 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkWindow" id="window1">
+    <child>
+      <object class="GtkViewport" id="viewport">
+        <property name="visible">True</property>
+        <property name="resize_mode">queue</property>
+        <child>
+          <object class="GtkVBox" id="maintable">
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkTable" id="backup_properties">
+                <property name="visible">True</property>
+                <property name="n_rows">2</property>
+                <property name="n_columns">2</property>
+                <property name="row_spacing">2</property>
+                <child>
+                  <object class="GtkLabel" id="label1">
+                    <property name="width_request">1</property>
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">Backup source</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label2">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">Encrypted</property>
+                  </object>
+                  <packing>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="x_options">GTK_FILL</property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="padding">3</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkHSeparator" id="hseparator1">
+                <property name="visible">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkVBox" id="vbox1">
+                <property name="visible">True</property>
+                <child>
+                  <object class="GtkLabel" id="label3">
+                    <property name="visible">True</property>
+                    <property name="xalign">0.029999999329447746</property>
+                    <property name="label" translatable="yes">Restoring files:</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkScrolledWindow" id="scrolledwindow1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hscrollbar_policy">automatic</property>
+                    <property name="vscrollbar_policy">automatic</property>
+                    <child>
+                      <object class="GtkViewport" id="viewport1">
+                        <property name="visible">True</property>
+                        <property name="resize_mode">queue</property>
+                        <child>
+                          <object class="GtkTable" id="restore_files">
+                            <property name="visible">True</property>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>

=== added file 'interface/listfiles-crt-out.ui'
--- interface/listfiles-crt-out.ui	1970-01-01 00:00:00 +0000
+++ interface/listfiles-crt-out.ui	2010-07-12 16:58:42 +0000
@@ -0,0 +1,144 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkListStore" id="deletedfiles">
+    <columns>
+      <!-- column-name Restore -->
+      <column type="gboolean"/>
+      <!-- column-name File -->
+      <column type="gchararray"/>
+      <!-- column-name Deleted -->
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0">True</col>
+        <col id="1" translatable="yes">foo.txt</col>
+        <col id="2" translatable="yes">12. 3. 2009</col>
+      </row>
+      <row>
+        <col id="0">False</col>
+        <col id="1" translatable="yes">bar.txt</col>
+        <col id="2" translatable="yes">19.7.2008</col>
+      </row>
+    </data>
+  </object>
+  <object class="GtkWindow" id="window">
+    <property name="default_width">300</property>
+    <property name="default_height">200</property>
+    <signal name="destroy" handler="gtk_main_quit"/>
+    <child>
+      <object class="GtkViewport" id="viewport">
+        <property name="visible">True</property>
+        <property name="resize_mode">queue</property>
+        <child>
+          <object class="GtkVBox" id="vbox1">
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkTable" id="backup_table">
+                <property name="visible">True</property>
+                <property name="n_rows">2</property>
+                <property name="n_columns">3</property>
+                <child>
+                  <object class="GtkLabel" id="label2">
+                    <property name="visible">True</property>
+                    <property name="xpad">10</property>
+                    <property name="ypad">5</property>
+                    <property name="label" translatable="yes">Backup source</property>
+                  </object>
+                  <packing>
+                    <property name="x_options"></property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label3">
+                    <property name="visible">True</property>
+                    <property name="xalign">1</property>
+                    <property name="yalign">0.44999998807907104</property>
+                    <property name="xpad">10</property>
+                    <property name="ypad">5</property>
+                    <property name="label" translatable="yes">Status</property>
+                    <property name="width_chars">10</property>
+                  </object>
+                  <packing>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="x_options"></property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkTable" id="progress_table">
+                    <property name="visible">True</property>
+                    <property name="n_columns">2</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow" id="filelistwindow">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hscrollbar_policy">automatic</property>
+                <property name="vscrollbar_policy">automatic</property>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkHBox" id="hbox1">
+                <property name="visible">True</property>
+                <child>
+                  <object class="GtkLabel" id="label1">
+                    <property name="visible">True</property>
+                  </object>
+                  <packing>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>

=== added file 'interface/listfiles.ui'
--- interface/listfiles.ui	1970-01-01 00:00:00 +0000
+++ interface/listfiles.ui	2010-07-12 16:58:42 +0000
@@ -0,0 +1,164 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkListStore" id="deletedfiles">
+    <columns>
+      <!-- column-name Restore -->
+      <column type="gboolean"/>
+      <!-- column-name File -->
+      <column type="gchararray"/>
+      <!-- column-name Deleted -->
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0">True</col>
+        <col id="1" translatable="yes">foo.txt</col>
+        <col id="2" translatable="yes">12. 3. 2009</col>
+      </row>
+      <row>
+        <col id="0">False</col>
+        <col id="1" translatable="yes">bar.txt</col>
+        <col id="2" translatable="yes">19.7.2008</col>
+      </row>
+    </data>
+  </object>
+  <object class="GtkWindow" id="window">
+    <property name="default_width">300</property>
+    <property name="default_height">200</property>
+    <signal name="destroy" handler="gtk_main_quit"/>
+    <child>
+      <object class="GtkViewport" id="viewport">
+        <property name="visible">True</property>
+        <property name="resize_mode">queue</property>
+        <child>
+          <object class="GtkVBox" id="vbox1">
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkHBox" id="hbox3">
+                <property name="visible">True</property>
+                <child>
+                  <object class="GtkLabel" id="status">
+                    <property name="width_request">65</property>
+                    <property name="height_request">21</property>
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">Currently </property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="timediff">
+                    <property name="visible">True</property>
+                  </object>
+                  <packing>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="entry1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="invisible_char">&#x25CF;</property>
+                    <property name="text" translatable="yes">Search</property>
+                  </object>
+                  <packing>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow" id="scrolledwindow1">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hscrollbar_policy">automatic</property>
+                <property name="vscrollbar_policy">automatic</property>
+                <child>
+                  <object class="GtkTreeView" id="treeview">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="model">deletedfiles</property>
+                    <property name="reorderable">True</property>
+                    <property name="search_column">1</property>
+                    <property name="enable_grid_lines">horizontal</property>
+                    <property name="enable_tree_lines">True</property>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="checkboxcolumn">
+                        <property name="clickable">True</property>
+                        <property name="reorderable">True</property>
+                        <property name="sort_indicator">True</property>
+                        <child>
+                          <object class="GtkCellRendererToggle" id="restoretoggle">
+                            <signal name="toggled" handler="assistant_directory_history_on_restoretoggle"/>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="filenamecolumn">
+                        <property name="title">File name</property>
+                        <property name="reorderable">True</property>
+                        <property name="sort_indicator">True</property>
+                        <property name="sort_column_id">1</property>
+                        <child>
+                          <object class="GtkCellRendererText" id="filenametext"/>
+                          <attributes>
+                            <attribute name="text">1</attribute>
+                          </attributes>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="datecolumn">
+                        <property name="title">Deleted</property>
+                        <property name="reorderable">True</property>
+                        <property name="sort_indicator">True</property>
+                        <child>
+                          <object class="GtkCellRendererText" id="datetext"/>
+                          <attributes>
+                            <attribute name="text">2</attribute>
+                          </attributes>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkHBox" id="hbox1">
+                <property name="visible">True</property>
+                <child>
+                  <object class="GtkLabel" id="label1">
+                    <property name="visible">True</property>
+                  </object>
+                  <packing>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>

=== added file 'interface/restorefiles.glade'
--- interface/restorefiles.glade	1970-01-01 00:00:00 +0000
+++ interface/restorefiles.glade	2010-07-12 16:58:42 +0000
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkWindow" id="window">
+    <child>
+      <object class="GtkViewport" id="viewport">
+        <property name="visible">True</property>
+        <property name="resize_mode">queue</property>
+        <child>
+          <object class="GtkVBox" id="vbox1">
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">You will restore the following files:</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow" id="restorefileswindow">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hscrollbar_policy">automatic</property>
+                <property name="vscrollbar_policy">automatic</property>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label2">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Click Forward to proceed</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>

=== renamed file 'po/deja-dup.pot' => 'po/deja-dup.pot.THIS'

Follow ups