OSDN Git Service

WinGui:
[handbrake-jp/handbrake-jp-git.git] / win / C# / frmQueue.cs
index 43f198a..8bb0e19 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.Collections;\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.Windows.Forms;\r
+    using Functions;\r
+    using Model;\r
+    using Services;\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.Encode cliObj = new Functions.Encode();\r
-        Boolean paused = false;\r
-        Process hbProc = null;\r
-        Queue.QueueHandler queue;\r
-        frmMain mainWindow = null;\r
-        Thread theQ;\r
-\r
-        public frmQueue(frmMain main)\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 Queue 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(Queue q, frmMain mw)\r
         {\r
             InitializeComponent();\r
-            mainWindow = main;\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
         }\r
 \r
         /// <summary>\r
-        /// Initializes the Queue list with the Arraylist from the Queue class\r
+        /// Handle the Queue Paused event\r
         /// </summary>\r
-        /// <param name="qw"></param>\r
-        public void setQueue(Queue.QueueHandler qw)\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
-            queue = qw;\r
-            redrawQueue();\r
-            lbl_encodesPending.Text = list_queue.Items.Count + " encode(s) pending";\r
+            SetUiEncodeFinished();\r
+            UpdateUiElements();\r
         }\r
 \r
         /// <summary>\r
-        /// Returns if there is currently an item being encoded by the queue\r
+        /// Handle the Queue Finished event.\r
         /// </summary>\r
-        /// <returns>Boolean true if encoding</returns>\r
-        public Boolean isEncoding()\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
-            if (hbProc == null)\r
-                return false;\r
-            else\r
-                return true;\r
+            SetUiEncodeFinished();\r
+            ResetQueue(); // Reset the Queue Window\r
         }\r
 \r
         /// <summary>\r
-        /// Allows frmMain to start an encode.\r
-        /// Should probably find a cleaner way of doing this.\r
+        /// Handle the Encode Started event\r
         /// </summary>\r
-        public void frmMain_encode()\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
-            btn_encode_Click(this, null);\r
+            SetUiEncodeStarted(); // make sure the UI is set correctly\r
+            SetCurrentEncodeInformation();\r
+            UpdateUiElements(); // Redraw the Queue, a new encode has started.\r
         }\r
 \r
-        // Start and Stop Controls\r
-        private void btn_encode_Click(object sender, EventArgs e)\r
+        /// <summary>\r
+        /// Initializes the Queue list with the Arraylist from the Queue class\r
+        /// </summary>\r
+        public void SetQueue()\r
         {\r
-            if (queue.count() != 0)\r
-            {\r
-                if (paused == true)\r
-                {\r
-                    paused = false;\r
-                    btn_encode.Enabled = false;\r
-                    btn_stop.Visible = true;\r
-                }\r
-                else\r
-                {\r
-                    paused = false;\r
-                    btn_encode.Enabled = false;\r
-                    mainWindow.setLastAction("encode");\r
-                    mainWindow.setEncodeStarted();\r
-\r
-                    // Start the encode\r
-                    try\r
-                    {\r
-                        // Setup or reset some values\r
-                        btn_encode.Enabled = false;\r
-                        btn_stop.Visible = true;\r
-\r
-                        theQ = new Thread(startProc);\r
-                        theQ.IsBackground = true;\r
-                        theQ.Start();\r
-                    }\r
-                    catch (Exception exc)\r
-                    {\r
-                        MessageBox.Show(exc.ToString());\r
-                    }\r
-                }\r
-            }\r
+            UpdateUiElements();\r
         }\r
-        private void btn_stop_Click(object sender, EventArgs e)\r
+\r
+        /// <summary>\r
+        /// Initializes the Queue list, then shows and activates the window\r
+        /// </summary>\r
+        public new void Show()\r
         {\r
-            paused = true;\r
-            btn_stop.Visible = false;\r
-            btn_encode.Enabled = true;\r
-            mainWindow.setEncodeFinished();\r
-            resetQueue();\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
+            Show(true);\r
         }\r
 \r
