Index: src/interface/resources/menus.xrc
===================================================================
--- src/interface/resources/menus.xrc	(revision 1608)
+++ src/interface/resources/menus.xrc	(working copy)
@@ -171,6 +171,42 @@
         <checkable>1</checkable>
       </object>
     </object>
+    <object class="wxMenu" name="ID_ACTIONAFTER">
+      <label>Action after queue &amp;completion</label>
+      <object class="wxMenuItem" name="ID_ACTIONAFTER_CLOSE">
+        <label>&amp;Close FileZilla</label>
+        <checkable>1</checkable>
+      </object>
+      <object class="wxMenuItem" name="ID_ACTIONAFTER_DISCONNECT">
+        <label>&amp;Disconnect from server</label>
+        <checkable>1</checkable>
+      </object>
+      <object class="wxMenuItem" name="ID_ACTIONAFTER_RUNCOMMAND">
+        <label>&amp;Run command...</label>
+        <checkable>1</checkable>
+      </object>
+      <object class="wxMenuItem" name="ID_ACTIONAFTER_SHOWMESSAGE">
+        <label>&amp;Show message</label>
+        <checkable>1</checkable>
+      </object>
+      <object class="wxMenuItem" name="ID_ACTIONAFTER_PLAYSOUND">
+        <label>&amp;Play sound</label>
+        <checkable>1</checkable>
+      </object>
+      <object class="wxMenuItem" name="ID_ACTIONAFTER_REBOOT" platform="win">
+        <label>&amp;Reboot system</label>
+        <checkable>1</checkable>
+      </object>
+      <object class="wxMenuItem" name="ID_ACTIONAFTER_SHUTDOWN" platform="win">
+        <label>&amp;Shutdown system</label>
+        <checkable>1</checkable>
+      </object>
+      <object class="separator"/>
+      <object class="wxMenuItem" name="ID_ACTIONAFTER_DISABLE" platform="win">
+        <label>&amp;Do nothing</label>
+        <checkable>1</checkable>
+      </object>
+    </object>
   </object>
   <object class="wxMenu" name="ID_MENU_LOG">
     <object class="wxMenuItem" name="ID_MENU_SERVER_CMD">
@@ -253,4 +289,4 @@
       <help>Change the file permissions.</help>
     </object>
   </object>
-</resource>
\ No newline at end of file
+</resource>
Index: src/interface/QueueView.h
===================================================================
--- src/interface/QueueView.h	(revision 1608)
+++ src/interface/QueueView.h	(working copy)
@@ -3,6 +3,7 @@
 
 #include <set>
 #include "dndobjects.h"
+#include <wx/progdlg.h>
 
 struct t_newEntry
 {
@@ -12,6 +13,21 @@
 	wxLongLong size;
 };
 
+enum ActionAfterState
+{
+	ActionAfterState_Disabled,
+	ActionAfterState_Close,
+	ActionAfterState_Disconnect,
+	ActionAfterState_RunCommand,
+	ActionAfterState_ShowMessage,
+	ActionAfterState_PlaySound,
+// On Windows, wx can reboot or shutdown the system as well.
+#ifdef __WXMSW__
+	ActionAfterState_Reboot,
+	ActionAfterState_Shutdown
+#endif
+};
+
 class CStatusLineCtrl;
 struct t_EngineData
 {
@@ -108,6 +124,8 @@
 		retry,
 		remove
 	};
+	
+	enum ActionAfterState GetActionAfterState() const;
 
 	void ResetEngine(t_EngineData& data, const enum ResetReason reason);
 	void DeleteEngines();
@@ -126,6 +144,10 @@
 	void DisplayQueueSize();
 	void SaveQueue();
 	bool ShouldUseBinaryMode(wxString filename);
+	
+	bool IsActionAfter(enum ActionAfterState);
+	void ActionAfter(bool warned = false);
+	void ActionAfterWarnUser(wxString message);
 
 	void ProcessNotification(t_EngineData* pEngineData, CNotification* pNotification);
 
