Beispiel #1
0
        private async Task <bool> ParseFiles(FileInfo inputFile)
        {
            try {
                IEnumerable <FileInfo> subLanguageFiles = FilesystemHelper.FindSubLanguages(inputFile);

                IList <ILocalizationKey> keys = await JsonHelper.ParseLanguage(inputFile);

                MainLanguage = new Language(inputFile, keys);

                SubLanguages = new ObservableCollection <ILanguage>();
                foreach (FileInfo subLanguageFile in subLanguageFiles)
                {
                    keys = await JsonHelper.ParseLanguage(subLanguageFile);

                    ILanguage language = new Language(subLanguageFile, keys);
                    SubLanguages.Add(language);
                }

                if (SubLanguages.Any())
                {
                    SelectedSubLanguage = SubLanguages.First();
                }

                Configuration config   = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                string        oldValue = config.AppSettings.Settings["LastFileUsed"].Value;
                config.AppSettings.Settings["LastFileUsed"].Value = MainLanguage.Path;
                config.Save(ConfigurationSaveMode.Modified);
                HasChanges = false;

                return(true);
            } catch (Exception ex) {
                StatusMessage = ex.Message;
                return(false);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Ask for a filename and then save the metadata to this filename.
        /// </summary>
        public void UserSaveAs(Metadata metadata, string videoFile)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();

            saveFileDialog.Title = ScreenManagerLang.dlgSaveAnalysisTitle;

            // Go to this video directory and suggest sidecar filename.
            saveFileDialog.InitialDirectory = Path.GetDirectoryName(videoFile);
            saveFileDialog.FileName         = Path.GetFileNameWithoutExtension(videoFile);
            saveFileDialog.Filter           = FilesystemHelper.SaveKVAFilter();
            saveFileDialog.FilterIndex      = 1;

            if (saveFileDialog.ShowDialog() != DialogResult.OK || string.IsNullOrEmpty(saveFileDialog.FileName))
            {
                return;
            }

            string filename = saveFileDialog.FileName;

            if (!filename.ToLower().EndsWith(".kva") && !filename.ToLower().EndsWith(".xml"))
            {
                filename += ".kva";
            }

            SaveToFile(metadata, filename);
            metadata.LastKVAPath = filename;
            metadata.AfterManualExport();
        }
Beispiel #3
0
        /// <summary>
        /// Main video export.
        /// </summary>
        public void SaveVideo(double playbackFrameInterval, double slowmotionPercentage, ImageRetriever imageRetriever)
        {
            // Show the intermediate dialog for export options.
            formVideoExport fve = new formVideoExport(videoReader.FilePath, slowmotionPercentage);

            if (fve.ShowDialog() != DialogResult.OK)
            {
                fve.Dispose();
                return;
            }

            if (!FilesystemHelper.CanWrite(fve.Filename))
            {
                DisplayErrorMessage(ScreenManagerLang.Error_SaveMovie_FileError);
                fve.Dispose();
                return;
            }

            DoSave(fve.Filename,
                   fve.UseSlowMotion ? playbackFrameInterval : metadata.UserInterval,
                   true,
                   false,
                   false,
                   imageRetriever);

            // Save this as the "preferred" format for video exports.
            PreferencesManager.PlayerPreferences.VideoFormat = FilesystemHelper.GetVideoFormat(fve.Filename);
            PreferencesManager.Save();

            fve.Dispose();
        }
Beispiel #4
0
        private void btnCaptureKVA_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog           = new OpenFileDialog();
            string         initialDirectory = "";

            if (!string.IsNullOrEmpty(captureKVA) && File.Exists(captureKVA) && Path.IsPathRooted(captureKVA))
            {
                initialDirectory = Path.GetDirectoryName(captureKVA);
            }

            if (!string.IsNullOrEmpty(initialDirectory))
            {
                dialog.InitialDirectory = initialDirectory;
            }
            else
            {
                dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            }

            dialog.Title            = ScreenManagerLang.dlgLoadAnalysis_Title;
            dialog.RestoreDirectory = true;
            dialog.Filter           = FilesystemHelper.OpenKVAFilter(ScreenManagerLang.FileFilter_AllSupported);
            dialog.FilterIndex      = 1;

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                tbCaptureKVA.Text = dialog.FileName;
            }
        }