-        // Starts the encoding process\r
-        private void startProc(object state)\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
-            try\r
-            {\r
-                // Run through each item on the queue\r
-                while (queue.count() != 0)\r
-                {\r
-                    string query = queue.getNextItemForEncoding();\r
-                    queue.write2disk("hb_queue_recovery.xml"); // Update the queue recovery file\r
+            if (doSetQueue) SetQueue();\r
+            base.Show();\r
 \r
-                    setCurrentEncodeInformation();\r
-                    if (this.Created)\r
-                        updateUIElements();\r
+            // Activate();\r
+        }\r
 \r
-                    hbProc = cliObj.runCli(this, query);\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.PauseRequested)\r
+            {\r
+                SetUiEncodeStarted();\r
+                MessageBox.Show("Encoding restarted", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);\r
+            }\r
 \r
-                    hbProc.WaitForExit();\r
-                    cliObj.addCLIQueryToLog(query);\r
-                    cliObj.copyLog(query, queue.getLastQueryItem().Destination);\r
+            if (!queue.IsEncoding)\r
+                queue.Start();\r
+        }\r
 \r
-                    hbProc.Close();\r
-                    hbProc.Dispose();\r
-                    hbProc = null;\r
-                    query = "";\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
+            SetUiEncodeFinished();\r
+            ResetQueue();\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
-                    while (paused == true) // Need to find a better way of doing this.\r
-                    {\r
-                        Thread.Sleep(10000);\r
-                    }\r
-                }\r
+        // UI Work\r
 \r
-                resetQueue();\r
-                \r
-                // After the encode is done, we may want to shutdown, suspend etc.\r
-                cliObj.afterEncodeAction();\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
+                BeginInvoke(new UpdateHandler(SetUiEncodeStarted));\r
+                return;\r
             }\r
-            catch (Exception exc)\r
+            btn_encode.Enabled = false;\r
+            btn_pause.Visible = true;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Setup the UI to indicate that an encode has finished.\r
+        /// </summary>\r
+        private void SetUiEncodeFinished()\r
+        {\r
+            if (InvokeRequired)\r
             {\r
-                MessageBox.Show(exc.ToString());\r
+                BeginInvoke(new UpdateHandler(SetUiEncodeFinished));\r
+                return;\r
             }\r
+            btn_pause.Visible = false;\r
+            btn_encode.Enabled = true;\r
         }\r
 \r
-        // Window Display Management\r
-        private void resetQueue() \r
+        /// <summary>\r
+        /// Reset the Queue Window display\r
+        /// </summary>\r
+        private void ResetQueue()\r
         {\r
-            try\r
+            if (InvokeRequired)\r
             {\r
-                if (this.InvokeRequired)\r
-                {\r
-                    this.BeginInvoke(new ProgressUpdateHandler(resetQueue));\r
-                    return;\r
-                }\r
-                btn_stop.Visible = false;\r
-                btn_encode.Enabled = true;\r
+                BeginInvoke(new UpdateHandler(ResetQueue));\r
+                return;\r
+            }\r
+            btn_pause.Visible = false;\r
+            btn_encode.Enabled = true;\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
+            lbl_source.Text = "-";\r
+            lbl_dest.Text = "-";\r
+            lbl_vEnc.Text = "-";\r
+            lbl_aEnc.Text = "-";\r
+            lbl_title.Text = "-";\r
+            lbl_chapt.Text = "-";\r
 \r
-                lbl_encodesPending.Text = list_queue.Items.Count + " encode(s) pending";\r
+            lbl_encodesPending.Text = list_queue.Items.Count + " encode(s) pending";\r
+        }\r
 \r