@@ -158,6 +180,11 @@
 	int m_activeCountUp;
 	int m_activeMode; // 0 inactive, 1 only immediate transfers, 2 all
 	bool m_quit;
+	enum ActionAfterState m_actionAfterState;
+	wxString m_actionAfterRunCommand;
+	wxTimer* m_actionAfterTimer;
+	wxProgressDialog* m_actionAfterWarnDialog;
+	int m_actionAfterTimerCount;
 
 	wxLongLong m_totalQueueSize;
 	int m_filesWithUnknownSize;
@@ -192,6 +219,18 @@
 	void OnSetPriority(wxCommandEvent& event);
 
 	void OnExclusiveEngineRequestGranted(wxCommandEvent& event);
+
+	void OnActionAfterDisable(wxCommandEvent& event);
+	void OnActionAfterClose(wxCommandEvent& event);
+	void OnActionAfterDisconnect(wxCommandEvent& event);
+	void OnActionAfterRunCommand(wxCommandEvent& event);
+	void OnActionAfterTimerTick(wxTimerEvent & event);
+	void OnActionAfterShowMessage(wxCommandEvent& event);
+	void OnActionAfterPlaySound(wxCommandEvent& event);
+#ifdef __WXMSW__
+	void OnActionAfterReboot(wxCommandEvent& event);
+	void OnActionAfterShutdown(wxCommandEvent& event);
+#endif
 };
 
 #endif
Index: src/interface/QueueView.cpp
===================================================================
--- src/interface/QueueView.cpp	(revision 1608)
+++ src/interface/QueueView.cpp	(working copy)
@@ -19,6 +19,9 @@
 #include "queueview_failed.h"
 #include "queueview_successful.h"
 #include "commandqueue.h"
+#include <wx/utils.h>
+#include <wx/progdlg.h>
+#include <wx/sound.h>
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
@@ -142,6 +145,9 @@
 DECLARE_EVENT_TYPE(fzEVT_ASKFORPASSWORD, -1)
 DEFINE_EVENT_TYPE(fzEVT_ASKFORPASSWORD)
 
+DECLARE_EVENT_TYPE(fzEVT_ACTIONAFTER_WARN, -1)
+DEFINE_EVENT_TYPE(fzEVT_ACTIONAFTER_WARN)
+
 BEGIN_EVENT_TABLE(CQueueView, CQueueViewBase)
 EVT_FZ_NOTIFICATION(wxID_ANY, CQueueView::OnEngineEvent)
 EVT_COMMAND(wxID_ANY, fzEVT_FOLDERTHREAD_COMPLETE, CQueueView::OnFolderThreadComplete)
@@ -155,11 +161,20 @@
 EVT_MENU(XRCID("ID_REMOVEALL"), CQueueView::OnStopAndClear)
 EVT_MENU(XRCID("ID_REMOVE"), CQueueView::OnRemoveSelected)
 EVT_MENU(XRCID("ID_DEFAULT_FILEEXISTSACTION"), CQueueView::OnSetDefaultFileExistsAction)
+EVT_MENU(XRCID("ID_ACTIONAFTER_DISABLE"), CQueueView::OnActionAfterDisable)
+EVT_MENU(XRCID("ID_ACTIONAFTER_CLOSE"), CQueueView::OnActionAfterClose)
+EVT_MENU(XRCID("ID_ACTIONAFTER_DISCONNECT"), CQueueView::OnActionAfterDisconnect)
+EVT_MENU(XRCID("ID_ACTIONAFTER_RUNCOMMAND"), CQueueView::OnActionAfterRunCommand)
+EVT_MENU(XRCID("ID_ACTIONAFTER_SHOWMESSAGE"), CQueueView::OnActionAfterShowMessage)
+EVT_MENU(XRCID("ID_ACTIONAFTER_PLAYSOUND"), CQueueView::OnActionAfterPlaySound)
+EVT_MENU(XRCID("ID_ACTIONAFTER_REBOOT"), CQueueView::OnActionAfterReboot)
+EVT_MENU(XRCID("ID_ACTIONAFTER_SHUTDOWN"), CQueueView::OnActionAfterShutdown)
 
 EVT_COMMAND(wxID_ANY, fzEVT_ASKFORPASSWORD, CQueueView::OnAskPassword)
 
 EVT_LIST_ITEM_FOCUSED(wxID_ANY, CQueueView::OnFocusItemChanged)
 