Beispiel #5
0
        public void HandleRarFileCaseMultiParComplete()
        {
            var allParts     = Enumerable.Range(1, 5).Select(n => string.Format("music.part{0}.rar", n)).ToList();
            var partToHandle = allParts.Random();
            var part         = "";

            foreach (var existingPart in allParts)
            {
                part = Path.Combine(settings.MediaLibraryPath, "Others", "music", existingPart);
                FilesystemHelper.SafeCopy(TestHelper.GetRessourceFullPath(existingPart), part);
            }

            // Create and copy new .part.rar file to be handled
            part = Path.Combine(settings.DownloadsPath, "_5678", partToHandle);
            FilesystemHelper.SafeCopy(TestHelper.GetRessourceFullPath(partToHandle), part);

            var service = new ArchiveExtractorService(loggerMock.Object, optionsMock.Object);

            Assert.True(service.HandleRarFile(part, out var destDir));

            // assert .part0n.rar files are deleted
            Assert.AreEqual(1, Directory.GetFiles(destDir, "*", SearchOption.AllDirectories).Length);

            // assert music.mp3 has been extracted and is the right length
            var file = new  FileInfo(Path.Combine(settings.MediaLibraryPath, "Others", "music", "music.mp3"));

            Assert.IsTrue(file.Exists, "File should be extracted");
            Assert.AreEqual(4487785, file.Length);
        }
        private void ImportAgisoft()
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();

            openFileDialog.Title            = ScreenManagerLang.dlgCameraCalibration_OpenDialogTitle;
            openFileDialog.Filter           = FilesystemHelper.OpenXMLFilter();
            openFileDialog.FilterIndex      = 1;
            openFileDialog.InitialDirectory = Software.CameraCalibrationDirectory;

            if (openFileDialog.ShowDialog() != DialogResult.OK || string.IsNullOrEmpty(openFileDialog.FileName))
            {
                return;
            }

            DistortionParameters dp = DistortionImporterAgisoft.Import(openFileDialog.FileName, calibrationHelper.ImageSize);

            if (dp != null)
            {
                distortionParameters = dp;
                distorter.Initialize(distortionParameters, calibrationHelper.ImageSize);

                AfterImport();
                PopulatePhysicalParameters();
                PopulateValues();
                UpdateDistortionGrid();
            }
        }
Beispiel #7
0
        private void btnExportData_Click(object sender, EventArgs e)
        {
            if (plotView.Model == null)
            {
                return;
            }

            SaveFileDialog saveFileDialog = new SaveFileDialog();

            saveFileDialog.Title            = ScreenManagerLang.DataAnalysis_ExportData;
            saveFileDialog.Filter           = FilesystemHelper.SaveCSVFilter();
            saveFileDialog.FilterIndex      = 1;
            saveFileDialog.RestoreDirectory = true;

            if (saveFileDialog.ShowDialog() != DialogResult.OK || string.IsNullOrEmpty(saveFileDialog.FileName))
            {
                return;
            }

            List <string> lines = GetCSV();

            using (StreamWriter w = File.CreateText(saveFileDialog.FileName))
            {
                foreach (string line in lines)
                {
                    w.WriteLine(line);
                }
            }
        }
Beispiel #8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="srcPath"></param>
        /// <param name="destPath"></param>
        /// <returns></returns>
        public List <FileInfo> MoveMatchingSubtitlesOf(string srcPath, string destPath)
        {
            var subtitles = new List <FileInfo>();

            var srcBasePath  = Path.Combine(Path.GetDirectoryName(srcPath), Path.GetFileNameWithoutExtension(srcPath));
            var destBasePath = Path.Combine(Path.GetDirectoryName(destPath), Path.GetFileNameWithoutExtension(destPath));

            //reverse logic to iterate over folder
            MatchingSubtitlesExtensions.ForEach(subExt =>
            {
                var subPath = srcBasePath + subExt;
                if (File.Exists(subPath))
                {
                    var srtDestPath         = destBasePath + subExt;
                    var srtDestPath2Letters = FilesystemHelper.ConvertToTwoLetterIsoLanguageNameSubtitle(srtDestPath);
                    if (srtDestPath2Letters != null)
                    {
                        srtDestPath = srtDestPath2Letters;
                    }
                    FilesystemHelper.MoveOrReplace(subPath, srtDestPath);
                    subtitles.Add(new FileInfo(srtDestPath));
                }
            });

            return(subtitles);
        }
