Refactoring for new patterns and added the other projects to the solution, so refactoring is always made over all files.

git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@895 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
This commit is contained in:
RKrom 2010-09-22 09:41:19 +00:00
commit 7066a5e6ee
7 changed files with 247 additions and 60 deletions

View file

@ -335,7 +335,8 @@ namespace Greenshot.Forms {
bool fileWritten = false;
if (captureDestinations.Contains(CaptureDestination.File)) {
string filename = FilenameHelper.GetFilenameFromPattern(conf.OutputFileFilenamePattern, conf.OutputFileFormat, captureDetails);
fullPath = Path.Combine(conf.OutputFilePath,filename);
string filepath = FilenameHelper.FillVariables(conf.OutputFilePath);
fullPath = Path.Combine(filepath,filename);
// Catching any exception to prevent that the user can't write in the directory.
// This is done for e.g. bugs #2974608, #2963943, #2816163, #2795317, #2789218, #3004642

View file

@ -607,10 +607,11 @@ namespace Greenshot {
/// </summary>
private void ContextMenuDoubleClick(object sender, EventArgs eventArgs) {
string path;
string configPath = FilenameHelper.FillVariables(conf.OutputFilePath);
if (lastImagePath != null && Directory.Exists(lastImagePath)) {
path = lastImagePath;
} else if (Directory.Exists(conf.OutputFilePath)) {
path = conf.OutputFilePath;
} else if (Directory.Exists(configPath)) {
path = configPath;
} else {
// What do I open when nothing can be found? Right, nothing...
return;

View file

@ -1,4 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 10.00

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
# SharpDevelop 3.2.0.5777
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotCore", "..\GreenshotCore\GreenshotCore.csproj", "{BDC408EE-DEA1-4474-B59D-7F05757B12EC}"
@ -17,6 +18,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Greenshot", "Greenshot.cspr
{0A07500E-7404-48D7-8789-7EB2A23E0DD5} = {0A07500E-7404-48D7-8789-7EB2A23E0DD5}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotJiraPlugin", "..\GreenshotJiraPlugin\GreenshotJiraPlugin.csproj", "{19FEEF09-313F-43C7-819D-F1BCA782B08B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotConfluencePlugin", "..\GreenshotConfluencePlugin\GreenshotConfluencePlugin.csproj", "{C3052651-598A-44E2-AAB3-2E41311D50F9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotFlickrPlugin", "..\GreenshotFlickrPlugin\GreenshotFlickrPlugin.csproj", "{56828D7F-F227-41EC-8873-CC32A23A1783}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Greenshot-RunAtOutput-Plugin", "..\Greenshot-RunAtOutput-Plugin\Greenshot-RunAtOutput-Plugin.csproj", "{47F23C86-604E-4CC3-8767-B3D4088F30BB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -43,6 +52,21 @@ Global
{0A07500E-7404-48D7-8789-7EB2A23E0DD5}.Debug|Any CPU.ActiveCfg = Debug|x86
{0A07500E-7404-48D7-8789-7EB2A23E0DD5}.Release|Any CPU.Build.0 = Release|x86
{0A07500E-7404-48D7-8789-7EB2A23E0DD5}.Release|Any CPU.ActiveCfg = Release|x86
{19FEEF09-313F-43C7-819D-F1BCA782B08B}.Debug|Any CPU.Build.0 = Debug|x86
{19FEEF09-313F-43C7-819D-F1BCA782B08B}.Debug|Any CPU.ActiveCfg = Debug|x86
{19FEEF09-313F-43C7-819D-F1BCA782B08B}.Release|Any CPU.Build.0 = Release|x86
{19FEEF09-313F-43C7-819D-F1BCA782B08B}.Release|Any CPU.ActiveCfg = Release|x86
{C3052651-598A-44E2-AAB3-2E41311D50F9}.Debug|Any CPU.Build.0 = Debug|x86
{C3052651-598A-44E2-AAB3-2E41311D50F9}.Debug|Any CPU.ActiveCfg = Debug|x86
{C3052651-598A-44E2-AAB3-2E41311D50F9}.Release|Any CPU.Build.0 = Release|x86
{C3052651-598A-44E2-AAB3-2E41311D50F9}.Release|Any CPU.ActiveCfg = Release|x86
{56828D7F-F227-41EC-8873-CC32A23A1783}.Debug|Any CPU.Build.0 = Debug|x86
{56828D7F-F227-41EC-8873-CC32A23A1783}.Debug|Any CPU.ActiveCfg = Debug|x86
{56828D7F-F227-41EC-8873-CC32A23A1783}.Release|Any CPU.Build.0 = Release|x86
{56828D7F-F227-41EC-8873-CC32A23A1783}.Release|Any CPU.ActiveCfg = Release|x86
{47F23C86-604E-4CC3-8767-B3D4088F30BB}.Debug|Any CPU.Build.0 = Debug|x86
{47F23C86-604E-4CC3-8767-B3D4088F30BB}.Debug|Any CPU.ActiveCfg = Debug|x86
{47F23C86-604E-4CC3-8767-B3D4088F30BB}.Release|Any CPU.Build.0 = Release|x86
{47F23C86-604E-4CC3-8767-B3D4088F30BB}.Release|Any CPU.ActiveCfg = Release|x86
EndGlobalSection
EndGlobal

View file

@ -26,8 +26,8 @@ Source: ..\additional_files\*; DestDir: {app}; Flags: overwritereadonly recurses
Source: ..\..\bin\Release\Plugins\Greenshot-OCR-Plugin\*; DestDir: {app}\Plugins\Greenshot-OCR-Plugin; Components: plugins\ocr; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
Source: ..\..\bin\Release\Languages\Plugins\Greenshot-OCR-Plugin\*; DestDir: {app}\Languages\Plugins\Greenshot-OCR-Plugin; Components: plugins\ocr; Flags: overwritereadonly ignoreversion replacesameversion;
;JIRA Plugin
;Source: ..\..\bin\Release\Plugins\GreenshotJiraPlugin\*; DestDir: {app}\Plugins\GreenshotJiraPlugin; Components: plugins\jira; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
;Source: ..\..\bin\Release\Languages\Plugins\GreenshotJiraPlugin\*; DestDir: {app}\Languages\Plugins\GreenshotJiraPlugin; Components: plugins\jira; Flags: overwritereadonly ignoreversion replacesameversion;
Source: ..\..\bin\Release\Plugins\GreenshotJiraPlugin\*; DestDir: {app}\Plugins\GreenshotJiraPlugin; Components: plugins\jira; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
Source: ..\..\bin\Release\Languages\Plugins\GreenshotJiraPlugin\*; DestDir: {app}\Languages\Plugins\GreenshotJiraPlugin; Components: plugins\jira; Flags: overwritereadonly ignoreversion replacesameversion;
;Title-Fix Plugin
Source: ..\..\bin\Release\Plugins\Greenshot-TitleFix-Plugin\*; DestDir: {app}\Plugins\Greenshot-TitleFix-Plugin; Components: plugins\titlefix; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
@ -107,7 +107,7 @@ nl.ocr=OCR Plugin (heeft Microsoft Office 2003 of 2007 nodig)
[Components]
Name: "plugins"; Description: "Plugins"; Types: Full
Name: "plugins\ocr"; Description: {cm:ocr}; Types: Full; Check: CheckMODI
;Name: "plugins\jira"; Description: "JIRA Plugin"; Types: Full
Name: "plugins\jira"; Description: "JIRA Plugin"; Types: Full
Name: "plugins\titlefix"; Description: {cm:titlefix}; Types: Full
;Name: "plugins\flickr"; Description: "Flickr Plugin"; Types: Full
[Code]

View file

@ -204,6 +204,7 @@ namespace Greenshot.Forms {
private string GetRootDirFromConfig() {
string rootDir =conf.OutputFilePath;
rootDir = FilenameHelper.FillVariables(rootDir);
// 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

View file

@ -158,7 +158,7 @@ namespace Greenshot {
// Check the settings and somehow visibly mark when something is incorrect
private bool CheckSettings() {
bool settingsOk = true;
if(!Directory.Exists(textbox_storagelocation.Text)) {
if(!Directory.Exists(FilenameHelper.FillVariables(textbox_storagelocation.Text))) {
textbox_storagelocation.BackColor = Color.Red;
settingsOk = false;
} else {
@ -259,6 +259,7 @@ namespace Greenshot {
IniConfig.Save();
try {
// Check if the Run for all is set
if(!StartupHelper.checkRunAll()) {
// If not set the registry according to the settings
@ -271,6 +272,9 @@ namespace Greenshot {
// The run key for Greenshot is set for all users, delete the local version!
StartupHelper.deleteRunUser();
}
} catch (Exception e) {
LOG.Warn("Problem checking registry, ignoring for now: ", e);
}
}
void Settings_cancelClick(object sender, System.EventArgs e) {
@ -278,15 +282,23 @@ namespace Greenshot {
}
void Settings_okayClick(object sender, System.EventArgs e) {
if (CheckSettings()) {
SaveSettings();
this.Close();
} else {
this.tabcontrol.SelectTab(this.tab_output);
}
}
void BrowseClick(object sender, System.EventArgs e) {
this.folderBrowserDialog1.SelectedPath = this.textbox_storagelocation.Text;
// Get the storage location and replace the environment variables
this.folderBrowserDialog1.SelectedPath = FilenameHelper.FillVariables(this.textbox_storagelocation.Text);
if(this.folderBrowserDialog1.ShowDialog() == DialogResult.OK) {
// Only change if there is a change, otherwise we might overwrite the environment variables
if (this.folderBrowserDialog1.SelectedPath != null && !this.folderBrowserDialog1.SelectedPath.Equals(FilenameHelper.FillVariables(this.textbox_storagelocation.Text))) {
this.textbox_storagelocation.Text = this.folderBrowserDialog1.SelectedPath;
}
}
CheckSettings();
}

View file

@ -21,6 +21,7 @@
using System;
using System.Collections;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Greenshot.Capturing;
@ -30,6 +31,8 @@ using Greenshot.Plugin;
namespace Greenshot.Helpers {
public class FilenameHelper {
private static readonly Regex VAR_REGEXP = new Regex(@"\${(?<variable>[^:}]+)[:]?(?<parameters>[^}]*)}", RegexOptions.Compiled);
private static readonly Regex SPLIT_REGEXP = new Regex(";(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", RegexOptions.Compiled);
private const int MAX_TITLE_LENGTH = 80;
private static CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
@ -93,16 +96,83 @@ namespace Greenshot.Helpers {
return FillPattern(pattern, captureDetails) + "." + imageFormat;
}
private static string FillPattern(string initialPattern, ICaptureDetails captureDetails) {
string pattern = string.Copy(initialPattern);
// Default use "now" for the capture taken
DateTime captureTaken = DateTime.Now;
/// <summary>
/// This method will be called by the regexp.replace as a MatchEvaluator delegate!
/// </summary>
/// <param name="match">What are we matching?</param>
/// <param name="captureDetails">The detail, can be null</param>
/// <returns></returns>
private static string MatchVarEvaluator(Match match, ICaptureDetails captureDetails, IDictionary processVars, IDictionary userVars, IDictionary machineVars) {
// some defaults
int padWidth = 0;
int startIndex = 0;
int endIndex = 0;
char padChar = ' ';
string dateFormat = "yyyy-MM-dd HH-mm-ss";
string replaceValue = "";
string variable = match.Groups["variable"].Value;
string parameters = match.Groups["parameters"].Value;
if (parameters != null && parameters.Length > 0) {
string []parms = SPLIT_REGEXP.Split(parameters);
foreach(string parameter in parms) {
switch (parameter.Substring(0,1)) {
case "p":
string []padParams = parameter.Substring(1).Split(new char[] {','});
try {
padWidth = int.Parse(padParams[0]);
} catch {};
if (padParams.Length > 1) {
padChar = padParams[1][0];
}
break;
case "d":
dateFormat = parameter.Substring(1);
if (dateFormat.StartsWith("\"")) {
dateFormat = dateFormat.Substring(1);
}
if (dateFormat.EndsWith("\"")) {
dateFormat = dateFormat.Substring(0, dateFormat.Length-1);
}
break;
case "s":
string range=parameter.Substring(1);
string []rangelist = range.Split(new char[] {','});
if (rangelist.Length > 0) {
try {
startIndex = int.Parse(rangelist[0]);
} catch {
// Ignore
}
}
if (rangelist.Length > 1) {
try {
endIndex = int.Parse(rangelist[1]);
} catch {
// Ignore
}
}
break;
}
}
}
if (processVars != null && processVars.Contains(variable)) {
replaceValue = (string)processVars[variable];
} else if (userVars != null && userVars.Contains(variable)) {
replaceValue = (string)userVars[variable];
} else if (machineVars != null && machineVars.Contains(variable)) {
replaceValue = (string)machineVars[variable];
} else {
// Handle other variables
// Default use "now" for the capture take´n
DateTime capturetime = DateTime.Now;
// Use default application name for title
string title = Application.ProductName;
// Check if we have capture details
if (captureDetails != null) {
captureTaken = captureDetails.DateTime;
capturetime = captureDetails.DateTime;
if (captureDetails.Title != null) {
title = captureDetails.Title;
if (title.Length > MAX_TITLE_LENGTH) {
@ -110,38 +180,116 @@ namespace Greenshot.Helpers {
}
}
}
pattern = pattern.Replace("%YYYY%",captureTaken.Year.ToString());
pattern = pattern.Replace("%MM%", zeroPad(captureTaken.Month.ToString(), 2));
pattern = pattern.Replace("%DD%", zeroPad(captureTaken.Day.ToString(), 2));
pattern = pattern.Replace("%hh%", zeroPad(captureTaken.Hour.ToString(), 2));
pattern = pattern.Replace("%mm%", zeroPad(captureTaken.Minute.ToString(), 2));
pattern = pattern.Replace("%ss%", zeroPad(captureTaken.Second.ToString(), 2));
pattern = pattern.Replace("%domain%", Environment.UserDomainName);
pattern = pattern.Replace("%user%", Environment.UserName);
pattern = pattern.Replace("%hostname%", Environment.MachineName);
if(pattern.Contains("%NUM%")) {
uint num = conf.OutputFileIncrementingNumber++;
switch(variable) {
case "domain":
replaceValue = Environment.UserDomainName;
break;
case "user":
replaceValue = Environment.UserName;
break;
case "hostname":
replaceValue = Environment.MachineName;
break;
case "YYYY":
replaceValue = capturetime.Year.ToString();
break;
case "MM":
replaceValue = capturetime.Month.ToString();
break;
case "DD":
replaceValue = capturetime.Day.ToString();
break;
case "hh":
replaceValue = capturetime.Hour.ToString();
break;
case "mm":
replaceValue = capturetime.Minute.ToString();
break;
case "ss":
replaceValue = capturetime.Second.ToString();
break;
case "now":
replaceValue = DateTime.Now.ToString(dateFormat);
break;
case "capturetime":
replaceValue = capturetime.ToString(dateFormat);
break;
case "NUM":
conf.OutputFileIncrementingNumber = conf.OutputFileIncrementingNumber++;
IniConfig.Save();
pattern = pattern.Replace("%NUM%", zeroPad(num.ToString(), 6));
replaceValue = conf.OutputFileIncrementingNumber.ToString();
if (padWidth == 0) {
padWidth = -6;
padChar = '0';
}
// Use the last as it "might" have some nasty strings in it.
pattern = pattern.Replace("%title%", MakeFilenameSafe(title));
break;
case "title":
replaceValue = MakeFilenameSafe(title);
break;
}
}
// do substring
if (startIndex != 0 || endIndex != 0) {
if (startIndex < 0) {
startIndex = replaceValue.Length + startIndex;
}
if (endIndex < 0) {
endIndex = replaceValue.Length + endIndex;
}
if (endIndex != 0) {
try {
// Use MakeFQFilenameSafe so people can still use path characters for the name
return MakeFQFilenameSafe(pattern);
replaceValue = replaceValue.Substring(startIndex, endIndex);
} catch {
// Ignore
}
} else {
try {
replaceValue = replaceValue.Substring(startIndex);
} catch {
// Ignore
}
}
}
// do padding
if (padWidth >0) {
replaceValue = replaceValue.PadRight(padWidth, padChar);
} else if (padWidth < 0) {
replaceValue = replaceValue.PadLeft(-padWidth, padChar);
}
return replaceValue;
}
/// <summary>
/// "Simply" fill the pattern with environment variables
/// </summary>
/// <param name="pattern">String with pattern ${var}</param>
/// <returns>Filled string</returns>
public static string FillVariables(string pattern) {
IDictionary processVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process);
IDictionary userVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User);
IDictionary machineVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine);
return VAR_REGEXP.Replace(pattern,
new MatchEvaluator(delegate(Match m) { return MatchVarEvaluator(m, null, processVars, userVars, machineVars); })
);
}
private static string FillPattern(string pattern, ICaptureDetails captureDetails) {
IDictionary processVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process);
IDictionary userVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User);
IDictionary machineVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine);
try {
return VAR_REGEXP.Replace(pattern,
new MatchEvaluator(delegate(Match m) { return MatchVarEvaluator(m, captureDetails, processVars, userVars, machineVars); })
);
} catch (Exception e) {
// adding additional data for bug tracking
e.Data.Add("title", title);
e.Data.Add("pattern", initialPattern);
e.Data.Add("filename", pattern);
e.Data.Add("title", captureDetails.Title);
e.Data.Add("pattern", pattern);
throw e;
}
}
private static string zeroPad(string input, int chars) {
while(input.Length < chars) input = "0" + input;
return input;
}
}
}