+EVT_TIMER(fzEVT_ACTIONAFTER_WARN,CQueueView::OnActionAfterTimerTick)
 EVT_TIMER(wxID_ANY, CQueueView::OnTimer)
 
 EVT_MENU(XRCID("ID_PRIORITY_HIGHEST"), CQueueView::OnSetPriority)
@@ -411,6 +426,8 @@
 
 	m_totalQueueSize = 0;
 	m_filesWithUnknownSize = 0;
+	
+	m_actionAfterState = ActionAfterState_Disabled;
 
 	CreateColumns(_("Status"));
 
@@ -1413,6 +1430,7 @@
 			else if (pSuccessful->GetItemCount())
 				m_pQueue->SetSelection(2);
 		}
+	ActionAfter();
 	}
 
 	if (m_quit)
@@ -1869,6 +1887,16 @@
 		return;
 
 	pMenu->Check(XRCID("ID_PROCESSQUEUE"), IsActive() ? true : false);
+	pMenu->Check(XRCID("ID_ACTIONAFTER_DISABLE"), IsActionAfter(ActionAfterState_Disabled) ? true : false);
+	pMenu->Check(XRCID("ID_ACTIONAFTER_CLOSE"), IsActionAfter(ActionAfterState_Close) ? true : false);
+	pMenu->Check(XRCID("ID_ACTIONAFTER_DISCONNECT"), IsActionAfter(ActionAfterState_Disconnect) ? true : false);
+	pMenu->Check(XRCID("ID_ACTIONAFTER_RUNCOMMAND"), IsActionAfter(ActionAfterState_RunCommand) ? true : false);
+	pMenu->Check(XRCID("ID_ACTIONAFTER_SHOWMESSAGE"), IsActionAfter(ActionAfterState_ShowMessage) ? true : false);
+	pMenu->Check(XRCID("ID_ACTIONAFTER_PLAYSOUND"), IsActionAfter(ActionAfterState_PlaySound) ? true : false);
+#ifdef __WXMSW__
+	pMenu->Check(XRCID("ID_ACTIONAFTER_REBOOT"), IsActionAfter(ActionAfterState_Reboot) ? true : false);
+	pMenu->Check(XRCID("ID_ACTIONAFTER_SHUTDOWN"), IsActionAfter(ActionAfterState_Shutdown) ? true : false);
+#endif
 	pMenu->Enable(XRCID("ID_REMOVE"), GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
 
 	const bool hasSelection = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1;
@@ -1890,6 +1918,114 @@
 	RemoveAll();
 }
 