-                mainWindow.setEncodeFinished(); // Tell the main window encodes have finished.\r
-            }\r
-            catch (Exception exc)\r
+        /// <summary>\r
+        /// Redraw the Queue window with the latest information about HandBrakes status\r
+        /// </summary>\r
+        private void RedrawQueue()\r
+        {\r
+            if (InvokeRequired)\r
             {\r
-                MessageBox.Show(exc.ToString());\r
+                BeginInvoke(new UpdateHandler(RedrawQueue));\r
+                return;\r
             }\r
-        }\r
-        private void redrawQueue()  \r
-        {\r
+\r
             list_queue.Items.Clear();\r
-            List<Queue.QueueItem> theQueue = queue.getQueue();\r
-            foreach (Queue.QueueItem queue_item in theQueue)\r
+            ReadOnlyCollection<Job> theQueue = queue.CurrentQueue;\r
+            foreach (Job queueItem in theQueue)\r
             {\r
-                string q_item = queue_item.Query;\r
-                Functions.QueryParser parsed = Functions.QueryParser.Parse(q_item);\r
+                string qItem = queueItem.Query;\r
+                QueryParser parsed = Functions.QueryParser.Parse(qItem);\r
 \r
                 // Get the DVD Title\r
-                string title = "";\r
-                if (parsed.DVDTitle == 0)\r
-                    title = "Auto";\r
-                else\r
-                    title = parsed.DVDTitle.ToString();\r
+                string title = parsed.DVDTitle == 0 ? "Auto" : parsed.DVDTitle.ToString();\r
 \r
                 // Get the DVD Chapters\r
-                string chapters = "";\r
+                string chapters;\r
                 if (parsed.DVDChapterStart == 0)\r
                     chapters = "Auto";\r
                 else\r
@@ -216,67 +253,81 @@ namespace Handbrake
                 ListViewItem item = new ListViewItem();\r
                 item.Text = title; // Title\r
                 item.SubItems.Add(chapters); // Chapters\r
-                item.SubItems.Add(queue_item.Source); // Source\r
-                item.SubItems.Add(queue_item.Destination); // Destination\r
+                item.SubItems.Add(queueItem.Source); // Source\r
+                item.SubItems.Add(queueItem.Destination); // Destination\r
                 item.SubItems.Add(parsed.VideoEncoder); // Video\r
-                item.SubItems.Add(parsed.AudioEncoder1); // Audio\r
 \r
-                list_queue.Items.Add(item);\r
-            }\r
-        }\r
-        private void updateUIElements() \r
-        {\r
-            try\r
-            {\r
-                if (this.InvokeRequired)\r
+                // Display The Audio Track Information\r
+                string audio = string.Empty;\r
+                foreach (AudioTrack track in parsed.AudioInformation)\r
                 {\r
-                    this.BeginInvoke(new ProgressUpdateHandler(updateUIElements));\r
-                    return;\r
+                    if (audio != string.Empty)\r
+                        audio += ", " + track.Encoder;\r
+                    else\r
+                        audio = track.Encoder;\r
                 }\r
+                item.SubItems.Add(audio); // Audio\r
 \r
-                redrawQueue();\r
-                lbl_encodesPending.Text = list_queue.Items.Count + " encode(s) pending";\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 UpdateUiElements()\r
+        {\r
+            if (InvokeRequired)\r
             {\r
-                MessageBox.Show(exc.ToString());\r
+                BeginInvoke(new UpdateHandler(UpdateUiElements));\r
+                return;\r
             }\r
+\r
+            RedrawQueue();\r
+            lbl_encodesPending.Text = list_queue.Items.Count + " encode(s) pending";\r
         }\r
-        private void setCurrentEncodeInformation() \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(setCurrentEncodeInformation));\r
+                    BeginInvoke(new UpdateHandler(SetCurrentEncodeInformation));\r
                 }\r
 \r
                 // found query is a global varible\r
-                Functions.QueryParser parsed = Functions.QueryParser.Parse(queue.getLastQueryItem().Query);\r
-                lbl_source.Text = queue.getLastQueryItem().Source;\r
-                lbl_dest.Text = queue.getLastQueryItem().Destination;\r
+                QueryParser parsed = Functions.QueryParser.Parse(queue.LastEncode.Query);\r
+                lbl_source.Text = queue.LastEncode.Source;\r
+                lbl_dest.Text = queue.LastEncode.Destination;\r
 \r