Beispiel #9
0
        private void btnExportData_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();

            saveFileDialog.Title            = ScreenManagerLang.DataAnalysis_ExportData;
            saveFileDialog.Filter           = FilesystemHelper.SaveCSVFilter();
            saveFileDialog.FilterIndex      = 1;
            saveFileDialog.RestoreDirectory = true;

            if (saveFileDialog.ShowDialog() != DialogResult.OK || string.IsNullOrEmpty(saveFileDialog.FileName))
            {
                return;
            }

            string separator = CultureInfo.CurrentCulture.TextInfo.ListSeparator;

            using (StreamWriter w = File.CreateText(saveFileDialog.FileName))
            {
                string unit = UnitHelper.LengthAbbreviation(metadata.CalibrationHelper.LengthUnit);
                w.WriteLine(string.Format("t (ms){0}x ({1}){0}y ({1})", separator, unit));

                foreach (TimedPoint point in points)
                {
                    string time = metadata.TimeCodeBuilder(point.T, TimeType.UserOrigin, TimecodeFormat.Milliseconds, false);
                    PointF p    = metadata.CalibrationHelper.GetPointAtTime(point.Point, point.T);
                    w.WriteLine(string.Format("{0}{3}{1}{3}{2}", time, p.X, p.Y, separator));
                }
            }
        }
Beispiel #10
0
        private void btnOK_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();

            saveFileDialog.Title            = ScreenManagerLang.dlgSaveSequenceTitle;
            saveFileDialog.RestoreDirectory = true;
            saveFileDialog.Filter           = FilesystemHelper.SaveImageFilter();
            saveFileDialog.FilterIndex      = 1;
            saveFileDialog.FileName         = Path.GetFileNameWithoutExtension(fullPath);

            Hide();

            if (saveFileDialog.ShowDialog() != DialogResult.OK)
            {
                Show();
                return;
            }

            if (string.IsNullOrEmpty(saveFileDialog.FileName))
            {
                Close();
                return;
            }

            int              frames   = (int)Math.Round((float)totalFrames / decimationFrames);
            long             interval = info.AverageTimeStampsPerFrame * decimationFrames;
            FormFramesExport ffe      = new FormFramesExport(playerScreenUserInterface, saveFileDialog.FileName, interval, chkKeyframesOnly.Checked, frames);

            ffe.ShowDialog();
            ffe.Dispose();

            Close();
        }
Beispiel #11
0
        private void watcher_Changed(object sender, FileSystemEventArgs e)
        {
            if (!VideoTypeManager.IsSupported(Path.GetExtension(e.FullPath)))
            {
                return;
            }

            if (e.FullPath == currentFile)
            {
                // In this case we can't use the normal heuristic of trying to get exclusive access on the file,
                // because the player screen itself already has the file opened.

                // First of all we need to stop the player from playing the file as it's reading frames from disk (no caching).
                dummy.BeginInvoke((Action) delegate { player.StopPlaying(); });

                // We normally receive only two events. One at start and one on close.
                overwriteEventCount++;
                if (overwriteEventCount >= 2)
                {
                    overwriteEventCount = 0;
                    dummy.BeginInvoke((Action) delegate { LoadVideo(e.FullPath); });
                }
            }
            else
            {
                if (FilesystemHelper.CanRead(e.FullPath))
                {
                    dummy.BeginInvoke((Action) delegate { LoadVideo(e.FullPath); });
                }
            }
        }
Beispiel #12
0
        public FileInfo MoveUnknownFile(string path)
        {
            var destPath = Path.Combine(settings.MediaLibraryPath,
                                        "Others", Path.GetFileName(path));

            FilesystemHelper.MoveOrReplace(path, destPath);
            return(new FileInfo(destPath));
        }
Beispiel #13
0
        // nicetohave: interface music item with spotify API
        public FileInfo MoveMusicFile(string path)
        {
            var destMusicPath = Path.Combine(settings.MediaLibraryPath, "Music", Path.GetFileName(path));

            FilesystemHelper.MoveOrReplace(path, destMusicPath);
            logger.LogInformation("ProcessMusicItem from: " + path + " to: " + destMusicPath);
            return(new FileInfo(destMusicPath));
        }