+void CQueueView::OnActionAfterDisable(wxCommandEvent& event)
+{
+	m_actionAfterState = ActionAfterState_Disabled;
+}
+
+void CQueueView::OnActionAfterClose(wxCommandEvent& event)
+{
+	if(event.IsChecked())
+	{ // goes from non-checked to checked
+		m_actionAfterState = ActionAfterState_Close;
+	} 
+	else
+	{ // goes from checked to non-checked
+		m_actionAfterState = ActionAfterState_Disabled;
+	}
+}
+
+void CQueueView::OnActionAfterDisconnect(wxCommandEvent& event)
+{
+	if(event.IsChecked())
+	{ // goes from non-checked to checked
+		m_actionAfterState = ActionAfterState_Disconnect;
+	} 
+	else
+	{ // goes from checked to non-checked
+		m_actionAfterState = ActionAfterState_Disabled;
+	}
+}
+
+void CQueueView::OnActionAfterRunCommand(wxCommandEvent& event)
+{
+	if(event.IsChecked())
+	{ // goes from non-checked to checked
+		m_actionAfterState = ActionAfterState_RunCommand;
+		wxTextEntryDialog dlg(m_pMainFrame, _("Please enter a path and executable to run.\nE.g. c:\\somePath\\file.exe under MS Windows or /somePath/file under Unix.\nYou can also optionally specify program arguments."), _("Enter command"));
+		
+		if (dlg.ShowModal() != wxID_OK)
+		{
+			m_actionAfterState = ActionAfterState_Disabled;
+			return;
+		}
+		const wxString &command = dlg.GetValue();
+		
+		if (command == _T(""))
+		{
+			wxMessageBox(_("No command given, aborting."), _("Empty command"), wxICON_ERROR, m_pMainFrame);
+			m_actionAfterState = ActionAfterState_Disabled;
+			return;
+		}
+		m_actionAfterRunCommand = command;
+	} 
+	else
+	{ // goes from checked to non-checked
+		m_actionAfterState = ActionAfterState_Disabled;
+		m_actionAfterRunCommand = _T("");
+	}
+}
+
+void CQueueView::OnActionAfterShowMessage(wxCommandEvent& event)
+{
+	if(event.IsChecked())
+	{ // goes from non-checked to checked
+		m_actionAfterState = ActionAfterState_ShowMessage;
+	} 
+	else
+	{ // goes from checked to non-checked
+		m_actionAfterState = ActionAfterState_Disabled;
+	}
+}
+
+void CQueueView::OnActionAfterPlaySound(wxCommandEvent& event)
+{
+	if(event.IsChecked())
+	{ // goes from non-checked to checked
+		m_actionAfterState = ActionAfterState_PlaySound;
+	} 
+	else
+	{ // goes from checked to non-checked
+		m_actionAfterState = ActionAfterState_Disabled;
+	}
+}
+
+#ifdef __WXMSW__
+void CQueueView::OnActionAfterReboot(wxCommandEvent& event)
+{
+	if(event.IsChecked()) // goes from non-checked to checked
+	{ 
+		m_actionAfterState = ActionAfterState_Reboot;
+	} 
+	else // goes from checked to non-checked
+	{ 
+		m_actionAfterState = ActionAfterState_Disabled;
+	}
+}
+
+void CQueueView::OnActionAfterShutdown(wxCommandEvent& event)
+{
+	if(event.IsChecked()) // goes from non-checked to checked
+	{
+		m_actionAfterState = ActionAfterState_Shutdown;
+	} 
+	else // goes from checked to non-checked
+	{
+		m_actionAfterState = ActionAfterState_Disabled;
+	}
+}
+#endif
+
 void CQueueView::RemoveAll()
 {
 	// This function removes all inactive items and queues active items
@@ -1913,6 +2049,7 @@
 		}
 	}
 	SetItemCount(m_itemCount);
+	m_actionAfterState = ActionAfterState_Disabled;
 
 	m_serverList = newServerList;
 	UpdateStatusLinePositions();
@@ -2487,3 +2624,117 @@
 
 	SendNextCommand(*pEngineData);
 }