+                lbl_title.Text = parsed.DVDTitle == 0 ? "Auto" : parsed.DVDTitle.ToString();\r
 \r
-                if (parsed.DVDTitle == 0)\r
-                    lbl_title.Text = "Auto";\r
-                else\r
-                    lbl_title.Text = parsed.DVDTitle.ToString();\r
-\r
-                string chapters = "";\r
-                if (parsed.DVDChapterStart == 0)\r
-                {\r
+                if (Equals(parsed.DVDChapterStart, 0))\r
                     lbl_chapt.Text = "Auto";\r
-                }\r
                 else\r
                 {\r
-                    chapters = parsed.DVDChapterStart.ToString();\r
+                    string chapters = parsed.DVDChapterStart.ToString();\r
                     if (parsed.DVDChapterFinish != 0)\r
                         chapters = chapters + " - " + parsed.DVDChapterFinish;\r
                     lbl_chapt.Text = chapters;\r
                 }\r
 \r
                 lbl_vEnc.Text = parsed.VideoEncoder;\r
-                lbl_aEnc.Text = parsed.AudioEncoder1;\r
+\r
+                // Display The Audio Track Information\r
+                string audio = string.Empty;\r
+                foreach (AudioTrack track in parsed.AudioInformation)\r
+                {\r
+                    if (audio != string.Empty)\r
+                        audio += ", " + track.Encoder;\r
+                    else\r
+                        audio = track.Encoder;\r
+                }\r
+                lbl_aEnc.Text = audio;\r
             }\r
             catch (Exception)\r
             {\r
@@ -284,95 +335,310 @@ namespace Handbrake
             }\r
         }\r
 \r
-        // Queue Management\r
-        private void btn_up_Click(object sender, EventArgs e)\r
+        /// <summary>\r
+        /// Delete the currently selected items on the queue\r
+        /// </summary>\r
+        private void DeleteSelectedItems()\r
         {\r
-            if (list_queue.SelectedIndices.Count != 0)\r
+            // If there are selected items\r
+            if (list_queue.SelectedIndices.Count > 0)\r
             {\r
-                int selected = list_queue.SelectedIndices[0];\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
+                int firstSelectedIndex = selectedIndices[0];\r
 \r
-                queue.moveUp(selected);\r
-                queue.write2disk("hb_queue_recovery.xml"); // Update the queue recovery file\r
-                redrawQueue();\r
+                // Reverse the list to delete the items from last to first (preserves indices)\r
+                selectedIndices.Reverse();\r
 \r
-                if (selected - 1 > 0)\r
-                    list_queue.Items[selected - 1].Selected = true;\r
+                // Remove each selected item\r
+                foreach (int selectedIndex in selectedIndices)\r
+                    queue.Remove(selectedIndex);\r
 \r
-                list_queue.Select();\r
+                UpdateUiElements();\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
-        private void btn_down_Click(object sender, EventArgs e)\r
+\r
+        // Queue Management\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.SelectedIndices.Count != 0)\r
-            {\r
-                int selected = list_queue.SelectedIndices[0];\r
+            MoveUp();\r
+        }\r
 \r
-                queue.moveDown(list_queue.SelectedIndices[0]);\r
-                queue.write2disk("hb_queue_recovery.xml"); // Update the queue recovery file\r
-                redrawQueue();\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
+            MoveDown();\r
+        }\r
 \r
-                if (selected + 1 < list_queue.Items.Count)\r
-                    list_queue.Items[selected + 1].Selected = true;\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
+            DeleteSelectedItems();\r
+        }\r
 \r
-                list_queue.Select();\r
-            }\r
+        /// <summary>\r
+        /// Handle the Button Up Click\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
+        private void BtnUpClick(object sender, EventArgs e)\r
+        {\r
+            MoveUp();\r
+        }\r
+\r
+        /// <summary>\r
+        /// Handle the button down click\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
+        private void BtnDownClick(object sender, EventArgs e)\r
+        {\r
+            MoveDown();\r
+        }\r
+\r
+        /// <summary>\r
+        /// Handle the delete button click\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
+        private void BtnDeleteClick(object sender, EventArgs e)\r
+        {\r
+            DeleteSelectedItems();\r
         }\r