Beispiel #14
0
 public void Delete()
 {
     FilesystemHelper.DeleteFile(m_FileName);
     if (!File.Exists(m_FileName))
     {
         NotificationCenter.RaiseRefreshFileExplorer(this, true);
     }
 }
Beispiel #15
0
        private void LocateSelectedVideo(ListView lv)
        {
            string path = GetSelectedVideoPath(lv);

            if (path != null)
            {
                FilesystemHelper.LocateFile(path);
            }
        }
Beispiel #16
0
        private static async Task <ChangedObject> SaveEventFile(IEnumerable <EventEntry> events)
        {
            var filename  = events.First().Filename;
            var eventFile = FilesystemHelper.GenerateFileInfo(EVENT_DIRECTORY, filename);
            var content   = JsonHelper.ConvertToJson(events);

            var result = await FilesystemHelper.WriteAllTextAsyncOnlyWhenChanged(eventFile, content);

            return(new ChangedObject(filename, result.ChangeState));
        }
Beispiel #17
0
        private static async Task SaveAllEventsCsv(IEnumerable <EventEntry> events)
        {
            const string datetimeformat = "d MMM yyyy HH:mm";
            var          file           = FilesystemHelper.GenerateFileInfo(EVENT_DIRECTORY, "all", ".csv");
            var          lines          = events.Select(o => string.Join(';', new string[] { o.Name, o.Location, o.StartDateTime.ToString(datetimeformat), o.EndDateTime.ToString(datetimeformat), o.Description })).ToArray();
            var          headline       = string.Join(';', new string[] { "Name", "Location", "StartTime", "EndTime", "Description" });
            var          content        = headline + '\n' + string.Join('\n', lines);

            await File.WriteAllTextAsync(file.FullName, content);
        }
Beispiel #18
0
        private void view_LocateAsked(object sender, EventArgs e)
        {
            CapturedFileView view = sender as CapturedFileView;

            if (view == null || view.CapturedFile == null || string.IsNullOrEmpty(view.CapturedFile.Filepath))
            {
                return;
            }

            FilesystemHelper.LocateFile(view.CapturedFile.Filepath);
        }
Beispiel #19
0
        private void mnuLocateFolder_Click(object sender, EventArgs e)
        {
            CShItem item = activeTab == ActiveFileBrowserTab.Explorer ? currentExptreeItem : currentShortcutItem;

            if (item == null || string.IsNullOrEmpty(item.Path) || item.Path.StartsWith("::"))
            {
                return;
            }

            FilesystemHelper.LocateDirectory(item.Path);
        }
 private void TargetDirectory_Click(object sender, EventArgs e)
 {
     if (_folder.LastFilename != null)
     {
         FilesystemHelper.OpenPathInExplorer(Path.Combine(_folder.Path, _folder.LastFilename));
         CloseParentForm();
     }
     else
     {
         AnyControl_Click(sender, e);
     }
 }
Beispiel #21
0
        private static async Task <ChangedObject> GenerateCalendar(string name, FileInfo file, string[] eventnames, IEnumerable <Change> changes, string removedEvents)
        {
            var allEvents = await LoadEventsByName(eventnames);

            var events = ApplyChanges(allEvents, changes, removedEvents);

            var icsContent = IcsGenerator.GenerateIcsContent(name, events);

            var result = await FilesystemHelper.WriteAllTextAsyncOnlyWhenChanged(file, icsContent);

            return(new ChangedObject(name, result.ChangeState));
        }
Beispiel #22
0
        private static FileInfo GetCalendarFileOfUser(Userconfig config)
        {
            var filename = config.chat.id.ToString();

            if (!string.IsNullOrWhiteSpace(config.config.calendarfileSuffix))
            {
                filename += "-" + config.config.calendarfileSuffix;
            }
            var file = FilesystemHelper.GenerateFileInfo(CALENDAR_DIRECTORY, filename, ".ics");

            return(file);
        }
