OSDN Git Service

CLI: update the built in presets
[handbrake-jp/handbrake-jp-git.git] / win / C# / frmQueue.cs
index 37c6462..2684772 100644 (file)
 /*  frmQueue.cs $\r
-       \r
-          This file is part of the HandBrake source code.\r
-          Homepage: <http://handbrake.fr>.\r
-          It may be used under the terms of the GNU General Public License. */\r
-\r
-using System;\r
-using System.Collections.Generic;\r
-using System.ComponentModel;\r
-using System.Data;\r
-using System.Drawing;\r
-using System.Text;\r
-using System.Windows.Forms;\r
-using System.Threading;\r
-using System.Diagnostics;\r
-using System.Runtime.InteropServices;\r
-using System.IO;\r
+    This file is part of the HandBrake source code.\r
+    Homepage: <http://handbrake.fr>.\r
+    It may be used under the terms of the GNU General Public License. */\r
 \r
 namespace Handbrake\r
 {\r
+    using System;\r
+    using System.Collections.Generic;\r
+    using System.Collections.ObjectModel;\r
+    using System.ComponentModel;\r
+    using System.IO;\r
+    using System.Windows.Forms;\r
+    using Functions;\r
+\r
+    using HandBrake.ApplicationServices.Model;\r
+    using HandBrake.ApplicationServices.Services;\r
+    using HandBrake.ApplicationServices.Services.Interfaces;\r
+\r
+    using Model;\r
+\r
+    /// <summary>\r
+    /// The Queue Window\r
+    /// </summary>\r
     public partial class frmQueue : Form\r
     {\r
-        private delegate void ProgressUpdateHandler();\r
-        private delegate void setEncoding();\r
-        Functions.CLI cliObj = new Functions.CLI();\r
-        Boolean cancel = false;\r
-        Process hbProc = null;\r
-\r
-        public frmQueue()\r
+        /// <summary>\r
+        /// Update Handler Delegate\r
+        /// </summary>\r
+        private delegate void UpdateHandler();\r
+\r
+        /// <summary>\r
+        /// An instance of the Queue service\r
+        /// </summary>\r
+        private readonly IQueue queue;\r
+\r
+        /// <summary>\r
+        /// A reference to the main application window\r
+        /// </summary>\r
+        private readonly frmMain mainWindow;\r
+\r
+        /// <summary>\r
+        /// Initializes a new instance of the <see cref="frmQueue"/> class.\r
+        /// </summary>\r
+        /// <param name="q">\r
+        /// An instance of the queue service.\r
+        /// </param>\r
+        /// <param name="mw">\r
+        /// The main window.\r
+        /// </param>\r
+        public frmQueue(IQueue q, frmMain mw)\r
         {\r
-            InitializeComponent();  \r
-        }\r
+            InitializeComponent();\r
+\r
+            this.mainWindow = mw;\r
+\r
+            this.queue = q;\r
+            queue.EncodeStarted += new EventHandler(QueueOnEncodeStart);\r
+            queue.QueueCompleted += new EventHandler(QueueOnQueueFinished);\r
+            queue.QueuePauseRequested += new EventHandler(QueueOnPaused);\r
+            queue.QueueListChanged += new EventHandler(queue_QueueListChanged);\r
 \r
+            queue.EncodeStarted += new EventHandler(queue_EncodeStarted);\r
+            queue.EncodeEnded += new EventHandler(queue_EncodeEnded);\r
 \r
-        #region Queue / Handling\r
+            drp_completeOption.Text = Properties.Settings.Default.CompletionOption;\r
+        }\r
 \r
-        public Boolean isEncoding()\r
+        /// <summary>\r
+        /// Queue Changed\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
+        private void queue_QueueListChanged(object sender, EventArgs e)\r
         {\r
-            if (hbProc == null)\r
-                return false;\r
-            else\r
-                return true;\r
+            UpdateUiElementsOnQueueChange();\r
         }\r
 \r
-        private void btn_encode_Click(object sender, EventArgs e)\r
+        /// <summary>\r
+        /// Encode Ended\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
+        private void queue_EncodeEnded(object sender, EventArgs e)\r
         {\r
-            // Reset some values\r
+            queue.EncodeStatusChanged -= EncodeQueue_EncodeStatusChanged;\r
+            ResetEncodeText();\r
+        }\r
 \r
-            if (list_queue.Items.Count != 0)\r
-            {\r
-                lbl_status.Visible = false;\r
-                btn_encode.Enabled = false;\r
-            }\r
-            cancel = false;\r
+        /// <summary>\r
+        /// Queue Started\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
+        private void queue_EncodeStarted(object sender, EventArgs e)\r
+        {\r
+            this.SetCurrentEncodeInformation();\r
+            queue.EncodeStatusChanged += EncodeQueue_EncodeStatusChanged;        \r
+        }\r
 \r
-            // Start the encode\r
-            try\r
-            {\r
-                if (list_queue.Items.Count != 0)\r
-                {\r
-                    // Setup or reset some values\r
-                    btn_stop.Visible = true;\r
-                    progressBar.Value = 0;\r
-                    lbl_progressValue.Text = "0 %";\r
-                    progressBar.Step = 100 / list_queue.Items.Count;\r
-                    progressBar.Update();\r
-                    //ThreadPool.QueueUserWorkItem(startProc);\r
-                    // Testing a new way of launching a thread. Hopefully will fix a random freeze up of the main thread.\r
-                    Thread theQ = new Thread(startProc);\r
-                    theQ.Start();\r
-                }\r
-            }\r
-            catch (Exception exc)\r
+        /// <summary>\r
+        /// Display the Encode Status\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
+        private void EncodeQueue_EncodeStatusChanged(object sender, HandBrake.ApplicationServices.EncodeProgressEventArgs e)\r
+        {\r
+            if (this.InvokeRequired)\r
             {\r
-                MessageBox.Show(exc.ToString());\r
+                this.BeginInvoke(new Encode.EncodeProgessStatus(EncodeQueue_EncodeStatusChanged), new[] { sender, e });\r
+                return;\r
             }\r
+\r
+            lbl_encodeStatus.Text =\r
+                string.Format(\r
+                "Encoding: Pass {0} of {1}, {2:00.00}% Time Remaining: {3}",\r
+                e.Task,\r
+                e.TaskCount,\r
+                e.PercentComplete,\r
+                e.EstimatedTimeLeft);\r
         }\r
 \r
-        private void btn_stop_Click(object sender, EventArgs e)\r
+        /// <summary>\r
+        /// Handle the Queue Paused event\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The EventArgs.\r
+        /// </param>\r
+        private void QueueOnPaused(object sender, EventArgs e)\r
         {\r
-            cancel = true;\r
-            btn_stop.Visible = false;\r
-            btn_encode.Enabled = true;\r
-            MessageBox.Show("No further items on the queue will start. The current encode process will continue until it is finished. \nClick 'Encode Video' when you wish to continue encoding the queue.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);\r
+            SetUiEncodeFinished();\r
+            UpdateUiElementsOnQueueChange();\r
         }\r
 \r
-        private void startProc(object state)\r
+        /// <summary>\r
+        /// Handle the Queue Finished event.\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The EventArgs.\r
+        /// </param>\r
+        private void QueueOnQueueFinished(object sender, EventArgs e)\r
         {\r
-            try\r
-            {\r
+            SetUiEncodeFinished();\r
+            ResetQueue(); // Reset the Queue Window\r
+        }\r
 \r
-                while (list_queue.Items.Count != 0)\r
-                {\r
-                    string query = list_queue.Items[0].ToString();\r
-                    setEncValue();\r
-                    updateUIElements();\r
+        /// <summary>\r
+        /// Handle the Encode Started event\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
+        private void QueueOnEncodeStart(object sender, EventArgs e)\r
+        {\r
+            SetUiEncodeStarted(); // make sure the UI is set correctly\r
+            UpdateUiElementsOnQueueChange(); // Redraw the Queue, a new encode has started.\r
+        }\r
 \r
+        /// <summary>\r
+        /// Initializes the Queue list with the Arraylist from the Queue class\r
+        /// </summary>\r
+        public void SetQueue()\r
+        {\r
+            UpdateUiElementsOnQueueChange();\r
+        }\r
 \r
-                    hbProc = cliObj.runCli(this, query);\r
+        /// <summary>\r
+        /// Initializes the Queue list, then shows and activates the window\r
+        /// </summary>\r
+        public new void Show()\r
+        {\r
+            Show(true);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Initializes the Queue list only if doSetQueue is true, then shows and activates the window\r
+        /// </summary>\r
+        /// <param name="doSetQueue">Indicates whether to call setQueue() before showing the window</param>\r
+        public void Show(bool doSetQueue)\r
+        {\r
+            if (doSetQueue) SetQueue();\r
+            base.Show();\r
+        }\r
 \r
-                    hbProc.WaitForExit();\r
-                    hbProc.Close();\r
-                    hbProc.Dispose();\r
-                    hbProc = null;\r
+        /// <summary>\r
+        /// Handle the Encode button Click event\r
+        /// </summary>\r
+        /// <param name="sender">The sender</param>\r
+        /// <param name="e">the EventArgs</param>\r
+        private void BtnEncodeClick(object sender, EventArgs e)\r
+        {\r
+            if (queue.Paused)\r
+            {\r
+                SetUiEncodeStarted();\r
+            }\r
 \r
-                    query = "";\r
+            lbl_encodeStatus.Text = "Encoding ...";\r
+            queue.Start();\r
+        }\r
 \r
-                    if (cancel == true)\r
-                    {\r
-                        break;\r
-                    }              \r
-                }\r
+        /// <summary>\r
+        /// Handle the Pause button click event.\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The EventArgs.\r
+        /// </param>\r
+        private void BtnPauseClick(object sender, EventArgs e)\r
+        {\r
+            queue.Pause();\r
+            MessageBox.Show(\r
+                "No further items on the queue will start. The current encode process will continue until it is finished. \nClick 'Encode' when you wish to continue encoding the queue.",\r
+                "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);\r
+        }\r
 \r
-                resetQueue();\r
+        // UI Work\r
 \r
-               \r
-                // After the encode is done, we may want to shutdown, suspend etc.\r
-                cliObj.afterEncodeAction();\r
-            }\r
-            catch (Exception exc)\r
+        /// <summary>\r
+        /// Setup the UI to show that an encode has started\r
+        /// </summary>\r
+        private void SetUiEncodeStarted()\r
+        {\r
+            if (InvokeRequired)\r
             {\r
-                MessageBox.Show(exc.ToString());\r
+                BeginInvoke(new UpdateHandler(SetUiEncodeStarted));\r
+                return;\r
             }\r
+            btn_encode.Enabled = false;\r
+            btn_pause.Visible = true;\r
         }\r
 \r
-        private void updateUIElements()\r
+        /// <summary>\r
+        /// Setup the UI to indicate that an encode has finished.\r
+        /// </summary>\r
+        private void SetUiEncodeFinished()\r
         {\r
-            try\r
+            if (InvokeRequired)\r
             {\r
-                if (this.InvokeRequired)\r
-                {\r
-                    this.BeginInvoke(new ProgressUpdateHandler(updateUIElements));\r
-                    return;\r
-                }\r
-                this.list_queue.Items.RemoveAt(0);\r
+                BeginInvoke(new UpdateHandler(SetUiEncodeFinished));\r
+                return;\r
+            }\r
+            btn_pause.Visible = false;\r
+            btn_encode.Enabled = true;\r
+        }\r
 \r
-                progressBar.PerformStep();\r
-                lbl_progressValue.Text = string.Format("{0} %", progressBar.Value);\r
-                progressBar.Update();\r
+        /// <summary>\r
+        /// Reset the Queue Window display\r
+        /// </summary>\r
+        private void ResetQueue()\r
+        {\r
+            if (InvokeRequired)\r
+            {\r
+                BeginInvoke(new UpdateHandler(ResetQueue));\r
+                return;\r
             }\r
-            catch (Exception exc)\r
+            btn_pause.Visible = false;\r
+            btn_encode.Enabled = true;\r
+\r
+            ResetEncodeText();\r
+        }\r
+\r
+        /// <summary>\r
+        /// Reset the current job text\r
+        /// </summary>\r
+        private void ResetEncodeText()\r
+        {\r
+            if (InvokeRequired)\r
             {\r
-                MessageBox.Show(exc.ToString());\r
+                BeginInvoke(new UpdateHandler(ResetEncodeText));\r
+                return;\r
             }\r
+            lbl_encodeStatus.Text = "Ready";\r
+\r
+            lbl_source.Text = "-";\r
+            lbl_dest.Text = "-";\r
+            lbl_encodeOptions.Text = "-";\r
+\r
+            lbl_encodesPending.Text = list_queue.Items.Count + " encode(s) pending";\r
         }\r
 \r
-        private void resetQueue()\r
+        /// <summary>\r
+        /// Redraw the Queue window with the latest information about HandBrakes status\r
+        /// </summary>\r
+        private void RedrawQueue()\r
         {\r
-            try\r
+            if (InvokeRequired)\r
             {\r
-                if (this.InvokeRequired)\r
-                {\r
-                    this.BeginInvoke(new ProgressUpdateHandler(resetQueue));\r
-                    return;\r
+                BeginInvoke(new UpdateHandler(RedrawQueue));\r
+                return;\r
+            }\r
 \r
-                }\r
-                btn_stop.Visible = false;\r
-                btn_encode.Enabled = true;\r
+            list_queue.Items.Clear();\r
+            ReadOnlyCollection<Job> theQueue = queue.CurrentQueue;\r
+            foreach (Job queueItem in theQueue)\r
+            {\r
+                string qItem = queueItem.Query;\r
+                QueryParser parsed = Functions.QueryParser.Parse(qItem);\r
+\r
+                // Get the DVD Title\r
+                string title = parsed.Title == 0 ? "Auto" : parsed.Title.ToString();\r
 \r
-                if (cancel == true)\r
+                // Get the DVD Chapters\r
+                string chapters;\r
+                if (parsed.ChapterStart == 0)\r
+                    chapters = "Auto";\r
+                else\r
                 {\r
-                    lbl_status.Visible = true;\r
-                    lbl_status.Text = "Encode Queue Cancelled!";\r
-                    text_edit.Text = "";\r
+                    chapters = parsed.ChapterStart.ToString();\r
+                    if (parsed.ChapterFinish != 0)\r
+                        chapters = chapters + " - " + parsed.ChapterFinish;\r
                 }\r
-                else\r
+\r
+                ListViewItem item = new ListViewItem();\r
+                item.Text = title; // Title\r
+                item.SubItems.Add(chapters); // Chapters\r
+                item.SubItems.Add(queueItem.Source); // Source\r
+                item.SubItems.Add(queueItem.Destination); // Destination\r
+                item.SubItems.Add(parsed.VideoEncoder); // Video\r
+\r
+                // Display The Audio Track Information\r
+                string audio = string.Empty;\r
+                foreach (AudioTrack track in parsed.AudioInformation)\r
                 {\r
-                    lbl_status.Visible = true;\r
-                    lbl_status.Text = "Encode Queue Completed!";\r
-                    text_edit.Text = "";\r
+                    if (audio != string.Empty)\r
+                        audio += ", " + track.Encoder;\r
+                    else\r
+                        audio = track.Encoder;\r
                 }\r
-                \r
-                lbl_progressValue.Text = "0 %";\r
-                progressBar.Value = 0;\r
-                progressBar.Update();\r
-\r
-                lbl_source.Text = "-";\r
-                lbl_dest.Text = "-";\r
-                lbl_vEnc.Text = "-";\r
-                lbl_aEnc.Text = "-";\r
-                lbl_title.Text = "-";\r
-                lbl_chapt.Text = "-";\r
+                item.SubItems.Add(audio); // Audio\r
+\r
+                list_queue.Items.Add(item);\r
             }\r
-            catch (Exception exc)\r
+        }\r
+\r
+        /// <summary>\r
+        /// Update the UI elements\r
+        /// </summary>\r
+        private void UpdateUiElementsOnQueueChange()\r
+        {\r
+            if (InvokeRequired)\r
             {\r
-                MessageBox.Show(exc.ToString());\r
+                BeginInvoke(new UpdateHandler(UpdateUiElementsOnQueueChange));\r
+                return;\r
             }\r
+\r
+            RedrawQueue();\r
+            lbl_encodesPending.Text = list_queue.Items.Count + " encode(s) pending";\r
         }\r
-        \r
-        private void setEncValue()\r
+\r
+        /// <summary>\r
+        /// Set the window up with the current encode information\r
+        /// </summary>\r
+        private void SetCurrentEncodeInformation()\r
         {\r
             try\r
             {\r
-                if (this.InvokeRequired)\r
+                if (InvokeRequired)\r
                 {\r
-                    this.BeginInvoke(new setEncoding(setEncValue));\r
+                    BeginInvoke(new UpdateHandler(SetCurrentEncodeInformation));\r
                 }\r
 \r
-                string query = query = list_queue.Items[0].ToString();\r
-\r
-                // found query is a global varible\r
-                Functions.QueryParser parsed = Functions.QueryParser.Parse(query);\r
-                lbl_source.Text = parsed.Source;\r
-                lbl_dest.Text = parsed.Destination;\r
-\r
+                QueryParser parsed = QueryParser.Parse(queue.LastEncode.Query);\r
 \r
-                if (parsed.DVDTitle == 0)\r
-                    lbl_title.Text = "Auto";\r
+                // Get title and chapters\r
+                string title = parsed.Title == 0 ? "Auto" : parsed.Title.ToString();\r
+                string chapterlbl;\r
+                if (Equals(parsed.ChapterStart, 0))\r
+                    chapterlbl = "Auto";\r
                 else\r
-                    lbl_title.Text = parsed.DVDTitle.ToString();\r
-\r
-                string chapters = "";\r
-                if (parsed.DVDChapterStart == 0)\r
                 {\r
-                    lbl_chapt.Text = "Auto";\r
+                    string chapters = parsed.ChapterStart.ToString();\r
+                    if (parsed.ChapterFinish != 0)\r
+                        chapters = chapters + " - " + parsed.ChapterFinish;\r
+                    chapterlbl = chapters;\r
                 }\r
-                else\r
+\r
+                // Get audio information\r
+                string audio = string.Empty;\r
+                foreach (AudioTrack track in parsed.AudioInformation)\r
                 {\r
-                    chapters = parsed.DVDChapterStart.ToString();\r
-                    if (parsed.DVDChapterFinish != 0)\r
-                        chapters = chapters + " - " + parsed.DVDChapterFinish;\r
-                    lbl_chapt.Text = chapters;\r
+                    if (audio != string.Empty) \r
+                        audio += ", " + track.Encoder;\r
+                    else\r
+                        audio = track.Encoder;\r
                 }\r
 \r
-                lbl_vEnc.Text = parsed.VideoEncoder;\r
-                lbl_aEnc.Text = parsed.AudioEncoder1;\r
-            }\r
+                // found query is a global varible        \r
+                lbl_encodeStatus.Text = "Encoding ...";\r
+                lbl_source.Text = queue.LastEncode.Source + "(Title: " + title + " Chapters: " + chapterlbl + ")";\r
+                lbl_dest.Text = queue.LastEncode.Destination;\r
+                lbl_encodeOptions.Text = "Video: " + parsed.VideoEncoder + " Audio: " + audio + Environment.NewLine +\r
+                                    "x264 Options: " + parsed.H264Query;\r
+               }\r
             catch (Exception)\r
             {\r
                 // Do Nothing\r
             }\r
         }\r
 \r
-        private void list_queue_SelectedIndexChanged(object sender, EventArgs e)\r
+        /* Right Click Menu */\r
+\r
+        /// <summary>\r
+        /// Handle the Move Up Menu Item\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
+        private void MnuUpClick(object sender, EventArgs e)\r
         {\r
-            if (list_queue.SelectedItem != null)\r
-                text_edit.Text = list_queue.SelectedItem.ToString();\r
-\r
-            listCount = list_queue.Items.Count;\r
+            MoveUp();\r
         }\r
 \r
-        #endregion\r
-\r
-        #region Buttons\r
-\r
-        private void btn_up_Click(object sender, EventArgs e)\r
+        /// <summary>\r
+        /// Handle the Move down Menu Item\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
+        private void MnuDownClick(object sender, EventArgs e)\r
         {\r
-            int count = list_queue.Items.Count;\r
-            int itemToMove = list_queue.SelectedIndex;\r
-            int previousItemint = 0;\r
-            String previousItem = "";\r
+            MoveDown();\r
+        }\r
 \r
-            if (itemToMove > 0)\r
+        /// <summary>\r
+        /// Edit a job\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
+        private void MnuEditClick(object sender, EventArgs e)\r
+        {\r
+            if (list_queue.SelectedIndices != null && list_queue.SelectedIndices.Count != 0)\r
             {\r
-                previousItemint = itemToMove - 1;\r
-                previousItem = list_queue.Items[previousItemint].ToString();\r
-                list_queue.Items[previousItemint] = list_queue.Items[itemToMove];\r
-                list_queue.Items[itemToMove] = previousItem;\r
-                list_queue.SelectedIndex = list_queue.SelectedIndex - 1;\r
+                lock (queue)\r
+                {\r
+                    lock (list_queue)\r
+                    {\r
+                        int index = list_queue.SelectedIndices[0];\r
+                        mainWindow.RecievingJob(queue.GetJob(index));\r
+                        queue.Remove(index);\r
+                        RedrawQueue();\r
+                    }\r
+                }\r
             }\r
         }\r
 \r
-        private void btn_down_Click(object sender, EventArgs e)\r
+        /// <summary>\r
+        /// Handle the delete Menu Item\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
+        private void MnuDeleteClick(object sender, EventArgs e)\r
         {\r
-            int count = list_queue.Items.Count;\r
-            int itemToMove = list_queue.SelectedIndex;\r
-            int itemAfterInt = 0;\r
-            String itemAfter = "";\r
-\r
-            if (itemToMove < (count - 1))\r
-            {\r
-                itemAfterInt = itemToMove + 1;\r
-                itemAfter = list_queue.Items[itemAfterInt].ToString();\r
-                list_queue.Items[itemAfterInt] = list_queue.Items[itemToMove];\r
-                list_queue.Items[itemToMove] = itemAfter;\r
-                list_queue.SelectedIndex = list_queue.SelectedIndex + 1;\r
-            }\r
+            DeleteSelectedItems();\r
         }\r
 \r
-        private void btn_delete_Click(object sender, EventArgs e)\r
+        /* Keyboard Shortcuts */\r
+\r
+        /// <summary>\r
+        /// Handle the delete keyboard press\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
+        private void ListQueueDeleteKey(object sender, KeyEventArgs e)\r
         {\r
-            list_queue.Items.Remove(list_queue.SelectedItem);\r
+            if (e.KeyCode == Keys.Delete && e.Modifiers == Keys.None)\r
+                DeleteSelectedItems();\r
         }\r
 \r
-        private void btn_batch_Click(object sender, EventArgs e)\r
+        /* Queue Management */\r
+\r
+        /// <summary>\r
+        /// Move items up in the queue\r
+        /// </summary>\r
+        private void MoveUp()\r
         {\r
-            string queries = "";\r
-            for (int i = 0; i < list_queue.Items.Count; i++)\r
+            // If there are selected items and the first item is not selected\r
+            if (list_queue.SelectedIndices.Count > 0 && !list_queue.SelectedIndices.Contains(0))\r
             {\r
-                string query = list_queue.Items[i].ToString();\r
-                string fullQuery = '"' + Application.StartupPath.ToString() + "\\HandBrakeCLI.exe" + '"' + query;\r
+                // Copy the selected indices to preserve them during the movement\r
+                List<int> selectedIndices = new List<int>(list_queue.SelectedIndices.Count);\r
+                foreach (int selectedIndex in list_queue.SelectedIndices)\r
+                    selectedIndices.Add(selectedIndex);\r
+\r
+                // Move up each selected item\r
+                foreach (int selectedIndex in selectedIndices)\r
+                    queue.MoveUp(selectedIndex);\r
+\r
+                // Keep the selected item(s) selected, now moved up one index\r
+                foreach (int selectedIndex in selectedIndices)\r
+                    if (selectedIndex - 1 > -1) // Defensive programming: ensure index is good\r
+                        list_queue.Items[selectedIndex - 1].Selected = true;\r
+            }\r
 \r
-                if (queries == "")\r
-                    queries = queries + fullQuery;\r
-                else\r
-                    queries = queries + " && " + fullQuery;\r
+            list_queue.Select(); // Activate the control to show the selected items\r
+        }\r
+\r
+        /// <summary>\r
+        /// Move items down in the queue\r
+        /// </summary>\r
+        private void MoveDown()\r
+        {\r
+            // If there are selected items and the last item is not selected\r
+            if (list_queue.SelectedIndices.Count > 0 &&\r
+                !list_queue.SelectedIndices.Contains(list_queue.Items[list_queue.Items.Count - 1].Index))\r
+            {\r
+                // Copy the selected indices to preserve them during the movement\r
+                List<int> selectedIndices = new List<int>(list_queue.SelectedIndices.Count);\r
+                foreach (int selectedIndex in list_queue.SelectedIndices)\r
+                    selectedIndices.Add(selectedIndex);\r
+\r
+                // Reverse the indices to move the items down from last to first (preserves indices)\r
+                selectedIndices.Reverse();\r
+\r
+                // Move down each selected item\r
+                foreach (int selectedIndex in selectedIndices)\r
+                    queue.MoveDown(selectedIndex);\r
+\r
+                // Keep the selected item(s) selected, now moved down one index\r
+                foreach (int selectedIndex in selectedIndices)\r
+                    if (selectedIndex + 1 < list_queue.Items.Count) // Defensive programming: ensure index is good\r
+                        list_queue.Items[selectedIndex + 1].Selected = true;\r
             }\r
-            string strCmdLine = queries;\r
 \r
-            SaveFile.ShowDialog();\r
-            string filename = SaveFile.FileName;\r
+            list_queue.Select(); // Activate the control to show the selected items\r
+        }\r
 \r
-            if (filename != "")\r
+        /// <summary>\r
+        /// Delete the currently selected items on the queue\r
+        /// </summary>\r
+        private void DeleteSelectedItems()\r
+        {\r
+            // If there are selected items\r
+            if (list_queue.SelectedIndices.Count > 0)\r
             {\r
-                try\r
-                {\r
-                    // Create a StreamWriter and open the file\r
-                    StreamWriter line = new StreamWriter(filename);\r
+                // Save the selected indices to select them after the move\r
+                List<int> selectedIndices = new List<int>(list_queue.SelectedIndices.Count);\r
+                foreach (int selectedIndex in list_queue.SelectedIndices)\r
+                    selectedIndices.Add(selectedIndex);\r
 \r
-                    // Write the batch file query to the file\r
-                    line.WriteLine(strCmdLine);\r
+                int firstSelectedIndex = selectedIndices[0];\r
 \r
-                    // close the stream\r
-                    line.Close();\r
+                // Reverse the list to delete the items from last to first (preserves indices)\r
+                selectedIndices.Reverse();\r
 \r
-                    MessageBox.Show("Your batch script has been sucessfully saved.", "Status", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);\r
-                }\r
-                catch (Exception)\r
-                {\r
-                    MessageBox.Show("Unable to write to the file. Please make sure that the location has the correct permissions for file writing.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);\r
-                }\r
+                // Remove each selected item\r
+                foreach (int selectedIndex in selectedIndices)\r
+                    queue.Remove(selectedIndex);\r
 \r
+                // Select the item where the first deleted item was previously\r
+                if (firstSelectedIndex < list_queue.Items.Count)\r
+                    list_queue.Items[firstSelectedIndex].Selected = true;\r
             }\r
+\r
+            list_queue.Select(); // Activate the control to show the selected items\r
         }\r
 \r
-        int listCount = 0;\r
-        private void btn_updateQuery_Click(object sender, EventArgs e)\r
+        /* Queue Import / Export features */\r
+\r
+        /// <summary>\r
+        /// Create a batch script\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
+        private void MnuBatchClick(object sender, EventArgs e)\r
         {\r
-            if (text_edit.Text != "")\r
-            {\r
-                if (list_queue.Items.Count != listCount)\r
-                {\r
-                    MessageBox.Show("Unable to modify the selected item. The number of items on the list has changed.  \nPlease avoid modifying an item when a new encode is about to start!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);\r
-                }\r
-                else\r
-                {\r
-                    if (list_queue.SelectedItem != null)\r
-                        list_queue.Items[list_queue.SelectedIndex] = text_edit.Text;\r
+            SaveFile.FileName = string.Empty;\r
+            SaveFile.Filter = "Batch|.bat";\r
+            SaveFile.ShowDialog();\r
+            if (SaveFile.FileName != String.Empty)\r
+                queue.WriteBatchScriptToFile(SaveFile.FileName);\r
+        }\r
 \r
-                }\r
-            }\r
+        /// <summary>\r
+        /// Export Queue\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
+        private void MnuExportClick(object sender, EventArgs e)\r
+        {\r
+            SaveFile.FileName = string.Empty;\r
+            SaveFile.Filter = "HandBrake Queue|*.queue";\r
+            SaveFile.ShowDialog();\r
+            if (SaveFile.FileName != String.Empty)\r
+                queue.WriteQueueStateToFile(SaveFile.FileName);\r
         }\r
 \r
-        private void btn_Close_Click(object sender, EventArgs e)\r
+        /// <summary>\r
+        /// Import Queue\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
+        private void MnuImportClick(object sender, EventArgs e)\r
         {\r
-            this.Hide();\r
+            OpenFile.FileName = string.Empty;\r
+            OpenFile.ShowDialog();\r
+            if (OpenFile.FileName != String.Empty)\r
+                queue.LoadQueueFromFile(OpenFile.FileName);\r
         }\r
 \r
-        #endregion   \r
+        /// <summary>\r
+        /// Readd current job to queue\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
+        private void MnuReaddClick(object sender, EventArgs e)\r
+        {\r
+            if (queue.LastEncode != null && !queue.LastEncode.IsEmpty)\r
+            {\r
+                queue.Add(\r
+                    queue.LastEncode.Query, \r
+                    queue.LastEncode.Title, \r
+                    queue.LastEncode.Source,\r
+                    queue.LastEncode.Destination,\r
+                    queue.LastEncode.CustomQuery);\r
+            }\r
+        }\r
+\r
+        /* Overrides */\r
 \r
+        /// <summary>\r
+        /// Hide's the window when the user tries to "x" out of the window instead of closing it.\r
+        /// </summary>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
         protected override void OnClosing(CancelEventArgs e)\r
         {\r
             e.Cancel = true;\r
             this.Hide();\r
             base.OnClosing(e);\r
         }\r
-      \r
+\r
+        /// <summary>\r
+        /// Change the OnComplete option setting.\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The EventArgs.\r
+        /// </param>\r
+        private void CompleteOptionChanged(object sender, EventArgs e)\r
+        {\r
+            Properties.Settings.Default.CompletionOption = drp_completeOption.Text;\r
+            HandBrake.ApplicationServices.Init.CompletionOption = drp_completeOption.Text;\r
+            Properties.Settings.Default.Save();\r
+        }\r
     }\r
 }
\ No newline at end of file