-        private void btn_delete_Click(object sender, EventArgs e)\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
-            if (list_queue.SelectedIndices.Count != 0)\r
+            if (e.KeyCode == Keys.Delete)\r
+                DeleteSelectedItems();\r
+        }\r
+\r
+        /// <summary>\r
+        /// Move items up in the queue\r
+        /// </summary>\r
+        private void MoveUp()\r
+        {\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
-                queue.remove(list_queue.SelectedIndices[0]);\r
-                queue.write2disk("hb_queue_recovery.xml"); // Update the queue recovery file\r
-                redrawQueue();\r
-                lbl_encodesPending.Text = list_queue.Items.Count + " encode(s) pending";\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
+                UpdateUiElements();\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
+            list_queue.Select(); // Activate the control to show the selected items\r
         }\r
-        private void list_queue_deleteKey(object sender, KeyEventArgs e)\r
+\r
+        /// <summary>\r
+        /// Move items down in the queue\r
+        /// </summary>\r
+        private void MoveDown()\r
         {\r
-            if (e.KeyCode == Keys.Delete)\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
-                if (list_queue.SelectedIndices.Count != 0)\r
-                {\r
-                    queue.remove(list_queue.SelectedIndices[0]);\r
-                    queue.write2disk("hb_queue_recovery.xml"); // Update the queue recovery file\r
-                    redrawQueue();\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
+                UpdateUiElements();\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
+\r
+            list_queue.Select(); // Activate the control to show the selected items\r
         }\r
 \r
         // Queue Import/Export Features\r
-        private void mnu_batch_Click(object sender, EventArgs e)\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
-            SaveFile.FileName = "";\r
+            SaveFile.FileName = string.Empty;\r
             SaveFile.Filter = "Batch|.bat";\r
             SaveFile.ShowDialog();\r
             if (SaveFile.FileName != String.Empty)\r
-                queue.writeBatchScript(SaveFile.FileName);\r
+                queue.WriteBatchScriptToFile(SaveFile.FileName);\r
         }\r
-        private void mnu_export_Click(object sender, EventArgs e)\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 = "";\r
+            SaveFile.FileName = string.Empty;\r
             SaveFile.Filter = "HandBrake Queue|*.queue";\r
             SaveFile.ShowDialog();\r
             if (SaveFile.FileName != String.Empty)\r
-                queue.write2disk(SaveFile.FileName);\r
+                queue.WriteQueueStateToFile(SaveFile.FileName);\r
         }\r
-        private void mnu_import_Click(object sender, EventArgs e)\r
+\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
-            OpenFile.FileName = "";\r
+            OpenFile.FileName = string.Empty;\r
             OpenFile.ShowDialog();\r
             if (OpenFile.FileName != String.Empty)\r
-                queue.recoverQueue(OpenFile.FileName);\r
-            redrawQueue();\r
+                queue.LoadQueueFromFile(OpenFile.FileName);\r
+            UpdateUiElements();\r
+        }\r
+\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.IsEmpty)\r
+            {\r
+                queue.Add(queue.LastEncode.Query, queue.LastEncode.Source, queue.LastEncode.Destination,\r
+                          queue.LastEncode.CustomQuery);\r
+                UpdateUiElements();\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Edit Job\r
+        /// </summary>\r
+        /// <param name="sender">\r
+        /// The sender.\r
+        /// </param>\r
+        /// <param name="e">\r
+        /// The e.\r
+        /// </param>\r
+        private void MnuReconfigureJobClick(object sender, EventArgs e)\r
+        {\r
+            if (list_queue.SelectedIndices != null)\r
+            {\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
-        // Hide's the window when the user tries to "x" out of the window instead of closing it.\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
 }
\ No newline at end of file