Beispiel #23
0
        private static async Task Main()
        {
            var lastGeneration = DateTime.Now;

            Log("Generate all Userconfigs...");
            await GenerateAllUserconfigs();

            Log("All generated");

            Log("Start main loop...");
            while (true)
            {
                try
                {
                    var preScan = DateTime.Now;
                    var changedUserconfigFiles = FilesystemHelper.GetFilesChangedAfterDate(USERCONFIG_DIRECTORY, lastGeneration, "*.json");
                    var changedUserconfigIds   = changedUserconfigFiles.Select(o => o.Name.Replace(".json", "")).Select(o => Convert.ToInt32(o));
                    var changedEventFiles      = FilesystemHelper.GetFilesChangedAfterDate(EVENT_DIRECTORY, lastGeneration, "*.json");

                    if (changedUserconfigFiles.Any())
                    {
                        Log(changedUserconfigFiles.ToArrayString("Userconfig Files changed"));
                    }

                    if (changedEventFiles.Any())
                    {
                        Log(changedEventFiles.ToArrayString("Event Files changed"));
                    }

                    if (changedUserconfigFiles.Any() || changedEventFiles.Any())
                    {
                        var allUserconfigs = await GetAllUserconfigs();

                        var directChangedUserconfigs   = allUserconfigs.Where(o => changedUserconfigIds.Contains(o.chat.id));
                        var indirectChangedUserconfigs = changedEventFiles.SelectMany(o => GetUserconfigsThatNeedEventFile(allUserconfigs, o));

                        var allChangedUserconfigs = directChangedUserconfigs.Concat(indirectChangedUserconfigs).Distinct();
                        await GenerateSetOfUserconfigs(allChangedUserconfigs);

                        lastGeneration = preScan;
                    }

                    await DeleteNotAnymoreNeededCalendars();
                }
                catch (Exception ex)
                {
                    Log(ex.ToString());
                }

                System.Threading.Thread.Sleep(1000 * 5); // 5 Seconds
            }
        }
        private void FswProfileFilesOnChanged(object sender, FileSystemEventArgs fileSystemEventArgs)
        {
            if (fileSystemEventArgs.ChangeType != WatcherChangeTypes.Deleted)
            {
                // file might still be written to, just wait until it's handles are closed
                while (FilesystemHelper.IsFileLocked(new FileInfo(fileSystemEventArgs.FullPath)))
                {
                    Thread.Sleep(100);
                }
            }

            LoadProfiles();
        }