+
+enum ActionAfterState CQueueView::GetActionAfterState() const
+{
+	return m_actionAfterState;
+}
+
+bool CQueueView::IsActionAfter(enum ActionAfterState state)
+{
+	return m_actionAfterState == state;
+}
+
+void CQueueView::ActionAfter(bool warned /*=false*/)
+{
+	switch(m_actionAfterState)
+	{
+		case ActionAfterState_Close:
+		{
+			//m_pMainFrame->Close();
+			wxSound(_T("resources/finished.wav")).Play(wxSOUND_ASYNC);
+			break;
+		}
+		case ActionAfterState_Disconnect:
+		{
+			if (m_pMainFrame->GetState()->IsRemoteConnected() && m_pMainFrame->GetState()->IsRemoteIdle()) 
+				m_pMainFrame->GetState()->m_pCommandQueue->ProcessCommand(new CDisconnectCommand());
+			m_actionAfterState = ActionAfterState_Disabled; // Resetting the state.
+			break;
+		}
+		case ActionAfterState_RunCommand:
+		{
+			wxExecute(m_actionAfterRunCommand);
+			m_actionAfterState = ActionAfterState_Disabled; // Resetting the state.
+			break;
+		}
+		case ActionAfterState_ShowMessage:
+		{
+			wxMessageDialog* dialog = new wxMessageDialog(m_pMainFrame, _T("No more files in the queue!"), _T("Queue completion"), wxOK | wxICON_INFORMATION);
+			dialog->ShowModal();
+			m_pMainFrame->RequestUserAttention(wxUSER_ATTENTION_ERROR);
+			
+			m_actionAfterState = ActionAfterState_Disabled; // Resetting the state.
+			break;
+		}
+		case ActionAfterState_PlaySound:
+		{
+			wxSound(wxGetApp().GetResourceDir() + _T("finished.wav")).Play(wxSOUND_ASYNC);
+			m_actionAfterState = ActionAfterState_Disabled; // Resetting the state.
+			break;
+		}
+#ifdef __WXMSW__
+		case ActionAfterState_Reboot:
+		{
+			if(!warned)
+				ActionAfterWarnUser(_T("The system will soon reboot unless you press cancel."));
+			else
+				wxShutdown(wxSHUTDOWN_REBOOT);
+			break;
+		}
+
+		case ActionAfterState_Shutdown:
+		{
+			if(!warned)
+				ActionAfterWarnUser(_T("The system will soon shutdown unless you press cancel."));
+			else
+				wxShutdown(wxSHUTDOWN_POWEROFF);
+			break;
+		}
+#endif
+		case ActionAfterState_Disabled:
+		{
+			m_actionAfterState = ActionAfterState_Disabled; // Resetting the state.
+			break;
+		}
+	}
+}
+
+void CQueueView::ActionAfterWarnUser(wxString message)
+{
+	m_actionAfterWarnDialog = new wxProgressDialog(_T("Queue completion dialog"), message, 150, m_pMainFrame, wxPD_CAN_ABORT | wxPD_AUTO_HIDE | wxPD_CAN_SKIP);
+	wxSize dialogSize = m_actionAfterWarnDialog->GetSize();
+	m_actionAfterWarnDialog->SetSize(dialogSize.GetWidth() / 2, dialogSize.GetHeight());
+	m_actionAfterWarnDialog->CentreOnParent();
+	m_actionAfterWarnDialog->SetFocus();
+	m_pMainFrame->RequestUserAttention(wxUSER_ATTENTION_ERROR);
+	
+	m_actionAfterTimer = new wxTimer(this,fzEVT_ACTIONAFTER_WARN);
+	m_actionAfterTimerCount = 0;
+	m_actionAfterTimer->Start(100, wxTIMER_CONTINUOUS);
+}
+
+void CQueueView::OnActionAfterTimerTick(wxTimerEvent& event)
+{
+	bool skipped = false;
+	if(m_actionAfterTimerCount > 150)
+	{
+		m_actionAfterWarnDialog->Destroy();
+		delete m_actionAfterTimer;
+		this->ActionAfter(true);
+	}
+	else if(!m_actionAfterWarnDialog->Update(m_actionAfterTimerCount++, _T(""), &skipped))
+	{
+		// User has pressed cancel!
+		m_actionAfterState = ActionAfterState_Disabled; // resetting to disabled
+		m_actionAfterWarnDialog->Destroy();
+		delete m_actionAfterTimer;
+	}
+	else if(skipped)
+	{
+		m_actionAfterWarnDialog->Destroy();
+		delete m_actionAfterTimer;
+		this->ActionAfter(true);
+	}
+		
+}

 	  	 
