/* * Greenshot - a free and open source screenshot tool * Copyright (C) 2007-2010 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ using System; using System.Collections; using System.Drawing; using System.IO; using System.Reflection; using System.Text.RegularExpressions; using System.Windows.Forms; using Greenshot.Capturing; using Greenshot.Configuration; using Greenshot.Helpers; using Greenshot.Plugin; namespace Greenshot.Forms { /// /// Custom dialog for saving images, wraps SaveFileDialog. /// For some reason SFD is sealed :( /// public class SaveImageFileDialog { private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(SaveImageFileDialog)); protected SaveFileDialog saveFileDialog; private FilterOption[] filterOptions; private DirectoryInfo eagerlyCreatedDirectory; private ICaptureDetails captureDetails = null; public SaveImageFileDialog() { init(); } public SaveImageFileDialog(ICaptureDetails captureDetails) { this.captureDetails = captureDetails; init(); } private void init() { saveFileDialog = new SaveFileDialog(); applyFilterOptions(); saveFileDialog.InitialDirectory = Path.GetDirectoryName(AppConfig.GetInstance().Output_FileAs_Fullpath); // The following property fixes a problem that the directory where we save is locked (bug #2899790) saveFileDialog.RestoreDirectory = true; saveFileDialog.CheckPathExists = false; saveFileDialog.AddExtension = false; ApplySuggestedValues(); } private void applyFilterOptions() { prepareFilterOptions(); AppConfig conf = AppConfig.GetInstance(); string fdf = ""; int preselect = 0; for(int i=0; i /// filename exactly as typed in the filename field /// public string FileName { get {return saveFileDialog.FileName;} set {saveFileDialog.FileName = value;} } /// /// initial directory of the dialog /// public string InitialDirectory { get {return saveFileDialog.InitialDirectory;} set {saveFileDialog.InitialDirectory = value;} } /// /// returns filename as typed in the filename field with extension. /// if filename field value ends with selected extension, the value is just returned. /// otherwise, the selected extension is appended to the filename. /// public string FileNameWithExtension { get { string fn = saveFileDialog.FileName; // if the filename contains a valid extension, which is the same like the selected filter item's extension, the filename is okay if(fn.EndsWith(Extension,System.StringComparison.CurrentCultureIgnoreCase)) return fn; // otherwise we just add the selected filter item's extension else return fn + "." + Extension; } set { FileName = Path.GetFileNameWithoutExtension(value); Extension = Path.GetExtension(value); } } /// /// gets or sets selected extension /// public string Extension { get { return filterOptions[saveFileDialog.FilterIndex-1].Extension; } set { for(int i=0; i /// sets InitialDirectory and FileName property of a SaveFileDialog smartly, considering default pattern and last used path /// /// a SaveFileDialog instance private void ApplySuggestedValues() { AppConfig conf = AppConfig.GetInstance(); string rootDir = GetRootDirFromConfig(); // build the full path and set dialog properties string filenameFromPattern = FilenameHelper.GetFilenameWithoutExtensionFromPattern(conf.Output_File_FilenamePattern, captureDetails); string fullpath = Path.Combine(rootDir, filenameFromPattern); string dir = CreateDirectoryIfNotExists(fullpath); FileName = Path.GetFileNameWithoutExtension(fullpath); Extension = Path.GetExtension(fullpath); InitialDirectory = dir; /*string path = conf.Output_FileAs_Fullpath; if(path.Length == 0) { // first save -> apply default storage location and pattern saveFileDialog.InitialDirectory = conf.Output_File_Path; saveFileDialog.FileName = FilenameHelper.GetFilenameWithoutExtensionFromPattern(conf.Output_File_FilenamePattern); } else { // check whether last used path matches default pattern string patternStr = Path.Combine(conf.Output_File_Path, conf.Output_File_FilenamePattern); patternStr = patternStr.Replace(@"\",@"\\"); // escape backslashes for regex IDictionaryEnumerator en = FilenameHelper.Placeholders.GetEnumerator(); while(en.MoveNext()) { patternStr = patternStr.Replace(en.Key.ToString(),en.Value.ToString()); } Regex rg = new Regex(patternStr); Match m = rg.Match(path); // rootDir serves as root for pattern based saving String rootDir = (m.Success) ? path.Substring(0, m.Index) : Path.GetDirectoryName(path); String fileNameFromPattern = FilenameHelper.GetFilenameWithoutExtensionFromPattern(conf.Output_File_FilenamePattern); String appendDir = Path.GetDirectoryName(fileNameFromPattern); String fileName = Path.GetFileName(fileNameFromPattern); String recommendedDir = Path.Combine(rootDir, appendDir); // due to weird behavior of SaveFileDialog, we cannot use a path in the FileName property (causes InitialDirectory to be ignored) // thus we create the recommended dir eagerly, assign it to InitialDirectory, and clean up afterwards, if it has not been used DirectoryInfo di = new DirectoryInfo(recommendedDir); if(!di.Exists) { di = Directory.CreateDirectory(recommendedDir); eagerlyCreatedDirectory = di; } InitialDirectory = recommendedDir; FileName = fileName; Extension = Path.GetExtension(fileName); }*/ } private string GetRootDirFromConfig() { string rootDir = AppConfig.GetInstance().Output_File_Path; // the idea was to let the user choose whether to suggest the dir // configured in the settings dialog or just remember the latest path. // however, we'd need an extra option for this, making the settings dialog // less comprehensive -> perhaps later.... /*if(rootDir.Length == 0) { // <-- no, wouldn't work just like that // no default storage location, use latest path or desktop rootDir = conf.Output_FileAs_Fullpath; if(rootDir.Length == 0) { rootDir = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); } else { rootDir = Path.GetDirectoryName(rootDir); } } else { // storage location is configured rootDir = conf.Output_File_Path; }*/ return rootDir; } private class FilterOption { public string Label; public string Extension; } private void CleanUp() { if(eagerlyCreatedDirectory!=null && eagerlyCreatedDirectory.GetFiles().Length==0 && eagerlyCreatedDirectory.GetDirectories().Length==0) { eagerlyCreatedDirectory.Delete(); eagerlyCreatedDirectory = null; } } private string CreateDirectoryIfNotExists(string fullPath) { string dirName = null; try { dirName = Path.GetDirectoryName(fullPath); DirectoryInfo di = new DirectoryInfo(dirName); if(!di.Exists) { di = Directory.CreateDirectory(dirName); eagerlyCreatedDirectory = di; } } catch (Exception e) { LOG.Error("Error in CreateDirectoryIfNotExists",e); } return dirName; } } }