Beispiel #25
0
        public List <FileSystemInfo> MoveVideoFile(string videoSrcPath)
        {
            var filesystemItems = new List <FileSystemInfo>();

            string videoDestPath;
            var    renameResult = filebot.Rename(new RenameRequest {
                Path = videoSrcPath, BaseDestPath = settings.MediaLibraryPath
            });

            if (!renameResult.Succeeded)
            {
                //fallback strategy to move video file based on duration
                logger.LogInformation("[MoveVideoFile] TryRename failed, executing fallback logic");
                mediaInfo.TryGetDuration(videoSrcPath, out var duration);
                var minutesDuration = duration.TotalMinutes;
                var fallbackDir     = "Others";
                if (minutesDuration > 0 && minutesDuration < 105)
                {
                    fallbackDir = "TV Shows";
                }
                else if (minutesDuration >= 105)
                {
                    fallbackDir = "Movies";
                }
                logger.LogInformation($"[MoveVideoFile] TryRename fallback destDir is [{fallbackDir}]");
                videoDestPath = Path.Combine(settings.MediaLibraryPath, fallbackDir, Path.GetFileName(videoSrcPath));
            }
            else
            {
                videoDestPath = renameResult.DestPath;
                logger.LogInformation("[MoveVideoFile] TryRename Succeeded videoDestPath: " + renameResult.DestPath);
            }

            //create dest dir if it does not exists and move item
            var destDirInfo = new DirectoryInfo(Path.GetDirectoryName(videoDestPath));

            //track created directories
            for (var tempDirInfo = destDirInfo; !tempDirInfo.Exists; tempDirInfo = tempDirInfo.Parent)
            {
                filesystemItems.Add(tempDirInfo);
            }

            if (!destDirInfo.Exists)
            {
                destDirInfo.Create();
            }
            filesystemItems.Add(new FileInfo(videoDestPath));
            FilesystemHelper.MoveOrReplace(videoSrcPath, videoDestPath, logger);
            return(filesystemItems);
        }
        /// <inheritdoc />
        /// <summary>
        /// Tries to start a P2P Download
        /// If the file is a magnet, it'll be converted into a torrent using aria2c CLI
        /// If the file is a torrent url, it'll download the torrent file locally
        /// Parses and assert the torrent validity before adding the torrent using transmission-remote CLI
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public void Start(DownloadItem item)
        {
            item.Type  = DownloadType.P2P;
            item.Token = "_" + DownloadType.P2P.ToString().ToLower() + Guid.NewGuid().ToString("N");

            var itemFolder = Path.Combine(settings.DownloadsPath, item.Token);

            Directory.CreateDirectory(itemFolder);


            var     torrentPath = "";
            Torrent torrent;

            try
            {
                //Download torrent file
                (item.FileUrl.StartsWith("magnet:?")
                        ? DownloadMagnetLink
                        : (Action <string, string>)DownloadTorrentFile)
                    (item.FileUrl, itemFolder);

                //Rename torrent file
                var tPath = new DirectoryInfo(itemFolder).EnumerateFiles("*.torrent").FirstOrDefault()?.FullName;
                torrentPath = itemFolder + ".torrent";
                FilesystemHelper.MoveOrReplace(tPath, torrentPath);

                //Parse torrent info
                torrent = ParseTorrent(torrentPath);

                //Add to torrent daemon service
                if (!torrentDaemonService.AddTorrent(torrentPath, itemFolder))
                {
                    throw new StartDownloadException(TorrentDaemonAddFailureMessage);
                }
            }
            catch (System.Exception)
            {
                FilesystemHelper.SafeDelete(itemFolder);
                throw;
            }
            finally
            {
                FilesystemHelper.SafeDelete(torrentPath);
            }

            item.Name      = torrent.DisplayName;
            item.Hash      = torrent.OriginalInfoHash.ToLower();
            item.TotalSize = torrent.TotalSize;
        }
        private void DeleteSelectedVideo(ListView lv)
        {
            string path = GetSelectedVideoPath(lv);

            if (path == null)
            {
                return;
            }

            FilesystemHelper.DeleteFile(path);
            if (!File.Exists(path))
            {
                DoRefreshFileList(true);
            }
        }
        private void Save()
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();

            saveFileDialog.Title            = ScreenManagerLang.dlgCameraCalibration_SaveDialogTitle;
            saveFileDialog.Filter           = FilesystemHelper.SaveXMLFilter();
            saveFileDialog.FilterIndex      = 1;
            saveFileDialog.InitialDirectory = Software.CameraCalibrationDirectory;

            if (saveFileDialog.ShowDialog() != DialogResult.OK || string.IsNullOrEmpty(saveFileDialog.FileName))
            {
                return;
            }

            DistortionImporterKinovea.Export(saveFileDialog.FileName, distorter.Parameters, calibrationHelper.ImageSize);
        }
        public void ConvertToTwoLetterIsoLanguageNameSubtitleTest(string subExt, string expectedResultEndsWith)
        {
            var srtFilename = "the.big.bang.theory.s10.e01";
            var srtBasePath = Path.Combine(Path.GetTempPath(), TestHelper.Uid(), srtFilename);

            var res = FilesystemHelper.ConvertToTwoLetterIsoLanguageNameSubtitle(srtBasePath + subExt);

            if (expectedResultEndsWith == null)
            {
                Assert.IsNull(res);
            }
            else
            {
                Assert.AreEqual(srtBasePath + expectedResultEndsWith, res);
            }
        }
Beispiel #30
0
        private void MnuWorkspaceExport_Click(object sender, EventArgs e)
        {
            // Extract the current workspace and save it in a separate file.
            Workspace workspace = screenManager.ExtractWorkspace();

            SaveFileDialog saveFileDialog = new SaveFileDialog();

            saveFileDialog.RestoreDirectory = true;
            saveFileDialog.Filter           = FilesystemHelper.SaveWorkspaceFilter();
            saveFileDialog.FilterIndex      = 1;
            if (saveFileDialog.ShowDialog() != DialogResult.OK || string.IsNullOrEmpty(saveFileDialog.FileName))
            {
                return;
            }

            workspace.Write(saveFileDialog.FileName);
        }