Code formatting (indents etc.) to get it consistent, simplify it for contributors.

This commit is contained in:
Robin Krom 2021-03-28 19:24:26 +02:00
parent 726644de99
commit e8c0b307ee
No known key found for this signature in database
GPG key ID: BCC01364F1371490
435 changed files with 46647 additions and 39014 deletions

View file

@ -25,16 +25,18 @@ using Greenshot.Plugin.Box.Forms;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
namespace Greenshot.Plugin.Box { namespace Greenshot.Plugin.Box
{
/// <summary> /// <summary>
/// Description of ImgurConfiguration. /// Description of ImgurConfiguration.
/// </summary> /// </summary>
[IniSection("Box", Description = "Greenshot Box Plugin configuration")] [IniSection("Box", Description = "Greenshot Box Plugin configuration")]
public class BoxConfiguration : IniSection { public class BoxConfiguration : IniSection
[IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")] {
[IniProperty("UploadFormat", Description = "What file type to use for uploading", DefaultValue = "png")]
public OutputFormat UploadFormat { get; set; } public OutputFormat UploadFormat { get; set; }
[IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")] [IniProperty("UploadJpegQuality", Description = "JPEG file save quality in %.", DefaultValue = "80")]
public int UploadJpegQuality { get; set; } public int UploadJpegQuality { get; set; }
[IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send Box link to clipboard.", DefaultValue = "true")] [IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send Box link to clipboard.", DefaultValue = "true")]
@ -42,6 +44,7 @@ namespace Greenshot.Plugin.Box {
[IniProperty("UseSharedLink", Description = "Use the shared link, instead of the private, on the clipboard", DefaultValue = "True")] [IniProperty("UseSharedLink", Description = "Use the shared link, instead of the private, on the clipboard", DefaultValue = "True")]
public bool UseSharedLink { get; set; } public bool UseSharedLink { get; set; }
[IniProperty("FolderId", Description = "Folder ID to upload to, only change if you know what you are doing!", DefaultValue = "0")] [IniProperty("FolderId", Description = "Folder ID to upload to, only change if you know what you are doing!", DefaultValue = "0")]
public string FolderId { get; set; } public string FolderId { get; set; }
@ -51,30 +54,26 @@ namespace Greenshot.Plugin.Box {
/// <summary> /// <summary>
/// Not stored /// Not stored
/// </summary> /// </summary>
public string AccessToken { public string AccessToken { get; set; }
get;
set;
}
/// <summary> /// <summary>
/// Not stored /// Not stored
/// </summary> /// </summary>
public DateTimeOffset AccessTokenExpires { public DateTimeOffset AccessTokenExpires { get; set; }
get;
set;
}
/// <summary> /// <summary>
/// A form for token /// A form for token
/// </summary> /// </summary>
/// <returns>bool true if OK was pressed, false if cancel</returns> /// <returns>bool true if OK was pressed, false if cancel</returns>
public bool ShowConfigDialog() { public bool ShowConfigDialog()
{
DialogResult result = new SettingsForm().ShowDialog(); DialogResult result = new SettingsForm().ShowDialog();
if (result == DialogResult.OK) { if (result == DialogResult.OK)
{
return true; return true;
} }
return false; return false;
} }
} }
} }

View file

@ -24,10 +24,14 @@ using System.Drawing;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
namespace Greenshot.Plugin.Box { namespace Greenshot.Plugin.Box
public class BoxDestination : AbstractDestination { {
public class BoxDestination : AbstractDestination
{
private readonly BoxPlugin _plugin; private readonly BoxPlugin _plugin;
public BoxDestination(BoxPlugin plugin) {
public BoxDestination(BoxPlugin plugin)
{
_plugin = plugin; _plugin = plugin;
} }
@ -35,20 +39,25 @@ namespace Greenshot.Plugin.Box {
public override string Description => Language.GetString("box", LangKey.upload_menu_item); public override string Description => Language.GetString("box", LangKey.upload_menu_item);
public override Image DisplayIcon { public override Image DisplayIcon
get { {
get
{
ComponentResourceManager resources = new ComponentResourceManager(typeof(BoxPlugin)); ComponentResourceManager resources = new ComponentResourceManager(typeof(BoxPlugin));
return (Image)resources.GetObject("Box"); return (Image) resources.GetObject("Box");
} }
} }
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails)
{
ExportInformation exportInformation = new ExportInformation(Designation, Description); ExportInformation exportInformation = new ExportInformation(Designation, Description);
string uploadUrl = _plugin.Upload(captureDetails, surface); string uploadUrl = _plugin.Upload(captureDetails, surface);
if (uploadUrl != null) { if (uploadUrl != null)
{
exportInformation.ExportMade = true; exportInformation.ExportMade = true;
exportInformation.Uri = uploadUrl; exportInformation.Uri = uploadUrl;
} }
ProcessExport(exportInformation, surface); ProcessExport(exportInformation, surface);
return exportInformation; return exportInformation;
} }

View file

@ -22,39 +22,35 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.Serialization; using System.Runtime.Serialization;
namespace Greenshot.Plugin.Box { namespace Greenshot.Plugin.Box
{
[DataContract] [DataContract]
public class Authorization { public class Authorization
[DataMember(Name = "access_token")] {
public string AccessToken { get; set; } [DataMember(Name = "access_token")] public string AccessToken { get; set; }
[DataMember(Name = "expires_in")] [DataMember(Name = "expires_in")] public int ExpiresIn { get; set; }
public int ExpiresIn { get; set; } [DataMember(Name = "refresh_token")] public string RefreshToken { get; set; }
[DataMember(Name = "refresh_token")] [DataMember(Name = "token_type")] public string TokenType { get; set; }
public string RefreshToken { get; set; }
[DataMember(Name = "token_type")]
public string TokenType { get; set; }
}
[DataContract]
public class SharedLink {
[DataMember(Name = "url")]
public string Url { get; set; }
[DataMember(Name = "download_url")]
public string DownloadUrl { get; set; }
} }
[DataContract] [DataContract]
public class FileEntry { public class SharedLink
[DataMember(Name = "id")] {
public string Id { get; set; } [DataMember(Name = "url")] public string Url { get; set; }
[DataMember(Name = "name")] [DataMember(Name = "download_url")] public string DownloadUrl { get; set; }
public string Name { get; set; }
[DataMember(Name = "shared_link")]
public SharedLink SharedLink { get; set; }
} }
[DataContract] [DataContract]
public class Upload { public class FileEntry
[DataMember(Name = "entries")] {
public List<FileEntry> Entries { get; set; } [DataMember(Name = "id")] public string Id { get; set; }
[DataMember(Name = "name")] public string Name { get; set; }
[DataMember(Name = "shared_link")] public SharedLink SharedLink { get; set; }
}
[DataContract]
public class Upload
{
[DataMember(Name = "entries")] public List<FileEntry> Entries { get; set; }
} }
} }

View file

@ -30,18 +30,21 @@ using GreenshotPlugin.IniFile;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin; using GreenshotPlugin.Interfaces.Plugin;
namespace Greenshot.Plugin.Box { namespace Greenshot.Plugin.Box
{
/// <summary> /// <summary>
/// This is the Box base code /// This is the Box base code
/// </summary> /// </summary>
[Plugin("Box", true)] [Plugin("Box", true)]
public class BoxPlugin : IGreenshotPlugin { public class BoxPlugin : IGreenshotPlugin
{
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(BoxPlugin)); private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(BoxPlugin));
private static BoxConfiguration _config; private static BoxConfiguration _config;
private ComponentResourceManager _resources; private ComponentResourceManager _resources;
private ToolStripMenuItem _itemPlugInConfig; private ToolStripMenuItem _itemPlugInConfig;
public void Dispose() { public void Dispose()
{
Dispose(true); Dispose(true);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
@ -59,13 +62,14 @@ namespace Greenshot.Plugin.Box {
/// <summary> /// <summary>
/// Implementation of the IGreenshotPlugin.Initialize /// Implementation of the IGreenshotPlugin.Initialize
/// </summary> /// </summary>
public bool Initialize() { public bool Initialize()
{
// Register configuration (don't need the configuration itself) // Register configuration (don't need the configuration itself)
_config = IniConfig.GetIniSection<BoxConfiguration>(); _config = IniConfig.GetIniSection<BoxConfiguration>();
_resources = new ComponentResourceManager(typeof(BoxPlugin)); _resources = new ComponentResourceManager(typeof(BoxPlugin));
SimpleServiceProvider.Current.AddService<IDestination>(new BoxDestination(this)); SimpleServiceProvider.Current.AddService<IDestination>(new BoxDestination(this));
_itemPlugInConfig = new ToolStripMenuItem { _itemPlugInConfig = new ToolStripMenuItem
{
Image = (Image) _resources.GetObject("Box"), Image = (Image) _resources.GetObject("Box"),
Text = Language.GetString("box", LangKey.Configure) Text = Language.GetString("box", LangKey.Configure)
}; };
@ -76,49 +80,57 @@ namespace Greenshot.Plugin.Box {
return true; return true;
} }
public void OnLanguageChanged(object sender, EventArgs e) { public void OnLanguageChanged(object sender, EventArgs e)
if (_itemPlugInConfig != null) { {
if (_itemPlugInConfig != null)
{
_itemPlugInConfig.Text = Language.GetString("box", LangKey.Configure); _itemPlugInConfig.Text = Language.GetString("box", LangKey.Configure);
} }
} }
public void Shutdown() { public void Shutdown()
{
LOG.Debug("Box Plugin shutdown."); LOG.Debug("Box Plugin shutdown.");
} }
/// <summary> /// <summary>
/// Implementation of the IPlugin.Configure /// Implementation of the IPlugin.Configure
/// </summary> /// </summary>
public void Configure() { public void Configure()
{
_config.ShowConfigDialog(); _config.ShowConfigDialog();
} }
public void ConfigMenuClick(object sender, EventArgs eventArgs) { public void ConfigMenuClick(object sender, EventArgs eventArgs)
{
_config.ShowConfigDialog(); _config.ShowConfigDialog();
} }
/// <summary> /// <summary>
/// This will be called when the menu item in the Editor is clicked /// This will be called when the menu item in the Editor is clicked
/// </summary> /// </summary>
public string Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload) { public string Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload)
{
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, false); SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, false);
try { try
{
string url = null; string url = null;
string filename = Path.GetFileName(FilenameHelper.GetFilename(_config.UploadFormat, captureDetails)); string filename = Path.GetFileName(FilenameHelper.GetFilename(_config.UploadFormat, captureDetails));
SurfaceContainer imageToUpload = new SurfaceContainer(surfaceToUpload, outputSettings, filename); SurfaceContainer imageToUpload = new SurfaceContainer(surfaceToUpload, outputSettings, filename);
new PleaseWaitForm().ShowAndWait("Box", Language.GetString("box", LangKey.communication_wait), new PleaseWaitForm().ShowAndWait("Box", Language.GetString("box", LangKey.communication_wait),
delegate { delegate { url = BoxUtils.UploadToBox(imageToUpload, captureDetails.Title, filename); }
url = BoxUtils.UploadToBox(imageToUpload, captureDetails.Title, filename);
}
); );
if (url != null && _config.AfterUploadLinkToClipBoard) { if (url != null && _config.AfterUploadLinkToClipBoard)
{
ClipboardHelper.SetClipboardData(url); ClipboardHelper.SetClipboardData(url);
} }
return url; return url;
} catch (Exception ex) { }
catch (Exception ex)
{
LOG.Error("Error uploading.", ex); LOG.Error("Error uploading.", ex);
MessageBox.Show(Language.GetString("box", LangKey.upload_failure) + " " + ex.Message); MessageBox.Show(Language.GetString("box", LangKey.upload_failure) + " " + ex.Message);
return null; return null;

View file

@ -27,12 +27,13 @@ using GreenshotPlugin.Core;
using GreenshotPlugin.Core.OAuth; using GreenshotPlugin.Core.OAuth;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
namespace Greenshot.Plugin.Box { namespace Greenshot.Plugin.Box
{
/// <summary> /// <summary>
/// Description of BoxUtils. /// Description of BoxUtils.
/// </summary> /// </summary>
public static class BoxUtils { public static class BoxUtils
{
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(BoxUtils)); private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(BoxUtils));
private static readonly BoxConfiguration Config = IniConfig.GetIniSection<BoxConfiguration>(); private static readonly BoxConfiguration Config = IniConfig.GetIniSection<BoxConfiguration>();
private const string UploadFileUri = "https://upload.box.com/api/2.0/files/content"; private const string UploadFileUri = "https://upload.box.com/api/2.0/files/content";
@ -45,13 +46,16 @@ namespace Greenshot.Plugin.Box {
/// <param name="content"></param> /// <param name="content"></param>
/// <param name="settings">OAuth2Settings</param> /// <param name="settings">OAuth2Settings</param>
/// <returns>response</returns> /// <returns>response</returns>
public static string HttpPut(string url, string content, OAuth2Settings settings) { public static string HttpPut(string url, string content, OAuth2Settings settings)
var webRequest= OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.PUT, url, settings); {
var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.PUT, url, settings);
byte[] data = Encoding.UTF8.GetBytes(content); byte[] data = Encoding.UTF8.GetBytes(content);
using (var requestStream = webRequest.GetRequestStream()) { using (var requestStream = webRequest.GetRequestStream())
{
requestStream.Write(data, 0, data.Length); requestStream.Write(data, 0, data.Length);
} }
return NetworkHelper.GetResponseAsString(webRequest); return NetworkHelper.GetResponseAsString(webRequest);
} }
@ -63,8 +67,8 @@ namespace Greenshot.Plugin.Box {
/// <param name="title">Title of box upload</param> /// <param name="title">Title of box upload</param>
/// <param name="filename">Filename of box upload</param> /// <param name="filename">Filename of box upload</param>
/// <returns>url to uploaded image</returns> /// <returns>url to uploaded image</returns>
public static string UploadToBox(SurfaceContainer image, string title, string filename) { public static string UploadToBox(SurfaceContainer image, string title, string filename)
{
// Fill the OAuth2Settings // Fill the OAuth2Settings
var settings = new OAuth2Settings var settings = new OAuth2Settings
{ {
@ -83,12 +87,17 @@ namespace Greenshot.Plugin.Box {
// Copy the settings from the config, which is kept in memory and on the disk // Copy the settings from the config, which is kept in memory and on the disk
try { try
{
var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, UploadFileUri, settings); var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, UploadFileUri, settings);
IDictionary<string, object> parameters = new Dictionary<string, object> IDictionary<string, object> parameters = new Dictionary<string, object>
{ {
{ "file", image }, {
{ "parent_id", Config.FolderId } "file", image
},
{
"parent_id", Config.FolderId
}
}; };
NetworkHelper.WriteMultipartFormData(webRequest, parameters); NetworkHelper.WriteMultipartFormData(webRequest, parameters);
@ -100,13 +109,17 @@ namespace Greenshot.Plugin.Box {
var upload = JsonSerializer.Deserialize<Upload>(response); var upload = JsonSerializer.Deserialize<Upload>(response);
if (upload?.Entries == null || upload.Entries.Count == 0) return null; if (upload?.Entries == null || upload.Entries.Count == 0) return null;
if (Config.UseSharedLink) { if (Config.UseSharedLink)
{
string filesResponse = HttpPut(string.Format(FilesUri, upload.Entries[0].Id), "{\"shared_link\": {\"access\": \"open\"}}", settings); string filesResponse = HttpPut(string.Format(FilesUri, upload.Entries[0].Id), "{\"shared_link\": {\"access\": \"open\"}}", settings);
var file = JsonSerializer.Deserialize<FileEntry>(filesResponse); var file = JsonSerializer.Deserialize<FileEntry>(filesResponse);
return file.SharedLink.Url; return file.SharedLink.Url;
} }
return $"http://www.box.com/files/0/f/0/1/f_{upload.Entries[0].Id}"; return $"http://www.box.com/files/0/f/0/1/f_{upload.Entries[0].Id}";
} finally { }
finally
{
// Copy the settings back to the config, so they are stored. // Copy the settings back to the config, so they are stored.
Config.RefreshToken = settings.RefreshToken; Config.RefreshToken = settings.RefreshToken;
Config.AccessToken = settings.AccessToken; Config.AccessToken = settings.AccessToken;
@ -116,23 +129,26 @@ namespace Greenshot.Plugin.Box {
} }
} }
} }
/// <summary> /// <summary>
/// A simple helper class for the DataContractJsonSerializer /// A simple helper class for the DataContractJsonSerializer
/// </summary> /// </summary>
internal static class JsonSerializer { internal static class JsonSerializer
{
/// <summary> /// <summary>
/// Helper method to parse JSON to object /// Helper method to parse JSON to object
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <param name="jsonString"></param> /// <param name="jsonString"></param>
/// <returns></returns> /// <returns></returns>
public static T Deserialize<T>(string jsonString) { public static T Deserialize<T>(string jsonString)
{
var deserializer = new DataContractJsonSerializer(typeof(T)); var deserializer = new DataContractJsonSerializer(typeof(T));
using var stream = new MemoryStream(); using var stream = new MemoryStream();
byte[] content = Encoding.UTF8.GetBytes(jsonString); byte[] content = Encoding.UTF8.GetBytes(jsonString);
stream.Write(content, 0, content.Length); stream.Write(content, 0, content.Length);
stream.Seek(0, SeekOrigin.Begin); stream.Seek(0, SeekOrigin.Begin);
return (T)deserializer.ReadObject(stream); return (T) deserializer.ReadObject(stream);
} }
} }
} }

View file

@ -21,7 +21,9 @@
using GreenshotPlugin.Controls; using GreenshotPlugin.Controls;
namespace Greenshot.Plugin.Box.Forms { namespace Greenshot.Plugin.Box.Forms
public class BoxForm : GreenshotForm { {
public class BoxForm : GreenshotForm
{
} }
} }

View file

@ -19,12 +19,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Greenshot.Plugin.Box.Forms { namespace Greenshot.Plugin.Box.Forms
{
/// <summary> /// <summary>
/// Description of PasswordRequestForm. /// Description of PasswordRequestForm.
/// </summary> /// </summary>
public partial class SettingsForm : BoxForm { public partial class SettingsForm : BoxForm
public SettingsForm() { {
public SettingsForm()
{
// //
// The InitializeComponent() call is required for Windows Forms designer support. // The InitializeComponent() call is required for Windows Forms designer support.
// //

View file

@ -18,8 +18,11 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Greenshot.Plugin.Box {
public enum LangKey { namespace Greenshot.Plugin.Box
{
public enum LangKey
{
upload_menu_item, upload_menu_item,
upload_failure, upload_failure,
communication_wait, communication_wait,

View file

@ -26,16 +26,21 @@ using GreenshotConfluencePlugin.confluence;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
namespace Greenshot.Plugin.Confluence { namespace Greenshot.Plugin.Confluence
public class Page { {
public Page(RemotePage page) { public class Page
{
public Page(RemotePage page)
{
Id = page.id; Id = page.id;
Title = page.title; Title = page.title;
SpaceKey = page.space; SpaceKey = page.space;
Url = page.url; Url = page.url;
Content = page.content; Content = page.content;
} }
public Page(RemoteSearchResult searchResult, string space) {
public Page(RemoteSearchResult searchResult, string space)
{
Id = searchResult.id; Id = searchResult.id;
Title = searchResult.title; Title = searchResult.title;
SpaceKey = space; SpaceKey = space;
@ -43,53 +48,39 @@ namespace Greenshot.Plugin.Confluence {
Content = searchResult.excerpt; Content = searchResult.excerpt;
} }
public Page(RemotePageSummary pageSummary) { public Page(RemotePageSummary pageSummary)
{
Id = pageSummary.id; Id = pageSummary.id;
Title = pageSummary.title; Title = pageSummary.title;
SpaceKey = pageSummary.space; SpaceKey = pageSummary.space;
Url =pageSummary.url; Url = pageSummary.url;
} }
public long Id {
get; public long Id { get; set; }
set; public string Title { get; set; }
public string Url { get; set; }
public string Content { get; set; }
public string SpaceKey { get; set; }
} }
public string Title {
get; public class Space
set; {
} public Space(RemoteSpaceSummary space)
public string Url { {
get;
set;
}
public string Content {
get;
set;
}
public string SpaceKey {
get;
set;
}
}
public class Space {
public Space(RemoteSpaceSummary space) {
Key = space.key; Key = space.key;
Name = space.name; Name = space.name;
} }
public string Key {
get; public string Key { get; set; }
set; public string Name { get; set; }
}
public string Name {
get;
set;
}
} }
/// <summary> /// <summary>
/// For details see the Confluence API site /// For details see the Confluence API site
/// See: http://confluence.atlassian.com/display/CONFDEV/Remote+API+Specification /// See: http://confluence.atlassian.com/display/CONFDEV/Remote+API+Specification
/// </summary> /// </summary>
public class ConfluenceConnector : IDisposable { public class ConfluenceConnector : IDisposable
{
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ConfluenceConnector)); private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ConfluenceConnector));
private const string AuthFailedExceptionName = "com.atlassian.confluence.rpc.AuthenticationFailedException"; private const string AuthFailedExceptionName = "com.atlassian.confluence.rpc.AuthenticationFailedException";
private const string V2Failed = "AXIS"; private const string V2Failed = "AXIS";
@ -102,29 +93,37 @@ namespace Greenshot.Plugin.Confluence {
private string _url; private string _url;
private readonly Cache<string, RemotePage> _pageCache = new Cache<string, RemotePage>(60 * Config.Timeout); private readonly Cache<string, RemotePage> _pageCache = new Cache<string, RemotePage>(60 * Config.Timeout);
public void Dispose() { public void Dispose()
{
Dispose(true); Dispose(true);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
protected void Dispose(bool disposing) { protected void Dispose(bool disposing)
if (_confluence != null) { {
if (_confluence != null)
{
Logout(); Logout();
} }
if (disposing) {
if (_confluence != null) { if (disposing)
{
if (_confluence != null)
{
_confluence.Dispose(); _confluence.Dispose();
_confluence = null; _confluence = null;
} }
} }
} }
public ConfluenceConnector(string url, int timeout) { public ConfluenceConnector(string url, int timeout)
{
_timeout = timeout; _timeout = timeout;
Init(url); Init(url);
} }
private void Init(string url) { private void Init(string url)
{
_url = url; _url = url;
_confluence = new ConfluenceSoapServiceService _confluence = new ConfluenceSoapServiceService
{ {
@ -133,7 +132,8 @@ namespace Greenshot.Plugin.Confluence {
}; };
} }
~ConfluenceConnector() { ~ConfluenceConnector()
{
Dispose(false); Dispose(false);
} }
@ -141,21 +141,29 @@ namespace Greenshot.Plugin.Confluence {
/// Internal login which catches the exceptions /// Internal login which catches the exceptions
/// </summary> /// </summary>
/// <returns>true if login was done sucessfully</returns> /// <returns>true if login was done sucessfully</returns>
private bool DoLogin(string user, string password) { private bool DoLogin(string user, string password)
try { {
try
{
_credentials = _confluence.login(user, password); _credentials = _confluence.login(user, password);
_loggedInTime = DateTime.Now; _loggedInTime = DateTime.Now;
_loggedIn = true; _loggedIn = true;
} catch (Exception e) { }
catch (Exception e)
{
// Check if confluence-v2 caused an error, use v1 instead // Check if confluence-v2 caused an error, use v1 instead
if (e.Message.Contains(V2Failed) && _url.Contains("v2")) { if (e.Message.Contains(V2Failed) && _url.Contains("v2"))
{
Init(_url.Replace("v2", "v1")); Init(_url.Replace("v2", "v1"));
return DoLogin(user, password); return DoLogin(user, password);
} }
// check if auth failed // check if auth failed
if (e.Message.Contains(AuthFailedExceptionName)) { if (e.Message.Contains(AuthFailedExceptionName))
{
return false; return false;
} }
// Not an authentication issue // Not an authentication issue
_loggedIn = false; _loggedIn = false;
_credentials = null; _credentials = null;
@ -163,66 +171,89 @@ namespace Greenshot.Plugin.Confluence {
e.Data.Add("url", _url); e.Data.Add("url", _url);
throw; throw;
} }
return true; return true;
} }
public void Login() { public void Login()
{
Logout(); Logout();
try { try
{
// Get the system name, so the user knows where to login to // Get the system name, so the user knows where to login to
string systemName = _url.Replace(ConfluenceConfiguration.DEFAULT_POSTFIX1,""); string systemName = _url.Replace(ConfluenceConfiguration.DEFAULT_POSTFIX1, "");
systemName = systemName.Replace(ConfluenceConfiguration.DEFAULT_POSTFIX2, ""); systemName = systemName.Replace(ConfluenceConfiguration.DEFAULT_POSTFIX2, "");
CredentialsDialog dialog = new CredentialsDialog(systemName) CredentialsDialog dialog = new CredentialsDialog(systemName)
{ {
Name = null Name = null
}; };
while (dialog.Show(dialog.Name) == DialogResult.OK) { while (dialog.Show(dialog.Name) == DialogResult.OK)
if (DoLogin(dialog.Name, dialog.Password)) { {
if (dialog.SaveChecked) { if (DoLogin(dialog.Name, dialog.Password))
{
if (dialog.SaveChecked)
{
dialog.Confirm(true); dialog.Confirm(true);
} }
return; return;
} else { }
try { else
{
try
{
dialog.Confirm(false); dialog.Confirm(false);
} catch (ApplicationException e) { }
catch (ApplicationException e)
{
// exception handling ... // exception handling ...
Log.Error("Problem using the credentials dialog", e); Log.Error("Problem using the credentials dialog", e);
} }
// For every windows version after XP show an incorrect password baloon // For every windows version after XP show an incorrect password baloon
dialog.IncorrectPassword = true; dialog.IncorrectPassword = true;
// Make sure the dialog is display, the password was false! // Make sure the dialog is display, the password was false!
dialog.AlwaysDisplay = true; dialog.AlwaysDisplay = true;
} }
} }
} catch (ApplicationException e) { }
catch (ApplicationException e)
{
// exception handling ... // exception handling ...
Log.Error("Problem using the credentials dialog", e); Log.Error("Problem using the credentials dialog", e);
} }
} }
public void Logout() { public void Logout()
if (_credentials != null) { {
if (_credentials != null)
{
_confluence.logout(_credentials); _confluence.logout(_credentials);
_credentials = null; _credentials = null;
_loggedIn = false; _loggedIn = false;
} }
} }
private void CheckCredentials() { private void CheckCredentials()
if (_loggedIn) { {
if (_loggedInTime.AddMinutes(_timeout-1).CompareTo(DateTime.Now) < 0) { if (_loggedIn)
{
if (_loggedInTime.AddMinutes(_timeout - 1).CompareTo(DateTime.Now) < 0)
{
Logout(); Logout();
Login(); Login();
} }
} else { }
else
{
Login(); Login();
} }
} }
public bool IsLoggedIn => _loggedIn; public bool IsLoggedIn => _loggedIn;
public void AddAttachment(long pageId, string mime, string comment, string filename, IBinaryContainer image) { public void AddAttachment(long pageId, string mime, string comment, string filename, IBinaryContainer image)
{
CheckCredentials(); CheckCredentials();
// Comment is ignored, see: http://jira.atlassian.com/browse/CONF-9395 // Comment is ignored, see: http://jira.atlassian.com/browse/CONF-9395
var attachment = new RemoteAttachment var attachment = new RemoteAttachment
@ -234,69 +265,88 @@ namespace Greenshot.Plugin.Confluence {
_confluence.addAttachment(_credentials, pageId, attachment, image.ToByteArray()); _confluence.addAttachment(_credentials, pageId, attachment, image.ToByteArray());
} }
public Page GetPage(string spaceKey, string pageTitle) { public Page GetPage(string spaceKey, string pageTitle)
{
RemotePage page = null; RemotePage page = null;
string cacheKey = spaceKey + pageTitle; string cacheKey = spaceKey + pageTitle;
if (_pageCache.Contains(cacheKey)) { if (_pageCache.Contains(cacheKey))
{
page = _pageCache[cacheKey]; page = _pageCache[cacheKey];
} }
if (page == null) {
if (page == null)
{
CheckCredentials(); CheckCredentials();
page = _confluence.getPage(_credentials, spaceKey, pageTitle); page = _confluence.getPage(_credentials, spaceKey, pageTitle);
_pageCache.Add(cacheKey, page); _pageCache.Add(cacheKey, page);
} }
return new Page(page); return new Page(page);
} }
public Page GetPage(long pageId) { public Page GetPage(long pageId)
{
RemotePage page = null; RemotePage page = null;
string cacheKey = pageId.ToString(); string cacheKey = pageId.ToString();
if (_pageCache.Contains(cacheKey)) { if (_pageCache.Contains(cacheKey))
{
page = _pageCache[cacheKey]; page = _pageCache[cacheKey];
} }
if (page == null) {
if (page == null)
{
CheckCredentials(); CheckCredentials();
page = _confluence.getPage(_credentials, pageId); page = _confluence.getPage(_credentials, pageId);
_pageCache.Add(cacheKey, page); _pageCache.Add(cacheKey, page);
} }
return new Page(page); return new Page(page);
} }
public Page GetSpaceHomepage(Space spaceSummary) { public Page GetSpaceHomepage(Space spaceSummary)
{
CheckCredentials(); CheckCredentials();
RemoteSpace spaceDetail = _confluence.getSpace(_credentials, spaceSummary.Key); RemoteSpace spaceDetail = _confluence.getSpace(_credentials, spaceSummary.Key);
RemotePage page = _confluence.getPage(_credentials, spaceDetail.homePage); RemotePage page = _confluence.getPage(_credentials, spaceDetail.homePage);
return new Page(page); return new Page(page);
} }
public IEnumerable<Space> GetSpaceSummaries() { public IEnumerable<Space> GetSpaceSummaries()
{
CheckCredentials(); CheckCredentials();
RemoteSpaceSummary [] spaces = _confluence.getSpaces(_credentials); RemoteSpaceSummary[] spaces = _confluence.getSpaces(_credentials);
foreach(RemoteSpaceSummary space in spaces) { foreach (RemoteSpaceSummary space in spaces)
{
yield return new Space(space); yield return new Space(space);
} }
} }
public IEnumerable<Page> GetPageChildren(Page parentPage) { public IEnumerable<Page> GetPageChildren(Page parentPage)
{
CheckCredentials(); CheckCredentials();
RemotePageSummary[] pages = _confluence.getChildren(_credentials, parentPage.Id); RemotePageSummary[] pages = _confluence.getChildren(_credentials, parentPage.Id);
foreach(RemotePageSummary page in pages) { foreach (RemotePageSummary page in pages)
{
yield return new Page(page); yield return new Page(page);
} }
} }
public IEnumerable<Page> GetPageSummaries(Space space) { public IEnumerable<Page> GetPageSummaries(Space space)
{
CheckCredentials(); CheckCredentials();
RemotePageSummary[] pages = _confluence.getPages(_credentials, space.Key); RemotePageSummary[] pages = _confluence.getPages(_credentials, space.Key);
foreach(RemotePageSummary page in pages) { foreach (RemotePageSummary page in pages)
{
yield return new Page(page); yield return new Page(page);
} }
} }
public IEnumerable<Page> SearchPages(string query, string space) { public IEnumerable<Page> SearchPages(string query, string space)
{
CheckCredentials(); CheckCredentials();
foreach(var searchResult in _confluence.search(_credentials, query, 20)) { foreach (var searchResult in _confluence.search(_credentials, query, 20))
{
Log.DebugFormat("Got result of type {0}", searchResult.type); Log.DebugFormat("Got result of type {0}", searchResult.type);
if ("page".Equals(searchResult.type)) if ("page".Equals(searchResult.type))
{ {

View file

@ -23,63 +23,45 @@ using System;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
namespace Greenshot.Plugin.Confluence { namespace Greenshot.Plugin.Confluence
{
/// <summary> /// <summary>
/// Description of ConfluenceConfiguration. /// Description of ConfluenceConfiguration.
/// </summary> /// </summary>
[Serializable] [Serializable]
[IniSection("Confluence", Description="Greenshot Confluence Plugin configuration")] [IniSection("Confluence", Description = "Greenshot Confluence Plugin configuration")]
public class ConfluenceConfiguration : IniSection { public class ConfluenceConfiguration : IniSection
{
public const string DEFAULT_POSTFIX1 = "/rpc/soap-axis/confluenceservice-v1?wsdl"; public const string DEFAULT_POSTFIX1 = "/rpc/soap-axis/confluenceservice-v1?wsdl";
public const string DEFAULT_POSTFIX2 = "/rpc/soap-axis/confluenceservice-v2?wsdl"; public const string DEFAULT_POSTFIX2 = "/rpc/soap-axis/confluenceservice-v2?wsdl";
public const string DEFAULT_PREFIX = "http://"; public const string DEFAULT_PREFIX = "http://";
private const string DEFAULT_URL = DEFAULT_PREFIX + "confluence"; private const string DEFAULT_URL = DEFAULT_PREFIX + "confluence";
[IniProperty("Url", Description="Url to Confluence system, including wsdl.", DefaultValue=DEFAULT_URL)] [IniProperty("Url", Description = "Url to Confluence system, including wsdl.", DefaultValue = DEFAULT_URL)]
public string Url { public string Url { get; set; }
get;
set; [IniProperty("Timeout", Description = "Session timeout in minutes", DefaultValue = "30")]
} public int Timeout { get; set; }
[IniProperty("Timeout", Description="Session timeout in minutes", DefaultValue="30")]
public int Timeout { [IniProperty("UploadFormat", Description = "What file type to use for uploading", DefaultValue = "png")]
get; public OutputFormat UploadFormat { get; set; }
set;
} [IniProperty("UploadJpegQuality", Description = "JPEG file save quality in %.", DefaultValue = "80")]
public int UploadJpegQuality { get; set; }
[IniProperty("UploadReduceColors", Description = "Reduce color amount of the uploaded image to 256", DefaultValue = "False")]
public bool UploadReduceColors { get; set; }
[IniProperty("OpenPageAfterUpload", Description = "Open the page where the picture is uploaded after upload", DefaultValue = "True")]
public bool OpenPageAfterUpload { get; set; }
[IniProperty("CopyWikiMarkupForImageToClipboard", Description = "Copy the Wikimarkup for the recently uploaded image to the Clipboard", DefaultValue = "True")]
public bool CopyWikiMarkupForImageToClipboard { get; set; }
[IniProperty("SearchSpaceKey", Description = "Key of last space that was searched for")]
public string SearchSpaceKey { get; set; }
[IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")]
public OutputFormat UploadFormat {
get;
set;
}
[IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
public int UploadJpegQuality {
get;
set;
}
[IniProperty("UploadReduceColors", Description="Reduce color amount of the uploaded image to 256", DefaultValue="False")]
public bool UploadReduceColors {
get;
set;
}
[IniProperty("OpenPageAfterUpload", Description="Open the page where the picture is uploaded after upload", DefaultValue="True")]
public bool OpenPageAfterUpload {
get;
set;
}
[IniProperty("CopyWikiMarkupForImageToClipboard", Description="Copy the Wikimarkup for the recently uploaded image to the Clipboard", DefaultValue="True")]
public bool CopyWikiMarkupForImageToClipboard {
get;
set;
}
[IniProperty("SearchSpaceKey", Description="Key of last space that was searched for")]
public string SearchSpaceKey {
get;
set;
}
[IniProperty("IncludePersonSpaces", Description = "Include personal spaces in the search & browse spaces list", DefaultValue = "False")] [IniProperty("IncludePersonSpaces", Description = "Include personal spaces in the search & browse spaces list", DefaultValue = "False")]
public bool IncludePersonSpaces { public bool IncludePersonSpaces { get; set; }
get;
set;
}
} }
} }

View file

@ -32,121 +32,145 @@ using GreenshotPlugin.IniFile;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin; using GreenshotPlugin.Interfaces.Plugin;
namespace Greenshot.Plugin.Confluence { namespace Greenshot.Plugin.Confluence
{
/// <summary> /// <summary>
/// Description of ConfluenceDestination. /// Description of ConfluenceDestination.
/// </summary> /// </summary>
public class ConfluenceDestination : AbstractDestination { public class ConfluenceDestination : AbstractDestination
{
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ConfluenceDestination)); private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ConfluenceDestination));
private static readonly ConfluenceConfiguration ConfluenceConfig = IniConfig.GetIniSection<ConfluenceConfiguration>(); private static readonly ConfluenceConfiguration ConfluenceConfig = IniConfig.GetIniSection<ConfluenceConfiguration>();
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>(); private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
private static readonly Image ConfluenceIcon; private static readonly Image ConfluenceIcon;
private readonly Page _page; private readonly Page _page;
static ConfluenceDestination() { static ConfluenceDestination()
{
IsInitialized = false; IsInitialized = false;
try { try
{
Uri confluenceIconUri = new Uri("/GreenshotConfluencePlugin;component/Images/Confluence.ico", UriKind.Relative); Uri confluenceIconUri = new Uri("/GreenshotConfluencePlugin;component/Images/Confluence.ico", UriKind.Relative);
using (Stream iconStream = Application.GetResourceStream(confluenceIconUri)?.Stream) using (Stream iconStream = Application.GetResourceStream(confluenceIconUri)?.Stream)
{ {
// TODO: Check what to do with the IImage // TODO: Check what to do with the IImage
ConfluenceIcon = ImageHelper.FromStream(iconStream); ConfluenceIcon = ImageHelper.FromStream(iconStream);
} }
IsInitialized = true; IsInitialized = true;
} catch (Exception ex) { }
catch (Exception ex)
{
Log.ErrorFormat("Problem in the confluence static initializer: {0}", ex.Message); Log.ErrorFormat("Problem in the confluence static initializer: {0}", ex.Message);
} }
} }
public static bool IsInitialized public static bool IsInitialized { get; private set; }
public ConfluenceDestination()
{ {
get;
private set;
} }
public ConfluenceDestination() { public ConfluenceDestination(Page page)
} {
public ConfluenceDestination(Page page) {
_page = page; _page = page;
} }
public override string Designation { public override string Designation
get { {
return "Confluence"; get { return "Confluence"; }
}
} }
public override string Description { public override string Description
get { {
if (_page == null) { get
{
if (_page == null)
{
return Language.GetString("confluence", LangKey.upload_menu_item); return Language.GetString("confluence", LangKey.upload_menu_item);
} else { }
else
{
return Language.GetString("confluence", LangKey.upload_menu_item) + ": \"" + _page.Title + "\""; return Language.GetString("confluence", LangKey.upload_menu_item) + ": \"" + _page.Title + "\"";
} }
} }
} }
public override bool IsDynamic { public override bool IsDynamic
get { {
return true; get { return true; }
}
} }
public override bool IsActive { public override bool IsActive
get { {
return base.IsActive && !string.IsNullOrEmpty(ConfluenceConfig.Url); get { return base.IsActive && !string.IsNullOrEmpty(ConfluenceConfig.Url); }
}
} }
public override Image DisplayIcon { public override Image DisplayIcon
get { {
return ConfluenceIcon; get { return ConfluenceIcon; }
}
} }
public override IEnumerable<IDestination> DynamicDestinations() { public override IEnumerable<IDestination> DynamicDestinations()
if (ConfluencePlugin.ConfluenceConnectorNoLogin == null || !ConfluencePlugin.ConfluenceConnectorNoLogin.IsLoggedIn) { {
if (ConfluencePlugin.ConfluenceConnectorNoLogin == null || !ConfluencePlugin.ConfluenceConnectorNoLogin.IsLoggedIn)
{
yield break; yield break;
} }
List<Page> currentPages = ConfluenceUtils.GetCurrentPages(); List<Page> currentPages = ConfluenceUtils.GetCurrentPages();
if (currentPages == null || currentPages.Count == 0) { if (currentPages == null || currentPages.Count == 0)
{
yield break; yield break;
} }
foreach(Page currentPage in currentPages) {
foreach (Page currentPage in currentPages)
{
yield return new ConfluenceDestination(currentPage); yield return new ConfluenceDestination(currentPage);
} }
} }
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails)
{
ExportInformation exportInformation = new ExportInformation(Designation, Description); ExportInformation exportInformation = new ExportInformation(Designation, Description);
// force password check to take place before the pages load // force password check to take place before the pages load
if (!ConfluencePlugin.ConfluenceConnector.IsLoggedIn) { if (!ConfluencePlugin.ConfluenceConnector.IsLoggedIn)
{
return exportInformation; return exportInformation;
} }
Page selectedPage = _page; Page selectedPage = _page;
bool openPage = (_page == null) && ConfluenceConfig.OpenPageAfterUpload; bool openPage = (_page == null) && ConfluenceConfig.OpenPageAfterUpload;
string filename = FilenameHelper.GetFilenameWithoutExtensionFromPattern(CoreConfig.OutputFileFilenamePattern, captureDetails); string filename = FilenameHelper.GetFilenameWithoutExtensionFromPattern(CoreConfig.OutputFileFilenamePattern, captureDetails);
if (selectedPage == null) { if (selectedPage == null)
{
Forms.ConfluenceUpload confluenceUpload = new Forms.ConfluenceUpload(filename); Forms.ConfluenceUpload confluenceUpload = new Forms.ConfluenceUpload(filename);
bool? dialogResult = confluenceUpload.ShowDialog(); bool? dialogResult = confluenceUpload.ShowDialog();
if (dialogResult.HasValue && dialogResult.Value) { if (dialogResult.HasValue && dialogResult.Value)
{
selectedPage = confluenceUpload.SelectedPage; selectedPage = confluenceUpload.SelectedPage;
if (confluenceUpload.IsOpenPageSelected) { if (confluenceUpload.IsOpenPageSelected)
{
openPage = false; openPage = false;
} }
filename = confluenceUpload.Filename; filename = confluenceUpload.Filename;
} }
} }
string extension = "." + ConfluenceConfig.UploadFormat; string extension = "." + ConfluenceConfig.UploadFormat;
if (!filename.ToLower().EndsWith(extension)) { if (!filename.ToLower().EndsWith(extension))
{
filename += extension; filename += extension;
} }
if (selectedPage != null) {
if (selectedPage != null)
{
bool uploaded = Upload(surface, selectedPage, filename, out var errorMessage); bool uploaded = Upload(surface, selectedPage, filename, out var errorMessage);
if (uploaded) { if (uploaded)
if (openPage) { {
if (openPage)
{
try try
{ {
Process.Start(selectedPage.Url); Process.Start(selectedPage.Url);
@ -156,23 +180,32 @@ namespace Greenshot.Plugin.Confluence {
// Ignore // Ignore
} }
} }
exportInformation.ExportMade = true; exportInformation.ExportMade = true;
exportInformation.Uri = selectedPage.Url; exportInformation.Uri = selectedPage.Url;
} else { }
else
{
exportInformation.ErrorMessage = errorMessage; exportInformation.ErrorMessage = errorMessage;
} }
} }
ProcessExport(exportInformation, surface); ProcessExport(exportInformation, surface);
return exportInformation; return exportInformation;
} }
private bool Upload(ISurface surfaceToUpload, Page page, string filename, out string errorMessage) { private bool Upload(ISurface surfaceToUpload, Page page, string filename, out string errorMessage)
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(ConfluenceConfig.UploadFormat, ConfluenceConfig.UploadJpegQuality, ConfluenceConfig.UploadReduceColors); {
SurfaceOutputSettings outputSettings =
new SurfaceOutputSettings(ConfluenceConfig.UploadFormat, ConfluenceConfig.UploadJpegQuality, ConfluenceConfig.UploadReduceColors);
errorMessage = null; errorMessage = null;
try { try
{
new PleaseWaitForm().ShowAndWait(Description, Language.GetString("confluence", LangKey.communication_wait), new PleaseWaitForm().ShowAndWait(Description, Language.GetString("confluence", LangKey.communication_wait),
delegate { delegate
ConfluencePlugin.ConfluenceConnector.AddAttachment(page.Id, "image/" + ConfluenceConfig.UploadFormat.ToString().ToLower(), null, filename, new SurfaceContainer(surfaceToUpload, outputSettings, filename)); {
ConfluencePlugin.ConfluenceConnector.AddAttachment(page.Id, "image/" + ConfluenceConfig.UploadFormat.ToString().ToLower(), null, filename,
new SurfaceContainer(surfaceToUpload, outputSettings, filename));
} }
); );
Log.Debug("Uploaded to Confluence."); Log.Debug("Uploaded to Confluence.");
@ -180,25 +213,39 @@ namespace Greenshot.Plugin.Confluence {
{ {
return true; return true;
} }
int retryCount = 2; int retryCount = 2;
while (retryCount >= 0) { while (retryCount >= 0)
try { {
try
{
Clipboard.SetText("!" + filename + "!"); Clipboard.SetText("!" + filename + "!");
break; break;
} catch (Exception ee) { }
if (retryCount == 0) { catch (Exception ee)
{
if (retryCount == 0)
{
Log.Error(ee); Log.Error(ee);
} else { }
else
{
Thread.Sleep(100); Thread.Sleep(100);
} }
} finally { }
finally
{
--retryCount; --retryCount;
} }
} }
return true; return true;
} catch(Exception e) { }
catch (Exception e)
{
errorMessage = e.Message; errorMessage = e.Message;
} }
return false; return false;
} }
} }

View file

@ -28,53 +28,70 @@ using GreenshotPlugin.IniFile;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin; using GreenshotPlugin.Interfaces.Plugin;
namespace Greenshot.Plugin.Confluence { namespace Greenshot.Plugin.Confluence
{
/// <summary> /// <summary>
/// This is the ConfluencePlugin base code /// This is the ConfluencePlugin base code
/// </summary> /// </summary>
[Plugin("Confluence", true)] [Plugin("Confluence", true)]
public class ConfluencePlugin : IGreenshotPlugin { public class ConfluencePlugin : IGreenshotPlugin
{
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ConfluencePlugin)); private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ConfluencePlugin));
private static ConfluenceConnector _confluenceConnector; private static ConfluenceConnector _confluenceConnector;
private static ConfluenceConfiguration _config; private static ConfluenceConfiguration _config;
public void Dispose() { public void Dispose()
{
Dispose(true); Dispose(true);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
protected void Dispose(bool disposing) { protected void Dispose(bool disposing)
{
//if (disposing) {} //if (disposing) {}
} }
private static void CreateConfluenceConnector() { private static void CreateConfluenceConnector()
if (_confluenceConnector == null) { {
if (_config.Url.Contains("soap-axis")) { if (_confluenceConnector == null)
{
if (_config.Url.Contains("soap-axis"))
{
_confluenceConnector = new ConfluenceConnector(_config.Url, _config.Timeout); _confluenceConnector = new ConfluenceConnector(_config.Url, _config.Timeout);
} else { }
else
{
_confluenceConnector = new ConfluenceConnector(_config.Url + ConfluenceConfiguration.DEFAULT_POSTFIX2, _config.Timeout); _confluenceConnector = new ConfluenceConnector(_config.Url + ConfluenceConfiguration.DEFAULT_POSTFIX2, _config.Timeout);
} }
} }
} }
public static ConfluenceConnector ConfluenceConnectorNoLogin { public static ConfluenceConnector ConfluenceConnectorNoLogin
get { {
return _confluenceConnector; get { return _confluenceConnector; }
}
} }
public static ConfluenceConnector ConfluenceConnector { public static ConfluenceConnector ConfluenceConnector
get { {
if (_confluenceConnector == null) { get
{
if (_confluenceConnector == null)
{
CreateConfluenceConnector(); CreateConfluenceConnector();
} }
try {
if (_confluenceConnector != null && !_confluenceConnector.IsLoggedIn) { try
{
if (_confluenceConnector != null && !_confluenceConnector.IsLoggedIn)
{
_confluenceConnector.Login(); _confluenceConnector.Login();
} }
} catch (Exception e) { }
catch (Exception e)
{
MessageBox.Show(Language.GetFormattedString("confluence", LangKey.login_error, e.Message)); MessageBox.Show(Language.GetFormattedString("confluence", LangKey.login_error, e.Message));
} }
return _confluenceConnector; return _confluenceConnector;
} }
} }
@ -82,29 +99,39 @@ namespace Greenshot.Plugin.Confluence {
/// <summary> /// <summary>
/// Implementation of the IGreenshotPlugin.Initialize /// Implementation of the IGreenshotPlugin.Initialize
/// </summary> /// </summary>
public bool Initialize() { public bool Initialize()
{
// Register configuration (don't need the configuration itself) // Register configuration (don't need the configuration itself)
_config = IniConfig.GetIniSection<ConfluenceConfiguration>(); _config = IniConfig.GetIniSection<ConfluenceConfiguration>();
if(_config.IsDirty) { if (_config.IsDirty)
{
IniConfig.Save(); IniConfig.Save();
} }
try {
try
{
TranslationManager.Instance.TranslationProvider = new LanguageXMLTranslationProvider(); TranslationManager.Instance.TranslationProvider = new LanguageXMLTranslationProvider();
//resources = new ComponentResourceManager(typeof(ConfluencePlugin)); //resources = new ComponentResourceManager(typeof(ConfluencePlugin));
} catch (Exception ex) { }
catch (Exception ex)
{
LOG.ErrorFormat("Problem in ConfluencePlugin.Initialize: {0}", ex.Message); LOG.ErrorFormat("Problem in ConfluencePlugin.Initialize: {0}", ex.Message);
return false; return false;
} }
if (ConfluenceDestination.IsInitialized) if (ConfluenceDestination.IsInitialized)
{ {
SimpleServiceProvider.Current.AddService<IDestination>(new ConfluenceDestination()); SimpleServiceProvider.Current.AddService<IDestination>(new ConfluenceDestination());
} }
return true; return true;
} }
public void Shutdown() { public void Shutdown()
{
LOG.Debug("Confluence Plugin shutdown."); LOG.Debug("Confluence Plugin shutdown.");
if (_confluenceConnector != null) { if (_confluenceConnector != null)
{
_confluenceConnector.Logout(); _confluenceConnector.Logout();
_confluenceConnector = null; _confluenceConnector = null;
} }
@ -113,20 +140,26 @@ namespace Greenshot.Plugin.Confluence {
/// <summary> /// <summary>
/// Implementation of the IPlugin.Configure /// Implementation of the IPlugin.Configure
/// </summary> /// </summary>
public void Configure() { public void Configure()
{
ConfluenceConfiguration clonedConfig = _config.Clone(); ConfluenceConfiguration clonedConfig = _config.Clone();
ConfluenceConfigurationForm configForm = new ConfluenceConfigurationForm(clonedConfig); ConfluenceConfigurationForm configForm = new ConfluenceConfigurationForm(clonedConfig);
string url = _config.Url; string url = _config.Url;
bool? dialogResult = configForm.ShowDialog(); bool? dialogResult = configForm.ShowDialog();
if (dialogResult.HasValue && dialogResult.Value) { if (dialogResult.HasValue && dialogResult.Value)
{
// copy the new object to the old... // copy the new object to the old...
clonedConfig.CloneTo(_config); clonedConfig.CloneTo(_config);
IniConfig.Save(); IniConfig.Save();
if (_confluenceConnector != null) { if (_confluenceConnector != null)
if (!url.Equals(_config.Url)) { {
if (_confluenceConnector.IsLoggedIn) { if (!url.Equals(_config.Url))
{
if (_confluenceConnector.IsLoggedIn)
{
_confluenceConnector.Logout(); _confluenceConnector.Logout();
} }
_confluenceConnector = null; _confluenceConnector = null;
} }
} }

View file

@ -26,76 +26,106 @@ using System.Text.RegularExpressions;
using System.Windows.Automation; using System.Windows.Automation;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
namespace Greenshot.Plugin.Confluence { namespace Greenshot.Plugin.Confluence
{
/// <summary> /// <summary>
/// Description of ConfluenceUtils. /// Description of ConfluenceUtils.
/// </summary> /// </summary>
public class ConfluenceUtils { public class ConfluenceUtils
{
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ConfluenceUtils)); private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ConfluenceUtils));
public static List<Page> GetCurrentPages() { public static List<Page> GetCurrentPages()
{
List<Page> pages = new List<Page>(); List<Page> pages = new List<Page>();
Regex pageIdRegex = new Regex(@"pageId=(\d+)"); Regex pageIdRegex = new Regex(@"pageId=(\d+)");
Regex spacePageRegex = new Regex(@"\/display\/([^\/]+)\/([^#]+)"); Regex spacePageRegex = new Regex(@"\/display\/([^\/]+)\/([^#]+)");
foreach(string browserurl in GetBrowserUrls()) { foreach (string browserurl in GetBrowserUrls())
{
string url; string url;
try { try
{
url = Uri.UnescapeDataString(browserurl).Replace("+", " "); url = Uri.UnescapeDataString(browserurl).Replace("+", " ");
} catch { }
catch
{
LOG.WarnFormat("Error processing URL: {0}", browserurl); LOG.WarnFormat("Error processing URL: {0}", browserurl);
continue; continue;
} }
MatchCollection pageIdMatch = pageIdRegex.Matches(url); MatchCollection pageIdMatch = pageIdRegex.Matches(url);
if (pageIdMatch != null && pageIdMatch.Count > 0) { if (pageIdMatch != null && pageIdMatch.Count > 0)
{
long pageId = long.Parse(pageIdMatch[0].Groups[1].Value); long pageId = long.Parse(pageIdMatch[0].Groups[1].Value);
try { try
{
bool pageDouble = false; bool pageDouble = false;
foreach(Page page in pages) { foreach (Page page in pages)
if (page.Id == pageId) { {
if (page.Id == pageId)
{
pageDouble = true; pageDouble = true;
LOG.DebugFormat("Skipping double page with ID {0}", pageId); LOG.DebugFormat("Skipping double page with ID {0}", pageId);
break; break;
} }
} }
if (!pageDouble) {
if (!pageDouble)
{
Page page = ConfluencePlugin.ConfluenceConnector.GetPage(pageId); Page page = ConfluencePlugin.ConfluenceConnector.GetPage(pageId);
LOG.DebugFormat("Adding page {0}", page.Title); LOG.DebugFormat("Adding page {0}", page.Title);
pages.Add(page); pages.Add(page);
} }
continue; continue;
} catch (Exception ex) { }
catch (Exception ex)
{
// Preventing security problems // Preventing security problems
LOG.DebugFormat("Couldn't get page details for PageID {0}", pageId); LOG.DebugFormat("Couldn't get page details for PageID {0}", pageId);
LOG.Warn(ex); LOG.Warn(ex);
} }
} }
MatchCollection spacePageMatch = spacePageRegex.Matches(url); MatchCollection spacePageMatch = spacePageRegex.Matches(url);
if (spacePageMatch != null && spacePageMatch.Count > 0) { if (spacePageMatch != null && spacePageMatch.Count > 0)
if (spacePageMatch[0].Groups.Count >= 2) { {
if (spacePageMatch[0].Groups.Count >= 2)
{
string space = spacePageMatch[0].Groups[1].Value; string space = spacePageMatch[0].Groups[1].Value;
string title = spacePageMatch[0].Groups[2].Value; string title = spacePageMatch[0].Groups[2].Value;
if (string.IsNullOrEmpty(title) || string.IsNullOrEmpty(space)) { if (string.IsNullOrEmpty(title) || string.IsNullOrEmpty(space))
{
continue; continue;
} }
if (title.EndsWith("#")) {
title = title.Substring(0, title.Length-1); if (title.EndsWith("#"))
{
title = title.Substring(0, title.Length - 1);
} }
try {
try
{
bool pageDouble = false; bool pageDouble = false;
foreach(Page page in pages) { foreach (Page page in pages)
if (page.Title.Equals(title)) { {
if (page.Title.Equals(title))
{
LOG.DebugFormat("Skipping double page with title {0}", title); LOG.DebugFormat("Skipping double page with title {0}", title);
pageDouble = true; pageDouble = true;
break; break;
} }
} }
if (!pageDouble) {
if (!pageDouble)
{
Page page = ConfluencePlugin.ConfluenceConnector.GetPage(space, title); Page page = ConfluencePlugin.ConfluenceConnector.GetPage(space, title);
LOG.DebugFormat("Adding page {0}", page.Title); LOG.DebugFormat("Adding page {0}", page.Title);
pages.Add(page); pages.Add(page);
} }
} catch (Exception ex) { }
catch (Exception ex)
{
// Preventing security problems // Preventing security problems
LOG.DebugFormat("Couldn't get page details for space {0} / title {1}", space, title); LOG.DebugFormat("Couldn't get page details for space {0} / title {1}", space, title);
LOG.Warn(ex); LOG.Warn(ex);
@ -103,49 +133,65 @@ namespace Greenshot.Plugin.Confluence {
} }
} }
} }
return pages; return pages;
} }
private static IEnumerable<string> GetBrowserUrls() { private static IEnumerable<string> GetBrowserUrls()
{
HashSet<string> urls = new HashSet<string>(); HashSet<string> urls = new HashSet<string>();
// FireFox // FireFox
foreach (WindowDetails window in WindowDetails.GetAllWindows("MozillaWindowClass")) { foreach (WindowDetails window in WindowDetails.GetAllWindows("MozillaWindowClass"))
if (window.Text.Length == 0) { {
continue; if (window.Text.Length == 0)
} {
AutomationElement currentElement = AutomationElement.FromHandle(window.Handle);
Condition conditionCustom = new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Custom), new PropertyCondition(AutomationElement.IsOffscreenProperty, false));
for (int i = 5; i > 0 && currentElement != null; i--) {
currentElement = currentElement.FindFirst(TreeScope.Children, conditionCustom);
}
if (currentElement == null) {
continue; continue;
} }
Condition conditionDocument = new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document), new PropertyCondition(AutomationElement.IsOffscreenProperty, false)); AutomationElement currentElement = AutomationElement.FromHandle(window.Handle);
Condition conditionCustom = new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Custom),
new PropertyCondition(AutomationElement.IsOffscreenProperty, false));
for (int i = 5; i > 0 && currentElement != null; i--)
{
currentElement = currentElement.FindFirst(TreeScope.Children, conditionCustom);
}
if (currentElement == null)
{
continue;
}
Condition conditionDocument = new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document),
new PropertyCondition(AutomationElement.IsOffscreenProperty, false));
AutomationElement docElement = currentElement.FindFirst(TreeScope.Children, conditionDocument); AutomationElement docElement = currentElement.FindFirst(TreeScope.Children, conditionDocument);
if (docElement == null) { if (docElement == null)
{
continue; continue;
} }
foreach (AutomationPattern pattern in docElement.GetSupportedPatterns()) {
if (pattern.ProgrammaticName != "ValuePatternIdentifiers.Pattern") { foreach (AutomationPattern pattern in docElement.GetSupportedPatterns())
{
if (pattern.ProgrammaticName != "ValuePatternIdentifiers.Pattern")
{
continue; continue;
} }
string url = (docElement.GetCurrentPattern(pattern) as ValuePattern).Current.Value; string url = (docElement.GetCurrentPattern(pattern) as ValuePattern).Current.Value;
if (!string.IsNullOrEmpty(url)) { if (!string.IsNullOrEmpty(url))
{
urls.Add(url); urls.Add(url);
break; break;
} }
} }
} }
foreach(string url in IEHelper.GetIEUrls().Distinct()) { foreach (string url in IEHelper.GetIEUrls().Distinct())
{
urls.Add(url); urls.Add(url);
} }
return urls; return urls;
} }
} }
} }

View file

@ -28,69 +28,86 @@ using System.Reflection;
using System.Windows.Data; using System.Windows.Data;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
namespace Greenshot.Plugin.Confluence { namespace Greenshot.Plugin.Confluence
public class EnumDisplayer : IValueConverter { {
public class EnumDisplayer : IValueConverter
{
private Type _type; private Type _type;
private IDictionary _displayValues; private IDictionary _displayValues;
private IDictionary _reverseValues; private IDictionary _reverseValues;
public Type Type { public Type Type
{
get { return _type; } get { return _type; }
set { set
if (!value.IsEnum) { {
if (!value.IsEnum)
{
throw new ArgumentException("parameter is not an Enumerated type", nameof(value)); throw new ArgumentException("parameter is not an Enumerated type", nameof(value));
} }
_type = value; _type = value;
} }
} }
public ReadOnlyCollection<string> DisplayNames { public ReadOnlyCollection<string> DisplayNames
get { {
get
{
var genericTypeDefinition = typeof(Dictionary<,>).GetGenericTypeDefinition(); var genericTypeDefinition = typeof(Dictionary<,>).GetGenericTypeDefinition();
if (genericTypeDefinition != null) if (genericTypeDefinition != null)
{ {
_reverseValues = (IDictionary) Activator.CreateInstance(genericTypeDefinition.MakeGenericType(typeof(string),_type)); _reverseValues = (IDictionary) Activator.CreateInstance(genericTypeDefinition.MakeGenericType(typeof(string), _type));
} }
var typeDefinition = typeof(Dictionary<,>).GetGenericTypeDefinition(); var typeDefinition = typeof(Dictionary<,>).GetGenericTypeDefinition();
if (typeDefinition != null) if (typeDefinition != null)
{ {
_displayValues = (IDictionary)Activator.CreateInstance(typeDefinition.MakeGenericType(_type, typeof(string))); _displayValues = (IDictionary) Activator.CreateInstance(typeDefinition.MakeGenericType(_type, typeof(string)));
} }
var fields = _type.GetFields(BindingFlags.Public | BindingFlags.Static); var fields = _type.GetFields(BindingFlags.Public | BindingFlags.Static);
foreach (var field in fields) { foreach (var field in fields)
DisplayKeyAttribute[] a = (DisplayKeyAttribute[])field.GetCustomAttributes(typeof(DisplayKeyAttribute), false); {
DisplayKeyAttribute[] a = (DisplayKeyAttribute[]) field.GetCustomAttributes(typeof(DisplayKeyAttribute), false);
string displayKey = GetDisplayKeyValue(a); string displayKey = GetDisplayKeyValue(a);
object enumValue = field.GetValue(null); object enumValue = field.GetValue(null);
string displayString; string displayString;
if (displayKey != null && Language.HasKey(displayKey)) { if (displayKey != null && Language.HasKey(displayKey))
{
displayString = Language.GetString(displayKey); displayString = Language.GetString(displayKey);
} }
displayString = displayKey ?? enumValue.ToString(); displayString = displayKey ?? enumValue.ToString();
_displayValues.Add(enumValue, displayString); _displayValues.Add(enumValue, displayString);
_reverseValues.Add(displayString, enumValue); _reverseValues.Add(displayString, enumValue);
} }
return new List<string>((IEnumerable<string>)_displayValues.Values).AsReadOnly();
return new List<string>((IEnumerable<string>) _displayValues.Values).AsReadOnly();
} }
} }
private static string GetDisplayKeyValue(DisplayKeyAttribute[] a) { private static string GetDisplayKeyValue(DisplayKeyAttribute[] a)
if (a == null || a.Length == 0) { {
if (a == null || a.Length == 0)
{
return null; return null;
} }
DisplayKeyAttribute dka = a[0]; DisplayKeyAttribute dka = a[0];
return dka.Value; return dka.Value;
} }
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture) { object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return _displayValues[value]; return _displayValues[value];
} }
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return _reverseValues[value]; return _reverseValues[value];
} }
} }

View file

@ -21,20 +21,24 @@
using System.Windows; using System.Windows;
namespace Greenshot.Plugin.Confluence.Forms { namespace Greenshot.Plugin.Confluence.Forms
{
/// <summary> /// <summary>
/// Interaction logic for ConfluenceConfigurationForm.xaml /// Interaction logic for ConfluenceConfigurationForm.xaml
/// </summary> /// </summary>
public partial class ConfluenceConfigurationForm : Window { public partial class ConfluenceConfigurationForm : Window
{
public ConfluenceConfiguration Config { get; } public ConfluenceConfiguration Config { get; }
public ConfluenceConfigurationForm(ConfluenceConfiguration config) { public ConfluenceConfigurationForm(ConfluenceConfiguration config)
{
DataContext = config; DataContext = config;
Config = config; Config = config;
InitializeComponent(); InitializeComponent();
} }
private void Button_OK_Click(object sender, RoutedEventArgs e) { private void Button_OK_Click(object sender, RoutedEventArgs e)
{
DialogResult = true; DialogResult = true;
} }
} }

View file

@ -21,7 +21,8 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace Greenshot.Plugin.Confluence.Forms { namespace Greenshot.Plugin.Confluence.Forms
{
/// <summary> /// <summary>
/// Interaction logic for ConfluencePagePicker.xaml /// Interaction logic for ConfluencePagePicker.xaml
/// </summary> /// </summary>
@ -29,27 +30,34 @@ namespace Greenshot.Plugin.Confluence.Forms {
{ {
private readonly ConfluenceUpload _confluenceUpload; private readonly ConfluenceUpload _confluenceUpload;
public ConfluencePagePicker(ConfluenceUpload confluenceUpload, List<Page> pagesToPick) { public ConfluencePagePicker(ConfluenceUpload confluenceUpload, List<Page> pagesToPick)
{
_confluenceUpload = confluenceUpload; _confluenceUpload = confluenceUpload;
DataContext = pagesToPick; DataContext = pagesToPick;
InitializeComponent(); InitializeComponent();
} }
private void PageListView_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) { private void PageListView_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
SelectionChanged(); SelectionChanged();
} }
private void SelectionChanged() { private void SelectionChanged()
if (PageListView.HasItems && PageListView.SelectedItems.Count > 0) { {
_confluenceUpload.SelectedPage = (Page)PageListView.SelectedItem; if (PageListView.HasItems && PageListView.SelectedItems.Count > 0)
{
_confluenceUpload.SelectedPage = (Page) PageListView.SelectedItem;
// Make sure the uploader knows we selected an already opened page // Make sure the uploader knows we selected an already opened page
_confluenceUpload.IsOpenPageSelected = true; _confluenceUpload.IsOpenPageSelected = true;
} else { }
else
{
_confluenceUpload.SelectedPage = null; _confluenceUpload.SelectedPage = null;
} }
} }
private void Page_Loaded(object sender, System.Windows.RoutedEventArgs e) { private void Page_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
SelectionChanged(); SelectionChanged();
} }
} }

View file

@ -25,7 +25,8 @@ using System.Linq;
using System.Windows; using System.Windows;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
namespace Greenshot.Plugin.Confluence.Forms { namespace Greenshot.Plugin.Confluence.Forms
{
public partial class ConfluenceSearch public partial class ConfluenceSearch
{ {
private static readonly ConfluenceConfiguration ConfluenceConfig = IniConfig.GetIniSection<ConfluenceConfiguration>(); private static readonly ConfluenceConfiguration ConfluenceConfig = IniConfig.GetIniSection<ConfluenceConfiguration>();
@ -35,58 +36,76 @@ namespace Greenshot.Plugin.Confluence.Forms {
public ObservableCollection<Page> Pages { get; } = new ObservableCollection<Page>(); public ObservableCollection<Page> Pages { get; } = new ObservableCollection<Page>();
public ConfluenceSearch(ConfluenceUpload confluenceUpload) { public ConfluenceSearch(ConfluenceUpload confluenceUpload)
{
_confluenceUpload = confluenceUpload; _confluenceUpload = confluenceUpload;
DataContext = this; DataContext = this;
InitializeComponent(); InitializeComponent();
if (ConfluenceConfig.SearchSpaceKey == null) { if (ConfluenceConfig.SearchSpaceKey == null)
{
SpaceComboBox.SelectedItem = Spaces.FirstOrDefault(); SpaceComboBox.SelectedItem = Spaces.FirstOrDefault();
} else { }
foreach(var space in Spaces) { else
if (space.Key.Equals(ConfluenceConfig.SearchSpaceKey)) { {
foreach (var space in Spaces)
{
if (space.Key.Equals(ConfluenceConfig.SearchSpaceKey))
{
SpaceComboBox.SelectedItem = space; SpaceComboBox.SelectedItem = space;
} }
} }
} }
} }
private void PageListView_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) { private void PageListView_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
SelectionChanged(); SelectionChanged();
} }
private void SelectionChanged() { private void SelectionChanged()
if (PageListView.HasItems && PageListView.SelectedItems.Count > 0) { {
_confluenceUpload.SelectedPage = (Page)PageListView.SelectedItem; if (PageListView.HasItems && PageListView.SelectedItems.Count > 0)
} else { {
_confluenceUpload.SelectedPage = (Page) PageListView.SelectedItem;
}
else
{
_confluenceUpload.SelectedPage = null; _confluenceUpload.SelectedPage = null;
} }
} }
private void Search_Click(object sender, RoutedEventArgs e) { private void Search_Click(object sender, RoutedEventArgs e)
{
DoSearch(); DoSearch();
} }
private void DoSearch() { private void DoSearch()
string spaceKey = (string)SpaceComboBox.SelectedValue; {
string spaceKey = (string) SpaceComboBox.SelectedValue;
ConfluenceConfig.SearchSpaceKey = spaceKey; ConfluenceConfig.SearchSpaceKey = spaceKey;
Pages.Clear(); Pages.Clear();
foreach(var page in ConfluencePlugin.ConfluenceConnector.SearchPages(searchText.Text, spaceKey).OrderBy(p => p.Title)) { foreach (var page in ConfluencePlugin.ConfluenceConnector.SearchPages(searchText.Text, spaceKey).OrderBy(p => p.Title))
{
Pages.Add(page); Pages.Add(page);
} }
} }
private void SearchText_KeyDown(object sender, System.Windows.Input.KeyEventArgs e) { private void SearchText_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
if (e.Key == System.Windows.Input.Key.Return && Search.IsEnabled) { {
if (e.Key == System.Windows.Input.Key.Return && Search.IsEnabled)
{
DoSearch(); DoSearch();
e.Handled = true; e.Handled = true;
} }
} }
private void Page_Loaded(object sender, RoutedEventArgs e) { private void Page_Loaded(object sender, RoutedEventArgs e)
{
SelectionChanged(); SelectionChanged();
} }
private void SearchText_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e) { private void SearchText_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
Search.IsEnabled = !string.IsNullOrEmpty(searchText.Text); Search.IsEnabled = !string.IsNullOrEmpty(searchText.Text);
} }
} }

View file

@ -27,7 +27,8 @@ using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Threading; using System.Windows.Threading;
namespace Greenshot.Plugin.Confluence.Forms { namespace Greenshot.Plugin.Confluence.Forms
{
/// <summary> /// <summary>
/// Interaction logic for ConfluenceTreePicker.xaml /// Interaction logic for ConfluenceTreePicker.xaml
/// </summary> /// </summary>
@ -38,28 +39,36 @@ namespace Greenshot.Plugin.Confluence.Forms {
private readonly ConfluenceUpload _confluenceUpload; private readonly ConfluenceUpload _confluenceUpload;
private bool _isInitDone; private bool _isInitDone;
public ConfluenceTreePicker(ConfluenceUpload confluenceUpload) { public ConfluenceTreePicker(ConfluenceUpload confluenceUpload)
{
_confluenceConnector = ConfluencePlugin.ConfluenceConnector; _confluenceConnector = ConfluencePlugin.ConfluenceConnector;
_confluenceUpload = confluenceUpload; _confluenceUpload = confluenceUpload;
InitializeComponent(); InitializeComponent();
} }
private void PageTreeViewItem_DoubleClick(object sender, MouseButtonEventArgs eventArgs) { private void PageTreeViewItem_DoubleClick(object sender, MouseButtonEventArgs eventArgs)
{
Log.Debug("spaceTreeViewItem_MouseLeftButtonDown is called!"); Log.Debug("spaceTreeViewItem_MouseLeftButtonDown is called!");
TreeViewItem clickedItem = eventArgs.Source as TreeViewItem; TreeViewItem clickedItem = eventArgs.Source as TreeViewItem;
if (clickedItem?.Tag is not Page page) { if (clickedItem?.Tag is not Page page)
{
return; return;
} }
if (clickedItem.HasItems) if (clickedItem.HasItems)
{ {
return; return;
} }
Log.Debug("Loading pages for page: " + page.Title); Log.Debug("Loading pages for page: " + page.Title);
new Thread(() => { new Thread(() =>
Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)(() => {ShowBusy.Visibility = Visibility.Visible;})); {
Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart) (() => { ShowBusy.Visibility = Visibility.Visible; }));
var pages = _confluenceConnector.GetPageChildren(page).OrderBy(p => p.Title); var pages = _confluenceConnector.GetPageChildren(page).OrderBy(p => p.Title);
Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)(() => { Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart) (() =>
foreach(var childPage in pages) { {
foreach (var childPage in pages)
{
Log.Debug("Adding page: " + childPage.Title); Log.Debug("Adding page: " + childPage.Title);
var pageTreeViewItem = new TreeViewItem var pageTreeViewItem = new TreeViewItem
{ {
@ -70,32 +79,46 @@ namespace Greenshot.Plugin.Confluence.Forms {
pageTreeViewItem.PreviewMouseDoubleClick += PageTreeViewItem_DoubleClick; pageTreeViewItem.PreviewMouseDoubleClick += PageTreeViewItem_DoubleClick;
pageTreeViewItem.PreviewMouseLeftButtonDown += PageTreeViewItem_Click; pageTreeViewItem.PreviewMouseLeftButtonDown += PageTreeViewItem_Click;
} }
ShowBusy.Visibility = Visibility.Collapsed; ShowBusy.Visibility = Visibility.Collapsed;
})); }));
}) { Name = "Loading childpages for confluence page " + page.Title }.Start(); })
{
Name = "Loading childpages for confluence page " + page.Title
}.Start();
} }
private void PageTreeViewItem_Click(object sender, MouseButtonEventArgs eventArgs) { private void PageTreeViewItem_Click(object sender, MouseButtonEventArgs eventArgs)
{
Log.Debug("pageTreeViewItem_PreviewMouseDoubleClick is called!"); Log.Debug("pageTreeViewItem_PreviewMouseDoubleClick is called!");
if (eventArgs.Source is not TreeViewItem clickedItem) { if (eventArgs.Source is not TreeViewItem clickedItem)
{
return; return;
} }
Page page = clickedItem.Tag as Page; Page page = clickedItem.Tag as Page;
_confluenceUpload.SelectedPage = page; _confluenceUpload.SelectedPage = page;
if (page != null) { if (page != null)
{
Log.Debug("Page selected: " + page.Title); Log.Debug("Page selected: " + page.Title);
} }
} }
private void Page_Loaded(object sender, RoutedEventArgs e) { private void Page_Loaded(object sender, RoutedEventArgs e)
{
_confluenceUpload.SelectedPage = null; _confluenceUpload.SelectedPage = null;
if (_isInitDone) { if (_isInitDone)
{
return; return;
} }
ShowBusy.Visibility = Visibility.Visible; ShowBusy.Visibility = Visibility.Visible;
new Thread(() => { new Thread(() =>
Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)(() => { {
foreach (Space space in _confluenceUpload.Spaces) { Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart) (() =>
{
foreach (Space space in _confluenceUpload.Spaces)
{
TreeViewItem spaceTreeViewItem = new TreeViewItem TreeViewItem spaceTreeViewItem = new TreeViewItem
{ {
Header = space.Name, Header = space.Name,
@ -103,7 +126,8 @@ namespace Greenshot.Plugin.Confluence.Forms {
}; };
// Get homepage // Get homepage
try { try
{
Page page = _confluenceConnector.GetSpaceHomepage(space); Page page = _confluenceConnector.GetSpaceHomepage(space);
TreeViewItem pageTreeViewItem = new TreeViewItem TreeViewItem pageTreeViewItem = new TreeViewItem
{ {
@ -114,14 +138,20 @@ namespace Greenshot.Plugin.Confluence.Forms {
pageTreeViewItem.PreviewMouseLeftButtonDown += PageTreeViewItem_Click; pageTreeViewItem.PreviewMouseLeftButtonDown += PageTreeViewItem_Click;
spaceTreeViewItem.Items.Add(pageTreeViewItem); spaceTreeViewItem.Items.Add(pageTreeViewItem);
ConfluenceTreeView.Items.Add(spaceTreeViewItem); ConfluenceTreeView.Items.Add(spaceTreeViewItem);
} catch (Exception ex) { }
catch (Exception ex)
{
Log.Error("Can't get homepage for space : " + space.Name + " (" + ex.Message + ")"); Log.Error("Can't get homepage for space : " + space.Name + " (" + ex.Message + ")");
} }
} }
ShowBusy.Visibility = Visibility.Collapsed; ShowBusy.Visibility = Visibility.Collapsed;
_isInitDone = true; _isInitDone = true;
})); }));
}) { Name = "Loading spaces for confluence"}.Start(); })
{
Name = "Loading spaces for confluence"
}.Start();
} }
} }
} }

View file

@ -25,91 +25,116 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Windows; using System.Windows;
namespace Greenshot.Plugin.Confluence.Forms { namespace Greenshot.Plugin.Confluence.Forms
{
/// <summary> /// <summary>
/// Interaction logic for ConfluenceUpload.xaml /// Interaction logic for ConfluenceUpload.xaml
/// </summary> /// </summary>
public partial class ConfluenceUpload : Window { public partial class ConfluenceUpload : Window
{
private System.Windows.Controls.Page _pickerPage; private System.Windows.Controls.Page _pickerPage;
public System.Windows.Controls.Page PickerPage {
get { public System.Windows.Controls.Page PickerPage
if (_pickerPage == null) { {
get
{
if (_pickerPage == null)
{
List<Page> pages = ConfluenceUtils.GetCurrentPages(); List<Page> pages = ConfluenceUtils.GetCurrentPages();
if (pages != null && pages.Count > 0) { if (pages != null && pages.Count > 0)
{
_pickerPage = new ConfluencePagePicker(this, pages); _pickerPage = new ConfluencePagePicker(this, pages);
} }
} }
return _pickerPage; return _pickerPage;
} }
} }
private System.Windows.Controls.Page _searchPage; private System.Windows.Controls.Page _searchPage;
public System.Windows.Controls.Page SearchPage {
public System.Windows.Controls.Page SearchPage
{
get { return _searchPage ??= new ConfluenceSearch(this); } get { return _searchPage ??= new ConfluenceSearch(this); }
} }
private System.Windows.Controls.Page _browsePage; private System.Windows.Controls.Page _browsePage;
public System.Windows.Controls.Page BrowsePage {
public System.Windows.Controls.Page BrowsePage
{
get { return _browsePage ??= new ConfluenceTreePicker(this); } get { return _browsePage ??= new ConfluenceTreePicker(this); }
} }
private Page _selectedPage; private Page _selectedPage;
public Page SelectedPage {
public Page SelectedPage
{
get => _selectedPage; get => _selectedPage;
set { set
{
_selectedPage = value; _selectedPage = value;
Upload.IsEnabled = _selectedPage != null; Upload.IsEnabled = _selectedPage != null;
IsOpenPageSelected = false; IsOpenPageSelected = false;
} }
} }
public bool IsOpenPageSelected { public bool IsOpenPageSelected { get; set; }
get; public string Filename { get; set; }
set;
}
public string Filename {
get;
set;
}
private static DateTime _lastLoad = DateTime.Now; private static DateTime _lastLoad = DateTime.Now;
private static IList<Space> _spaces; private static IList<Space> _spaces;
public IList<Space> Spaces {
get { public IList<Space> Spaces
{
get
{
UpdateSpaces(); UpdateSpaces();
while (_spaces == null) { while (_spaces == null)
{
Thread.Sleep(300); Thread.Sleep(300);
} }
return _spaces; return _spaces;
} }
} }
public ConfluenceUpload(string filename) { public ConfluenceUpload(string filename)
{
Filename = filename; Filename = filename;
InitializeComponent(); InitializeComponent();
DataContext = this; DataContext = this;
UpdateSpaces(); UpdateSpaces();
if (PickerPage == null) { if (PickerPage == null)
{
PickerTab.Visibility = Visibility.Collapsed; PickerTab.Visibility = Visibility.Collapsed;
SearchTab.IsSelected = true; SearchTab.IsSelected = true;
} }
} }
private void UpdateSpaces() { private void UpdateSpaces()
if (_spaces != null && DateTime.Now.AddMinutes(-60).CompareTo(_lastLoad) > 0) { {
if (_spaces != null && DateTime.Now.AddMinutes(-60).CompareTo(_lastLoad) > 0)
{
// Reset // Reset
_spaces = null; _spaces = null;
} }
// Check if load is needed // Check if load is needed
if (_spaces == null) { if (_spaces == null)
(new Thread(() => { {
(new Thread(() =>
{
_spaces = ConfluencePlugin.ConfluenceConnector.GetSpaceSummaries().OrderBy(s => s.Name).ToList(); _spaces = ConfluencePlugin.ConfluenceConnector.GetSpaceSummaries().OrderBy(s => s.Name).ToList();
_lastLoad = DateTime.Now; _lastLoad = DateTime.Now;
}) { Name = "Loading spaces for confluence"}).Start(); })
{
Name = "Loading spaces for confluence"
}).Start();
} }
} }
private void Upload_Click(object sender, RoutedEventArgs e) { private void Upload_Click(object sender, RoutedEventArgs e)
{
DialogResult = true; DialogResult = true;
} }
} }

View file

@ -19,8 +19,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Greenshot.Plugin.Confluence { namespace Greenshot.Plugin.Confluence
public enum LangKey { {
public enum LangKey
{
login_error, login_error,
upload_menu_item, upload_menu_item,
communication_wait communication_wait

View file

@ -1,5 +1,7 @@
namespace Greenshot.Plugin.Confluence.Support { namespace Greenshot.Plugin.Confluence.Support
public interface ITranslationProvider { {
public interface ITranslationProvider
{
/// <summary> /// <summary>
/// Translates the specified key. /// Translates the specified key.
/// </summary> /// </summary>

View file

@ -22,13 +22,13 @@ namespace Greenshot.Plugin.Confluence.Support
protected override void StartListening(object source) protected override void StartListening(object source)
{ {
var manager = (TranslationManager)source; var manager = (TranslationManager) source;
manager.LanguageChanged += OnLanguageChanged; manager.LanguageChanged += OnLanguageChanged;
} }
protected override void StopListening(object source) protected override void StopListening(object source)
{ {
var manager = (TranslationManager)source; var manager = (TranslationManager) source;
manager.LanguageChanged -= OnLanguageChanged; manager.LanguageChanged -= OnLanguageChanged;
} }
@ -37,15 +37,15 @@ namespace Greenshot.Plugin.Confluence.Support
get get
{ {
Type managerType = typeof(LanguageChangedEventManager); Type managerType = typeof(LanguageChangedEventManager);
var manager = (LanguageChangedEventManager)GetCurrentManager(managerType); var manager = (LanguageChangedEventManager) GetCurrentManager(managerType);
if (manager == null) if (manager == null)
{ {
manager = new LanguageChangedEventManager(); manager = new LanguageChangedEventManager();
SetCurrentManager(managerType, manager); SetCurrentManager(managerType, manager);
} }
return manager; return manager;
} }
} }
} }
} }

View file

@ -1,17 +1,22 @@
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
namespace Greenshot.Plugin.Confluence.Support { namespace Greenshot.Plugin.Confluence.Support
{
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public class LanguageXMLTranslationProvider : ITranslationProvider { public class LanguageXMLTranslationProvider : ITranslationProvider
{
/// <summary> /// <summary>
/// See <see cref="ITranslationProvider.Translate" /> /// See <see cref="ITranslationProvider.Translate" />
/// </summary> /// </summary>
public object Translate(string key) { public object Translate(string key)
if (Language.HasKey("confluence", key)) { {
if (Language.HasKey("confluence", key))
{
return Language.GetString("confluence", key); return Language.GetString("confluence", key);
} }
return key; return key;
} }
} }

View file

@ -25,7 +25,7 @@ namespace Greenshot.Plugin.Confluence.Support
public string Key public string Key
{ {
get { return _key; } get { return _key; }
set { _key = value;} set { _key = value; }
} }
/// <summary> /// <summary>

View file

@ -2,15 +2,18 @@
using System.ComponentModel; using System.ComponentModel;
using System.Windows; using System.Windows;
namespace Greenshot.Plugin.Confluence.Support { namespace Greenshot.Plugin.Confluence.Support
public class TranslationData : IWeakEventListener, INotifyPropertyChanged { {
public class TranslationData : IWeakEventListener, INotifyPropertyChanged
{
private readonly string _key; private readonly string _key;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TranslationData"/> class. /// Initializes a new instance of the <see cref="TranslationData"/> class.
/// </summary> /// </summary>
/// <param name="key">The key.</param> /// <param name="key">The key.</param>
public TranslationData( string key) { public TranslationData(string key)
{
_key = key; _key = key;
LanguageChangedEventManager.AddListener(TranslationManager.Instance, this); LanguageChangedEventManager.AddListener(TranslationManager.Instance, this);
} }
@ -19,7 +22,8 @@ namespace Greenshot.Plugin.Confluence.Support {
/// Releases unmanaged resources and performs other cleanup operations before the /// Releases unmanaged resources and performs other cleanup operations before the
/// <see cref="TranslationData"/> is reclaimed by garbage collection. /// <see cref="TranslationData"/> is reclaimed by garbage collection.
/// </summary> /// </summary>
~TranslationData() { ~TranslationData()
{
LanguageChangedEventManager.RemoveListener(TranslationManager.Instance, this); LanguageChangedEventManager.RemoveListener(TranslationManager.Instance, this);
} }
@ -32,12 +36,13 @@ namespace Greenshot.Plugin.Confluence.Support {
OnLanguageChanged(sender, e); OnLanguageChanged(sender, e);
return true; return true;
} }
return false; return false;
} }
private void OnLanguageChanged(object sender, EventArgs e) private void OnLanguageChanged(object sender, EventArgs e)
{ {
PropertyChanged?.Invoke( this, new PropertyChangedEventArgs("Value")); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Value"));
} }
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;

View file

@ -1,7 +1,9 @@
using System; using System;
namespace Greenshot.Plugin.Confluence.Support { namespace Greenshot.Plugin.Confluence.Support
public class TranslationManager { {
public class TranslationManager
{
private static TranslationManager _translationManager; private static TranslationManager _translationManager;
public event EventHandler LanguageChanged; public event EventHandler LanguageChanged;
@ -29,11 +31,14 @@ namespace Greenshot.Plugin.Confluence.Support {
public ITranslationProvider TranslationProvider { get; set; } public ITranslationProvider TranslationProvider { get; set; }
public object Translate(string key) { public object Translate(string key)
{
object translatedValue = TranslationProvider?.Translate(key); object translatedValue = TranslationProvider?.Translate(key);
if( translatedValue != null) { if (translatedValue != null)
{
return translatedValue; return translatedValue;
} }
return $"!{key}!"; return $"!{key}!";
} }
} }

View file

@ -25,12 +25,16 @@ using GreenshotPlugin.Core;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
namespace Greenshot.Plugin.Dropbox { namespace Greenshot.Plugin.Dropbox
internal class DropboxDestination : AbstractDestination { {
internal class DropboxDestination : AbstractDestination
{
private static readonly DropboxPluginConfiguration DropboxConfig = IniConfig.GetIniSection<DropboxPluginConfiguration>(); private static readonly DropboxPluginConfiguration DropboxConfig = IniConfig.GetIniSection<DropboxPluginConfiguration>();
private readonly DropboxPlugin _plugin; private readonly DropboxPlugin _plugin;
public DropboxDestination(DropboxPlugin plugin) {
public DropboxDestination(DropboxPlugin plugin)
{
_plugin = plugin; _plugin = plugin;
} }
@ -38,23 +42,29 @@ namespace Greenshot.Plugin.Dropbox {
public override string Description => Language.GetString("dropbox", LangKey.upload_menu_item); public override string Description => Language.GetString("dropbox", LangKey.upload_menu_item);
public override Image DisplayIcon { public override Image DisplayIcon
get { {
get
{
ComponentResourceManager resources = new ComponentResourceManager(typeof(DropboxPlugin)); ComponentResourceManager resources = new ComponentResourceManager(typeof(DropboxPlugin));
return (Image)resources.GetObject("Dropbox"); return (Image) resources.GetObject("Dropbox");
} }
} }
public override ExportInformation ExportCapture(bool manually, ISurface surface, ICaptureDetails captureDetails) { public override ExportInformation ExportCapture(bool manually, ISurface surface, ICaptureDetails captureDetails)
{
ExportInformation exportInformation = new ExportInformation(Designation, Description); ExportInformation exportInformation = new ExportInformation(Designation, Description);
bool uploaded = _plugin.Upload(captureDetails, surface, out var uploadUrl); bool uploaded = _plugin.Upload(captureDetails, surface, out var uploadUrl);
if (uploaded) { if (uploaded)
{
exportInformation.Uri = uploadUrl; exportInformation.Uri = uploadUrl;
exportInformation.ExportMade = true; exportInformation.ExportMade = true;
if (DropboxConfig.AfterUploadLinkToClipBoard) { if (DropboxConfig.AfterUploadLinkToClipBoard)
{
ClipboardHelper.SetClipboardData(uploadUrl); ClipboardHelper.SetClipboardData(uploadUrl);
} }
} }
ProcessExport(exportInformation, surface); ProcessExport(exportInformation, surface);
return exportInformation; return exportInformation;
} }

View file

@ -29,18 +29,21 @@ using GreenshotPlugin.IniFile;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin; using GreenshotPlugin.Interfaces.Plugin;
namespace Greenshot.Plugin.Dropbox { namespace Greenshot.Plugin.Dropbox
{
/// <summary> /// <summary>
/// This is the Dropbox base code /// This is the Dropbox base code
/// </summary> /// </summary>
[Plugin("Dropbox", true)] [Plugin("Dropbox", true)]
public class DropboxPlugin : IGreenshotPlugin { public class DropboxPlugin : IGreenshotPlugin
{
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(DropboxPlugin)); private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(DropboxPlugin));
private static DropboxPluginConfiguration _config; private static DropboxPluginConfiguration _config;
private ComponentResourceManager _resources; private ComponentResourceManager _resources;
private ToolStripMenuItem _itemPlugInConfig; private ToolStripMenuItem _itemPlugInConfig;
public void Dispose() { public void Dispose()
{
Dispose(true); Dispose(true);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
@ -56,8 +59,8 @@ namespace Greenshot.Plugin.Dropbox {
/// <summary> /// <summary>
/// Implementation of the IGreenshotPlugin.Initialize /// Implementation of the IGreenshotPlugin.Initialize
/// </summary> /// </summary>
public bool Initialize() { public bool Initialize()
{
// Register configuration (don't need the configuration itself) // Register configuration (don't need the configuration itself)
_config = IniConfig.GetIniSection<DropboxPluginConfiguration>(); _config = IniConfig.GetIniSection<DropboxPluginConfiguration>();
_resources = new ComponentResourceManager(typeof(DropboxPlugin)); _resources = new ComponentResourceManager(typeof(DropboxPlugin));
@ -65,7 +68,7 @@ namespace Greenshot.Plugin.Dropbox {
_itemPlugInConfig = new ToolStripMenuItem _itemPlugInConfig = new ToolStripMenuItem
{ {
Text = Language.GetString("dropbox", LangKey.Configure), Text = Language.GetString("dropbox", LangKey.Configure),
Image = (Image)_resources.GetObject("Dropbox") Image = (Image) _resources.GetObject("Dropbox")
}; };
_itemPlugInConfig.Click += ConfigMenuClick; _itemPlugInConfig.Click += ConfigMenuClick;
@ -74,44 +77,49 @@ namespace Greenshot.Plugin.Dropbox {
return true; return true;
} }
public void OnLanguageChanged(object sender, EventArgs e) { public void OnLanguageChanged(object sender, EventArgs e)
if (_itemPlugInConfig != null) { {
if (_itemPlugInConfig != null)
{
_itemPlugInConfig.Text = Language.GetString("dropbox", LangKey.Configure); _itemPlugInConfig.Text = Language.GetString("dropbox", LangKey.Configure);
} }
} }
public void Shutdown() { public void Shutdown()
{
Log.Debug("Dropbox Plugin shutdown."); Log.Debug("Dropbox Plugin shutdown.");
} }
/// <summary> /// <summary>
/// Implementation of the IPlugin.Configure /// Implementation of the IPlugin.Configure
/// </summary> /// </summary>
public void Configure() { public void Configure()
{
_config.ShowConfigDialog(); _config.ShowConfigDialog();
} }
public void ConfigMenuClick(object sender, EventArgs eventArgs) { public void ConfigMenuClick(object sender, EventArgs eventArgs)
{
_config.ShowConfigDialog(); _config.ShowConfigDialog();
} }
/// <summary> /// <summary>
/// This will be called when the menu item in the Editor is clicked /// This will be called when the menu item in the Editor is clicked
/// </summary> /// </summary>
public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, out string uploadUrl) { public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, out string uploadUrl)
{
uploadUrl = null; uploadUrl = null;
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, false); SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, false);
try try
{ {
bool result = false; bool result = false;
new PleaseWaitForm().ShowAndWait("Dropbox", Language.GetString("dropbox", LangKey.communication_wait), new PleaseWaitForm().ShowAndWait("Dropbox", Language.GetString("dropbox", LangKey.communication_wait),
delegate delegate { result = DropboxUtils.UploadToDropbox(surfaceToUpload, outputSettings, captureDetails); }
{
result = DropboxUtils.UploadToDropbox(surfaceToUpload, outputSettings, captureDetails);
}
); );
return result; return result;
} catch (Exception e) { }
catch (Exception e)
{
Log.Error(e); Log.Error(e);
MessageBox.Show(Language.GetString("dropbox", LangKey.upload_failure) + " " + e.Message); MessageBox.Show(Language.GetString("dropbox", LangKey.upload_failure) + " " + e.Message);
return false; return false;

View file

@ -25,16 +25,18 @@ using Greenshot.Plugin.Dropbox.Forms;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
namespace Greenshot.Plugin.Dropbox { namespace Greenshot.Plugin.Dropbox
{
/// <summary> /// <summary>
/// Description of ImgurConfiguration. /// Description of ImgurConfiguration.
/// </summary> /// </summary>
[IniSection("Dropbox", Description = "Greenshot Dropbox Plugin configuration")] [IniSection("Dropbox", Description = "Greenshot Dropbox Plugin configuration")]
public class DropboxPluginConfiguration : IniSection { public class DropboxPluginConfiguration : IniSection
[IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")] {
[IniProperty("UploadFormat", Description = "What file type to use for uploading", DefaultValue = "png")]
public OutputFormat UploadFormat { get; set; } public OutputFormat UploadFormat { get; set; }
[IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")] [IniProperty("UploadJpegQuality", Description = "JPEG file save quality in %.", DefaultValue = "80")]
public int UploadJpegQuality { get; set; } public int UploadJpegQuality { get; set; }
[IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send Dropbox link to clipboard.", DefaultValue = "true")] [IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send Dropbox link to clipboard.", DefaultValue = "true")]
@ -57,11 +59,14 @@ namespace Greenshot.Plugin.Dropbox {
/// A form for token /// A form for token
/// </summary> /// </summary>
/// <returns>bool true if OK was pressed, false if cancel</returns> /// <returns>bool true if OK was pressed, false if cancel</returns>
public bool ShowConfigDialog() { public bool ShowConfigDialog()
{
DialogResult result = new SettingsForm().ShowDialog(); DialogResult result = new SettingsForm().ShowDialog();
if (result == DialogResult.OK) { if (result == DialogResult.OK)
{
return true; return true;
} }
return false; return false;
} }
} }

View file

@ -29,15 +29,18 @@ using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin; using GreenshotPlugin.Interfaces.Plugin;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Greenshot.Plugin.Dropbox { namespace Greenshot.Plugin.Dropbox
{
/// <summary> /// <summary>
/// Description of DropboxUtils. /// Description of DropboxUtils.
/// </summary> /// </summary>
public class DropboxUtils { public class DropboxUtils
{
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(DropboxUtils)); private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(DropboxUtils));
private static readonly DropboxPluginConfiguration DropboxConfig = IniConfig.GetIniSection<DropboxPluginConfiguration>(); private static readonly DropboxPluginConfiguration DropboxConfig = IniConfig.GetIniSection<DropboxPluginConfiguration>();
private DropboxUtils() { private DropboxUtils()
{
} }
public static bool UploadToDropbox(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, ICaptureDetails captureDetails) public static bool UploadToDropbox(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, ICaptureDetails captureDetails)
@ -62,13 +65,21 @@ namespace Greenshot.Plugin.Dropbox {
IDictionary<string, object> arguments = new Dictionary<string, object> IDictionary<string, object> arguments = new Dictionary<string, object>
{ {
{ "autorename", true }, {
{ "mute", true }, "autorename", true
{ "path", "/" + filename.Replace(Path.DirectorySeparatorChar, '\\')} },
{
"mute", true
},
{
"path", "/" + filename.Replace(Path.DirectorySeparatorChar, '\\')
}
}; };
IDictionary<string, object> headers = new Dictionary<string, object> IDictionary<string, object> headers = new Dictionary<string, object>
{ {
{ "Dropbox-API-Arg", JsonConvert.SerializeObject(arguments)} {
"Dropbox-API-Arg", JsonConvert.SerializeObject(arguments)
}
}; };
var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, "https://content.dropboxapi.com/2/files/upload", oauth2Settings); var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, "https://content.dropboxapi.com/2/files/upload", oauth2Settings);
@ -78,10 +89,13 @@ namespace Greenshot.Plugin.Dropbox {
var response = JsonConvert.DeserializeObject<IDictionary<string, string>>(responseString); var response = JsonConvert.DeserializeObject<IDictionary<string, string>>(responseString);
return response.ContainsKey("id"); return response.ContainsKey("id");
} }
catch (Exception ex) { catch (Exception ex)
{
Log.Error("Upload error: ", ex); Log.Error("Upload error: ", ex);
throw; throw;
} finally { }
finally
{
DropboxConfig.RefreshToken = oauth2Settings.RefreshToken; DropboxConfig.RefreshToken = oauth2Settings.RefreshToken;
DropboxConfig.AccessToken = oauth2Settings.AccessToken; DropboxConfig.AccessToken = oauth2Settings.AccessToken;
DropboxConfig.AccessTokenExpires = oauth2Settings.AccessTokenExpires; DropboxConfig.AccessTokenExpires = oauth2Settings.AccessTokenExpires;

View file

@ -21,7 +21,9 @@
using GreenshotPlugin.Controls; using GreenshotPlugin.Controls;
namespace Greenshot.Plugin.Dropbox.Forms { namespace Greenshot.Plugin.Dropbox.Forms
public class DropboxForm : GreenshotForm { {
public class DropboxForm : GreenshotForm
{
} }
} }

View file

@ -19,12 +19,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Greenshot.Plugin.Dropbox.Forms { namespace Greenshot.Plugin.Dropbox.Forms
{
/// <summary> /// <summary>
/// Description of PasswordRequestForm. /// Description of PasswordRequestForm.
/// </summary> /// </summary>
public partial class SettingsForm : DropboxForm { public partial class SettingsForm : DropboxForm
public SettingsForm() { {
public SettingsForm()
{
// //
// The InitializeComponent() call is required for Windows Forms designer support. // The InitializeComponent() call is required for Windows Forms designer support.
// //
@ -32,6 +35,5 @@ namespace Greenshot.Plugin.Dropbox.Forms {
AcceptButton = buttonOK; AcceptButton = buttonOK;
CancelButton = buttonCancel; CancelButton = buttonCancel;
} }
} }
} }

View file

@ -18,8 +18,11 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Greenshot.Plugin.Dropbox {
public enum LangKey { namespace Greenshot.Plugin.Dropbox
{
public enum LangKey
{
upload_menu_item, upload_menu_item,
upload_failure, upload_failure,
communication_wait, communication_wait,

View file

@ -25,37 +25,48 @@ using System.IO;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
namespace Greenshot.Plugin.ExternalCommand { namespace Greenshot.Plugin.ExternalCommand
{
/// <summary> /// <summary>
/// Description of FlickrConfiguration. /// Description of FlickrConfiguration.
/// </summary> /// </summary>
[IniSection("ExternalCommand", Description="Greenshot ExternalCommand Plugin configuration")] [IniSection("ExternalCommand", Description = "Greenshot ExternalCommand Plugin configuration")]
public class ExternalCommandConfiguration : IniSection { public class ExternalCommandConfiguration : IniSection
[IniProperty("Commands", Description="The commands that are available.")] {
[IniProperty("Commands", Description = "The commands that are available.")]
public List<string> Commands { get; set; } public List<string> Commands { get; set; }
[IniProperty("RedirectStandardError", Description = "Redirect the standard error of all external commands, used to output as warning to the greenshot.log.", DefaultValue = "true")] [IniProperty("RedirectStandardError", Description = "Redirect the standard error of all external commands, used to output as warning to the greenshot.log.",
DefaultValue = "true")]
public bool RedirectStandardError { get; set; } public bool RedirectStandardError { get; set; }
[IniProperty("RedirectStandardOutput", Description = "Redirect the standard output of all external commands, used for different other functions (more below).", DefaultValue = "true")] [IniProperty("RedirectStandardOutput", Description = "Redirect the standard output of all external commands, used for different other functions (more below).",
DefaultValue = "true")]
public bool RedirectStandardOutput { get; set; } public bool RedirectStandardOutput { get; set; }
[IniProperty("ShowStandardOutputInLog", Description = "Depends on 'RedirectStandardOutput': Show standard output of all external commands to the Greenshot log, this can be usefull for debugging.", DefaultValue = "false")] [IniProperty("ShowStandardOutputInLog",
Description = "Depends on 'RedirectStandardOutput': Show standard output of all external commands to the Greenshot log, this can be usefull for debugging.",
DefaultValue = "false")]
public bool ShowStandardOutputInLog { get; set; } public bool ShowStandardOutputInLog { get; set; }
[IniProperty("ParseForUri", Description = "Depends on 'RedirectStandardOutput': Parse the output and take the first found URI, if a URI is found than clicking on the notify bubble goes there.", DefaultValue = "true")] [IniProperty("ParseForUri",
Description = "Depends on 'RedirectStandardOutput': Parse the output and take the first found URI, if a URI is found than clicking on the notify bubble goes there.",
DefaultValue = "true")]
public bool ParseOutputForUri { get; set; } public bool ParseOutputForUri { get; set; }
[IniProperty("OutputToClipboard", Description = "Depends on 'RedirectStandardOutput': Place the standard output on the clipboard.", DefaultValue = "false")] [IniProperty("OutputToClipboard", Description = "Depends on 'RedirectStandardOutput': Place the standard output on the clipboard.", DefaultValue = "false")]
public bool OutputToClipboard { get; set; } public bool OutputToClipboard { get; set; }
[IniProperty("UriToClipboard", Description = "Depends on 'RedirectStandardOutput' & 'ParseForUri': If an URI is found in the standard input, place it on the clipboard. (This overwrites the output from OutputToClipboard setting.)", DefaultValue = "true")] [IniProperty("UriToClipboard",
Description =
"Depends on 'RedirectStandardOutput' & 'ParseForUri': If an URI is found in the standard input, place it on the clipboard. (This overwrites the output from OutputToClipboard setting.)",
DefaultValue = "true")]
public bool UriToClipboard { get; set; } public bool UriToClipboard { get; set; }
[IniProperty("Commandline", Description="The commandline for the output command.")] [IniProperty("Commandline", Description = "The commandline for the output command.")]
public Dictionary<string, string> Commandline { get; set; } public Dictionary<string, string> Commandline { get; set; }
[IniProperty("Argument", Description="The arguments for the output command.")] [IniProperty("Argument", Description = "The arguments for the output command.")]
public Dictionary<string, string> Argument { get; set; } public Dictionary<string, string> Argument { get; set; }
[IniProperty("RunInbackground", Description = "Should the command be started in the background.")] [IniProperty("RunInbackground", Description = "Should the command be started in the background.")]
@ -71,13 +82,19 @@ namespace Greenshot.Plugin.ExternalCommand {
private const string PaintDotNet = "Paint.NET"; private const string PaintDotNet = "Paint.NET";
private static readonly string PaintDotNetPath; private static readonly string PaintDotNetPath;
private static readonly bool HasPaintDotNet; private static readonly bool HasPaintDotNet;
static ExternalCommandConfiguration() {
try { static ExternalCommandConfiguration()
{
try
{
PaintPath = PluginUtils.GetExePath("pbrush.exe"); PaintPath = PluginUtils.GetExePath("pbrush.exe");
HasPaint = !string.IsNullOrEmpty(PaintPath) && File.Exists(PaintPath); HasPaint = !string.IsNullOrEmpty(PaintPath) && File.Exists(PaintPath);
} catch { }
catch
{
// Ignore // Ignore
} }
try try
{ {
PaintDotNetPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Paint.NET\PaintDotNet.exe"); PaintDotNetPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Paint.NET\PaintDotNet.exe");
@ -99,6 +116,7 @@ namespace Greenshot.Plugin.ExternalCommand {
{ {
return; return;
} }
Commands.Remove(command); Commands.Remove(command);
Commandline.Remove(command); Commandline.Remove(command);
Argument.Remove(command); Argument.Remove(command);

View file

@ -31,45 +31,58 @@ using GreenshotPlugin.IniFile;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin; using GreenshotPlugin.Interfaces.Plugin;
namespace Greenshot.Plugin.ExternalCommand { namespace Greenshot.Plugin.ExternalCommand
{
/// <summary> /// <summary>
/// Description of OCRDestination. /// Description of OCRDestination.
/// </summary> /// </summary>
public class ExternalCommandDestination : AbstractDestination { public class ExternalCommandDestination : AbstractDestination
{
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ExternalCommandDestination)); private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ExternalCommandDestination));
private static readonly Regex URI_REGEXP = new Regex(@"((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)");
private static readonly Regex URI_REGEXP =
new Regex(
@"((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)");
private static readonly ExternalCommandConfiguration config = IniConfig.GetIniSection<ExternalCommandConfiguration>(); private static readonly ExternalCommandConfiguration config = IniConfig.GetIniSection<ExternalCommandConfiguration>();
private readonly string _presetCommand; private readonly string _presetCommand;
public ExternalCommandDestination(string commando) { public ExternalCommandDestination(string commando)
{
_presetCommand = commando; _presetCommand = commando;
} }
public override string Designation => "External " + _presetCommand.Replace(',','_'); public override string Designation => "External " + _presetCommand.Replace(',', '_');
public override string Description => _presetCommand; public override string Description => _presetCommand;
public override IEnumerable<IDestination> DynamicDestinations() { public override IEnumerable<IDestination> DynamicDestinations()
{
yield break; yield break;
} }
public override Image DisplayIcon => IconCache.IconForCommand(_presetCommand); public override Image DisplayIcon => IconCache.IconForCommand(_presetCommand);
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails)
{
ExportInformation exportInformation = new ExportInformation(Designation, Description); ExportInformation exportInformation = new ExportInformation(Designation, Description);
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(); SurfaceOutputSettings outputSettings = new SurfaceOutputSettings();
outputSettings.PreventGreenshotFormat(); outputSettings.PreventGreenshotFormat();
if (_presetCommand != null) { if (_presetCommand != null)
if (!config.RunInbackground.ContainsKey(_presetCommand)) { {
if (!config.RunInbackground.ContainsKey(_presetCommand))
{
config.RunInbackground.Add(_presetCommand, true); config.RunInbackground.Add(_presetCommand, true);
} }
bool runInBackground = config.RunInbackground[_presetCommand]; bool runInBackground = config.RunInbackground[_presetCommand];
string fullPath = captureDetails.Filename ?? ImageOutput.SaveNamedTmpFile(surface, captureDetails, outputSettings); string fullPath = captureDetails.Filename ?? ImageOutput.SaveNamedTmpFile(surface, captureDetails, outputSettings);
string output; string output;
string error; string error;
if (runInBackground) { if (runInBackground)
{
Thread commandThread = new Thread(delegate() Thread commandThread = new Thread(delegate()
{ {
CallExternalCommand(exportInformation, fullPath, out output, out error); CallExternalCommand(exportInformation, fullPath, out output, out error);
@ -82,11 +95,14 @@ namespace Greenshot.Plugin.ExternalCommand {
commandThread.SetApartmentState(ApartmentState.STA); commandThread.SetApartmentState(ApartmentState.STA);
commandThread.Start(); commandThread.Start();
exportInformation.ExportMade = true; exportInformation.ExportMade = true;
} else { }
else
{
CallExternalCommand(exportInformation, fullPath, out output, out error); CallExternalCommand(exportInformation, fullPath, out output, out error);
ProcessExport(exportInformation, surface); ProcessExport(exportInformation, surface);
} }
} }
return exportInformation; return exportInformation;
} }
@ -98,32 +114,44 @@ namespace Greenshot.Plugin.ExternalCommand {
/// <param name="fullPath"></param> /// <param name="fullPath"></param>
/// <param name="output"></param> /// <param name="output"></param>
/// <param name="error"></param> /// <param name="error"></param>
private void CallExternalCommand(ExportInformation exportInformation, string fullPath, out string output, out string error) { private void CallExternalCommand(ExportInformation exportInformation, string fullPath, out string output, out string error)
{
output = null; output = null;
error = null; error = null;
try { try
if (CallExternalCommand(_presetCommand, fullPath, out output, out error) == 0) { {
if (CallExternalCommand(_presetCommand, fullPath, out output, out error) == 0)
{
exportInformation.ExportMade = true; exportInformation.ExportMade = true;
if (!string.IsNullOrEmpty(output)) { if (!string.IsNullOrEmpty(output))
{
MatchCollection uriMatches = URI_REGEXP.Matches(output); MatchCollection uriMatches = URI_REGEXP.Matches(output);
// Place output on the clipboard before the URI, so if one is found this overwrites // Place output on the clipboard before the URI, so if one is found this overwrites
if (config.OutputToClipboard) { if (config.OutputToClipboard)
{
ClipboardHelper.SetClipboardData(output); ClipboardHelper.SetClipboardData(output);
} }
if (uriMatches.Count > 0) {
if (uriMatches.Count > 0)
{
exportInformation.Uri = uriMatches[0].Groups[1].Value; exportInformation.Uri = uriMatches[0].Groups[1].Value;
LOG.InfoFormat("Got URI : {0} ", exportInformation.Uri); LOG.InfoFormat("Got URI : {0} ", exportInformation.Uri);
if (config.UriToClipboard) { if (config.UriToClipboard)
{
ClipboardHelper.SetClipboardData(exportInformation.Uri); ClipboardHelper.SetClipboardData(exportInformation.Uri);
} }
} }
} }
} else { }
else
{
LOG.WarnFormat("Error calling external command: {0} ", output); LOG.WarnFormat("Error calling external command: {0} ", output);
exportInformation.ExportMade = false; exportInformation.ExportMade = false;
exportInformation.ErrorMessage = error; exportInformation.ErrorMessage = error;
} }
} catch (Exception ex) { }
catch (Exception ex)
{
exportInformation.ExportMade = false; exportInformation.ExportMade = false;
exportInformation.ErrorMessage = ex.Message; exportInformation.ErrorMessage = ex.Message;
LOG.WarnFormat("Error calling external command: {0} ", exportInformation.ErrorMessage); LOG.WarnFormat("Error calling external command: {0} ", exportInformation.ErrorMessage);
@ -138,18 +166,27 @@ namespace Greenshot.Plugin.ExternalCommand {
/// <param name="output"></param> /// <param name="output"></param>
/// <param name="error"></param> /// <param name="error"></param>
/// <returns></returns> /// <returns></returns>
private int CallExternalCommand(string commando, string fullPath, out string output, out string error) { private int CallExternalCommand(string commando, string fullPath, out string output, out string error)
try { {
try
{
return CallExternalCommand(commando, fullPath, null, out output, out error); return CallExternalCommand(commando, fullPath, null, out output, out error);
} catch (Win32Exception w32Ex) { }
try { catch (Win32Exception w32Ex)
{
try
{
return CallExternalCommand(commando, fullPath, "runas", out output, out error); return CallExternalCommand(commando, fullPath, "runas", out output, out error);
} catch { }
catch
{
w32Ex.Data.Add("commandline", config.Commandline[_presetCommand]); w32Ex.Data.Add("commandline", config.Commandline[_presetCommand]);
w32Ex.Data.Add("arguments", config.Argument[_presetCommand]); w32Ex.Data.Add("arguments", config.Argument[_presetCommand]);
throw; throw;
} }
} catch (Exception ex) { }
catch (Exception ex)
{
ex.Data.Add("commandline", config.Commandline[_presetCommand]); ex.Data.Add("commandline", config.Commandline[_presetCommand]);
ex.Data.Add("arguments", config.Argument[_presetCommand]); ex.Data.Add("arguments", config.Argument[_presetCommand]);
throw; throw;
@ -165,7 +202,8 @@ namespace Greenshot.Plugin.ExternalCommand {
/// <param name="output"></param> /// <param name="output"></param>
/// <param name="error"></param> /// <param name="error"></param>
/// <returns></returns> /// <returns></returns>
private int CallExternalCommand(string commando, string fullPath, string verb, out string output, out string error) { private int CallExternalCommand(string commando, string fullPath, string verb, out string output, out string error)
{
string commandline = config.Commandline[commando]; string commandline = config.Commandline[commando];
string arguments = config.Argument[commando]; string arguments = config.Argument[commando];
output = null; output = null;
@ -183,33 +221,46 @@ namespace Greenshot.Plugin.ExternalCommand {
process.StartInfo.FileName = FilenameHelper.FillCmdVariables(commandline, true); process.StartInfo.FileName = FilenameHelper.FillCmdVariables(commandline, true);
process.StartInfo.Arguments = FormatArguments(arguments, fullPath); process.StartInfo.Arguments = FormatArguments(arguments, fullPath);
process.StartInfo.UseShellExecute = false; process.StartInfo.UseShellExecute = false;
if (config.RedirectStandardOutput) { if (config.RedirectStandardOutput)
{
process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardOutput = true;
} }
if (config.RedirectStandardError) {
if (config.RedirectStandardError)
{
process.StartInfo.RedirectStandardError = true; process.StartInfo.RedirectStandardError = true;
} }
if (verb != null) {
if (verb != null)
{
process.StartInfo.Verb = verb; process.StartInfo.Verb = verb;
} }
LOG.InfoFormat("Starting : {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); LOG.InfoFormat("Starting : {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
process.Start(); process.Start();
process.WaitForExit(); process.WaitForExit();
if (config.RedirectStandardOutput) { if (config.RedirectStandardOutput)
{
output = process.StandardOutput.ReadToEnd(); output = process.StandardOutput.ReadToEnd();
if (config.ShowStandardOutputInLog && output.Trim().Length > 0) { if (config.ShowStandardOutputInLog && output.Trim().Length > 0)
{
LOG.InfoFormat("Output:\n{0}", output); LOG.InfoFormat("Output:\n{0}", output);
} }
} }
if (config.RedirectStandardError) {
if (config.RedirectStandardError)
{
error = process.StandardError.ReadToEnd(); error = process.StandardError.ReadToEnd();
if (error.Trim().Length > 0) { if (error.Trim().Length > 0)
{
LOG.WarnFormat("Error:\n{0}", error); LOG.WarnFormat("Error:\n{0}", error);
} }
} }
LOG.InfoFormat("Finished : {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); LOG.InfoFormat("Finished : {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
return process.ExitCode; return process.ExitCode;
} }
return -1; return -1;
} }

View file

@ -21,10 +21,12 @@
using GreenshotPlugin.Controls; using GreenshotPlugin.Controls;
namespace Greenshot.Plugin.ExternalCommand { namespace Greenshot.Plugin.ExternalCommand
{
/// <summary> /// <summary>
/// This class is needed for design-time resolving of the language files /// This class is needed for design-time resolving of the language files
/// </summary> /// </summary>
public class ExternalCommandForm : GreenshotForm { public class ExternalCommandForm : GreenshotForm
{
} }
} }

View file

@ -55,6 +55,7 @@ namespace Greenshot.Plugin.ExternalCommand
_itemPlugInRoot.Dispose(); _itemPlugInRoot.Dispose();
_itemPlugInRoot = null; _itemPlugInRoot = null;
} }
private IEnumerable<IDestination> Destinations() private IEnumerable<IDestination> Destinations()
{ {
foreach (string command in ExternalCommandConfig.Commands) foreach (string command in ExternalCommandConfig.Commands)
@ -77,17 +78,20 @@ namespace Greenshot.Plugin.ExternalCommand
// Fix it // Fix it
ExternalCommandConfig.RunInbackground.Add(command, true); ExternalCommandConfig.RunInbackground.Add(command, true);
} }
if (!ExternalCommandConfig.Argument.ContainsKey(command)) if (!ExternalCommandConfig.Argument.ContainsKey(command))
{ {
Log.WarnFormat("Found missing argument for {0}", command); Log.WarnFormat("Found missing argument for {0}", command);
// Fix it // Fix it
ExternalCommandConfig.Argument.Add(command, "{0}"); ExternalCommandConfig.Argument.Add(command, "{0}");
} }
if (!ExternalCommandConfig.Commandline.ContainsKey(command)) if (!ExternalCommandConfig.Commandline.ContainsKey(command))
{ {
Log.WarnFormat("Found missing commandline for {0}", command); Log.WarnFormat("Found missing commandline for {0}", command);
return false; return false;
} }
string commandline = FilenameHelper.FillVariables(ExternalCommandConfig.Commandline[command], true); string commandline = FilenameHelper.FillVariables(ExternalCommandConfig.Commandline[command], true);
commandline = FilenameHelper.FillCmdVariables(commandline, true); commandline = FilenameHelper.FillCmdVariables(commandline, true);
@ -96,8 +100,10 @@ namespace Greenshot.Plugin.ExternalCommand
Log.WarnFormat("Found 'invalid' commandline {0} for command {1}", ExternalCommandConfig.Commandline[command], command); Log.WarnFormat("Found 'invalid' commandline {0} for command {1}", ExternalCommandConfig.Commandline[command], command);
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Implementation of the IGreenshotPlugin.Initialize /// Implementation of the IGreenshotPlugin.Initialize
/// </summary> /// </summary>
@ -114,11 +120,13 @@ namespace Greenshot.Plugin.ExternalCommand
commandsToDelete.Add(command); commandsToDelete.Add(command);
} }
} }
// cleanup // cleanup
foreach (string command in commandsToDelete) foreach (string command in commandsToDelete)
{ {
ExternalCommandConfig.Delete(command); ExternalCommandConfig.Delete(command);
} }
SimpleServiceProvider.Current.AddService(Destinations()); SimpleServiceProvider.Current.AddService(Destinations());
_itemPlugInRoot = new ToolStripMenuItem(); _itemPlugInRoot = new ToolStripMenuItem();

View file

@ -25,22 +25,31 @@ using System.IO;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
namespace Greenshot.Plugin.ExternalCommand { namespace Greenshot.Plugin.ExternalCommand
public static class IconCache { {
public static class IconCache
{
private static readonly ExternalCommandConfiguration config = IniConfig.GetIniSection<ExternalCommandConfiguration>(); private static readonly ExternalCommandConfiguration config = IniConfig.GetIniSection<ExternalCommandConfiguration>();
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(IconCache)); private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(IconCache));
public static Image IconForCommand(string commandName) { public static Image IconForCommand(string commandName)
{
Image icon = null; Image icon = null;
if (commandName != null) { if (commandName != null)
if (config.Commandline.ContainsKey(commandName) && File.Exists(config.Commandline[commandName])) { {
try { if (config.Commandline.ContainsKey(commandName) && File.Exists(config.Commandline[commandName]))
{
try
{
icon = PluginUtils.GetCachedExeIcon(config.Commandline[commandName], 0); icon = PluginUtils.GetCachedExeIcon(config.Commandline[commandName], 0);
} catch (Exception ex) { }
catch (Exception ex)
{
LOG.Warn("Problem loading icon for " + config.Commandline[commandName], ex); LOG.Warn("Problem loading icon for " + config.Commandline[commandName], ex);
} }
} }
} }
return icon; return icon;
} }
} }

View file

@ -24,14 +24,17 @@ using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
namespace Greenshot.Plugin.ExternalCommand { namespace Greenshot.Plugin.ExternalCommand
{
/// <summary> /// <summary>
/// Description of SettingsForm. /// Description of SettingsForm.
/// </summary> /// </summary>
public partial class SettingsForm : ExternalCommandForm { public partial class SettingsForm : ExternalCommandForm
{
private static readonly ExternalCommandConfiguration ExternalCommandConfig = IniConfig.GetIniSection<ExternalCommandConfiguration>(); private static readonly ExternalCommandConfiguration ExternalCommandConfig = IniConfig.GetIniSection<ExternalCommandConfiguration>();
public SettingsForm() { public SettingsForm()
{
// //
// The InitializeComponent() call is required for Windows Forms designer support. // The InitializeComponent() call is required for Windows Forms designer support.
// //
@ -41,65 +44,83 @@ namespace Greenshot.Plugin.ExternalCommand {
UpdateView(); UpdateView();
} }
private void ButtonOkClick(object sender, EventArgs e) { private void ButtonOkClick(object sender, EventArgs e)
{
IniConfig.Save(); IniConfig.Save();
} }
private void ButtonAddClick(object sender, EventArgs e) { private void ButtonAddClick(object sender, EventArgs e)
{
var form = new SettingsFormDetail(null); var form = new SettingsFormDetail(null);
form.ShowDialog(); form.ShowDialog();
UpdateView(); UpdateView();
} }
private void ButtonDeleteClick(object sender, EventArgs e) { private void ButtonDeleteClick(object sender, EventArgs e)
foreach(ListViewItem item in listView1.SelectedItems) { {
foreach (ListViewItem item in listView1.SelectedItems)
{
string commando = item.Tag as string; string commando = item.Tag as string;
ExternalCommandConfig.Delete(commando); ExternalCommandConfig.Delete(commando);
} }
UpdateView(); UpdateView();
} }
private void UpdateView() { private void UpdateView()
{
listView1.Items.Clear(); listView1.Items.Clear();
if(ExternalCommandConfig.Commands != null) { if (ExternalCommandConfig.Commands != null)
{
listView1.ListViewItemSorter = new ListviewComparer(); listView1.ListViewItemSorter = new ListviewComparer();
ImageList imageList = new ImageList(); ImageList imageList = new ImageList();
listView1.SmallImageList = imageList; listView1.SmallImageList = imageList;
int imageNr = 0; int imageNr = 0;
foreach(string commando in ExternalCommandConfig.Commands) { foreach (string commando in ExternalCommandConfig.Commands)
{
ListViewItem item; ListViewItem item;
Image iconForExe = IconCache.IconForCommand(commando); Image iconForExe = IconCache.IconForCommand(commando);
if(iconForExe != null) { if (iconForExe != null)
{
imageList.Images.Add(iconForExe); imageList.Images.Add(iconForExe);
item = new ListViewItem(commando, imageNr++); item = new ListViewItem(commando, imageNr++);
} else { }
else
{
item = new ListViewItem(commando); item = new ListViewItem(commando);
} }
item.Tag = commando; item.Tag = commando;
listView1.Items.Add(item); listView1.Items.Add(item);
} }
} }
// Fix for bug #1484, getting an ArgumentOutOfRangeException as there is nothing selected but the edit button was still active. // Fix for bug #1484, getting an ArgumentOutOfRangeException as there is nothing selected but the edit button was still active.
button_edit.Enabled = listView1.SelectedItems.Count > 0; button_edit.Enabled = listView1.SelectedItems.Count > 0;
} }
private void ListView1ItemSelectionChanged(object sender, EventArgs e) { private void ListView1ItemSelectionChanged(object sender, EventArgs e)
{
button_edit.Enabled = listView1.SelectedItems.Count > 0; button_edit.Enabled = listView1.SelectedItems.Count > 0;
} }
private void ButtonEditClick(object sender, EventArgs e) { private void ButtonEditClick(object sender, EventArgs e)
{
ListView1DoubleClick(sender, e); ListView1DoubleClick(sender, e);
} }
private void ListView1DoubleClick(object sender, EventArgs e) { private void ListView1DoubleClick(object sender, EventArgs e)
{
// Safety check for bug #1484 // Safety check for bug #1484
bool selectionActive = listView1.SelectedItems.Count > 0; bool selectionActive = listView1.SelectedItems.Count > 0;
if(!selectionActive) { if (!selectionActive)
{
button_edit.Enabled = false; button_edit.Enabled = false;
return; return;
} }
string commando = listView1.SelectedItems[0].Tag as string; string commando = listView1.SelectedItems[0].Tag as string;
var form = new SettingsFormDetail(commando); var form = new SettingsFormDetail(commando);
@ -109,17 +130,22 @@ namespace Greenshot.Plugin.ExternalCommand {
} }
} }
public class ListviewComparer : System.Collections.IComparer { public class ListviewComparer : System.Collections.IComparer
public int Compare(object x, object y) { {
if(!(x is ListViewItem)) { public int Compare(object x, object y)
return (0); {
} if (!(x is ListViewItem))
if(!(y is ListViewItem)) { {
return (0); return (0);
} }
var l1 = (ListViewItem)x; if (!(y is ListViewItem))
var l2 = (ListViewItem)y; {
return (0);
}
var l1 = (ListViewItem) x;
var l2 = (ListViewItem) y;
return string.Compare(l1.Text, l2.Text, StringComparison.Ordinal); return string.Compare(l1.Text, l2.Text, StringComparison.Ordinal);
} }
} }

View file

@ -26,52 +26,64 @@ using System.Windows.Forms;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
namespace Greenshot.Plugin.ExternalCommand { namespace Greenshot.Plugin.ExternalCommand
{
/// <summary> /// <summary>
/// Description of SettingsFormDetail. /// Description of SettingsFormDetail.
/// </summary> /// </summary>
public partial class SettingsFormDetail : ExternalCommandForm { public partial class SettingsFormDetail : ExternalCommandForm
{
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(SettingsFormDetail)); private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(SettingsFormDetail));
private static readonly ExternalCommandConfiguration ExternalCommandConfig = IniConfig.GetIniSection<ExternalCommandConfiguration>(); private static readonly ExternalCommandConfiguration ExternalCommandConfig = IniConfig.GetIniSection<ExternalCommandConfiguration>();
private readonly string _commando; private readonly string _commando;
private readonly int _commandIndex; private readonly int _commandIndex;
public SettingsFormDetail(string commando) { public SettingsFormDetail(string commando)
{
InitializeComponent(); InitializeComponent();
AcceptButton = buttonOk; AcceptButton = buttonOk;
CancelButton = buttonCancel; CancelButton = buttonCancel;
_commando = commando; _commando = commando;
if(commando != null) { if (commando != null)
{
textBox_name.Text = commando; textBox_name.Text = commando;
textBox_commandline.Text = ExternalCommandConfig.Commandline[commando]; textBox_commandline.Text = ExternalCommandConfig.Commandline[commando];
textBox_arguments.Text = ExternalCommandConfig.Argument[commando]; textBox_arguments.Text = ExternalCommandConfig.Argument[commando];
_commandIndex = ExternalCommandConfig.Commands.FindIndex(s => s == commando); _commandIndex = ExternalCommandConfig.Commands.FindIndex(s => s == commando);
} else { }
else
{
textBox_arguments.Text = "\"{0}\""; textBox_arguments.Text = "\"{0}\"";
} }
OkButtonState(); OkButtonState();
} }
private void ButtonOkClick(object sender, EventArgs e) { private void ButtonOkClick(object sender, EventArgs e)
{
string commandName = textBox_name.Text; string commandName = textBox_name.Text;
string commandLine = textBox_commandline.Text; string commandLine = textBox_commandline.Text;
string arguments = textBox_arguments.Text; string arguments = textBox_arguments.Text;
if(_commando != null) { if (_commando != null)
{
ExternalCommandConfig.Commands[_commandIndex] = commandName; ExternalCommandConfig.Commands[_commandIndex] = commandName;
ExternalCommandConfig.Commandline.Remove(_commando); ExternalCommandConfig.Commandline.Remove(_commando);
ExternalCommandConfig.Commandline.Add(commandName, commandLine); ExternalCommandConfig.Commandline.Add(commandName, commandLine);
ExternalCommandConfig.Argument.Remove(_commando); ExternalCommandConfig.Argument.Remove(_commando);
ExternalCommandConfig.Argument.Add(commandName, arguments); ExternalCommandConfig.Argument.Add(commandName, arguments);
} else { }
else
{
ExternalCommandConfig.Commands.Add(commandName); ExternalCommandConfig.Commands.Add(commandName);
ExternalCommandConfig.Commandline.Add(commandName, commandLine); ExternalCommandConfig.Commandline.Add(commandName, commandLine);
ExternalCommandConfig.Argument.Add(commandName, arguments); ExternalCommandConfig.Argument.Add(commandName, arguments);
} }
} }
private void Button3Click(object sender, EventArgs e) { private void Button3Click(object sender, EventArgs e)
{
var openFileDialog = new OpenFileDialog var openFileDialog = new OpenFileDialog
{ {
Filter = "Executables (*.exe, *.bat, *.com)|*.exe; *.bat; *.com|All files (*)|*", Filter = "Executables (*.exe, *.bat, *.com)|*.exe; *.bat; *.com|All files (*)|*",
@ -89,35 +101,47 @@ namespace Greenshot.Plugin.ExternalCommand {
Log.WarnFormat("Can't get the initial path via {0}", textBox_commandline.Text); Log.WarnFormat("Can't get the initial path via {0}", textBox_commandline.Text);
Log.Warn("Exception: ", ex); Log.Warn("Exception: ", ex);
} }
if(initialPath != null && Directory.Exists(initialPath)) {
if (initialPath != null && Directory.Exists(initialPath))
{
openFileDialog.InitialDirectory = initialPath; openFileDialog.InitialDirectory = initialPath;
} else { }
else
{
initialPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); initialPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
openFileDialog.InitialDirectory = initialPath; openFileDialog.InitialDirectory = initialPath;
} }
Log.DebugFormat("Starting OpenFileDialog at {0}", initialPath); Log.DebugFormat("Starting OpenFileDialog at {0}", initialPath);
if(openFileDialog.ShowDialog() == DialogResult.OK) { if (openFileDialog.ShowDialog() == DialogResult.OK)
{
textBox_commandline.Text = openFileDialog.FileName; textBox_commandline.Text = openFileDialog.FileName;
} }
} }
private void OkButtonState() { private void OkButtonState()
{
// Assume OK // Assume OK
buttonOk.Enabled = true; buttonOk.Enabled = true;
textBox_name.BackColor = Color.White; textBox_name.BackColor = Color.White;
textBox_commandline.BackColor = Color.White; textBox_commandline.BackColor = Color.White;
textBox_arguments.BackColor = Color.White; textBox_arguments.BackColor = Color.White;
// Is there a text in the name field // Is there a text in the name field
if(string.IsNullOrEmpty(textBox_name.Text)) { if (string.IsNullOrEmpty(textBox_name.Text))
{
buttonOk.Enabled = false; buttonOk.Enabled = false;
} }
// Check if commandname is unique // Check if commandname is unique
if(_commando == null && !string.IsNullOrEmpty(textBox_name.Text) && ExternalCommandConfig.Commands.Contains(textBox_name.Text)) { if (_commando == null && !string.IsNullOrEmpty(textBox_name.Text) && ExternalCommandConfig.Commands.Contains(textBox_name.Text))
{
buttonOk.Enabled = false; buttonOk.Enabled = false;
textBox_name.BackColor = Color.Red; textBox_name.BackColor = Color.Red;
} }
// Is there a text in the commandline field // Is there a text in the commandline field
if(string.IsNullOrEmpty(textBox_commandline.Text)) { if (string.IsNullOrEmpty(textBox_commandline.Text))
{
buttonOk.Enabled = false; buttonOk.Enabled = false;
} }
@ -134,6 +158,7 @@ namespace Greenshot.Plugin.ExternalCommand {
textBox_commandline.BackColor = Color.Red; textBox_commandline.BackColor = Color.Red;
} }
} }
// Are the arguments in a valid format? // Are the arguments in a valid format?
try try
{ {
@ -149,11 +174,13 @@ namespace Greenshot.Plugin.ExternalCommand {
} }
} }
private void textBox_name_TextChanged(object sender, EventArgs e) { private void textBox_name_TextChanged(object sender, EventArgs e)
{
OkButtonState(); OkButtonState();
} }
private void textBox_commandline_TextChanged(object sender, EventArgs e) { private void textBox_commandline_TextChanged(object sender, EventArgs e)
{
OkButtonState(); OkButtonState();
} }
@ -161,6 +188,5 @@ namespace Greenshot.Plugin.ExternalCommand {
{ {
OkButtonState(); OkButtonState();
} }
} }
} }

View file

@ -24,17 +24,21 @@ using Greenshot.Plugin.Flickr.Forms;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
namespace Greenshot.Plugin.Flickr { namespace Greenshot.Plugin.Flickr
public enum SafetyLevel { {
public enum SafetyLevel
{
Safe = 1, Safe = 1,
Moderate = 2, Moderate = 2,
Restricted = 3 Restricted = 3
} }
/// <summary> /// <summary>
/// Description of FlickrConfiguration. /// Description of FlickrConfiguration.
/// </summary> /// </summary>
[IniSection("Flickr", Description = "Greenshot Flickr Plugin configuration")] [IniSection("Flickr", Description = "Greenshot Flickr Plugin configuration")]
public class FlickrConfiguration : IniSection { public class FlickrConfiguration : IniSection
{
[IniProperty("flickrIsPublic", Description = "IsPublic.", DefaultValue = "true")] [IniProperty("flickrIsPublic", Description = "IsPublic.", DefaultValue = "true")]
public bool IsPublic { get; set; } public bool IsPublic { get; set; }
@ -50,10 +54,10 @@ namespace Greenshot.Plugin.Flickr {
[IniProperty("HiddenFromSearch", Description = "Hidden from search", DefaultValue = "false")] [IniProperty("HiddenFromSearch", Description = "Hidden from search", DefaultValue = "false")]
public bool HiddenFromSearch { get; set; } public bool HiddenFromSearch { get; set; }
[IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")] [IniProperty("UploadFormat", Description = "What file type to use for uploading", DefaultValue = "png")]
public OutputFormat UploadFormat { get; set; } public OutputFormat UploadFormat { get; set; }
[IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")] [IniProperty("UploadJpegQuality", Description = "JPEG file save quality in %.", DefaultValue = "80")]
public int UploadJpegQuality { get; set; } public int UploadJpegQuality { get; set; }
[IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send flickr link to clipboard.", DefaultValue = "true")] [IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send flickr link to clipboard.", DefaultValue = "true")]
@ -64,6 +68,7 @@ namespace Greenshot.Plugin.Flickr {
[IniProperty("FlickrToken", Description = "The Flickr token", Encrypted = true, ExcludeIfNull = true)] [IniProperty("FlickrToken", Description = "The Flickr token", Encrypted = true, ExcludeIfNull = true)]
public string FlickrToken { get; set; } public string FlickrToken { get; set; }
[IniProperty("FlickrTokenSecret", Description = "The Flickr token secret", Encrypted = true, ExcludeIfNull = true)] [IniProperty("FlickrTokenSecret", Description = "The Flickr token secret", Encrypted = true, ExcludeIfNull = true)]
public string FlickrTokenSecret { get; set; } public string FlickrTokenSecret { get; set; }
@ -71,11 +76,14 @@ namespace Greenshot.Plugin.Flickr {
/// A form for token /// A form for token
/// </summary> /// </summary>
/// <returns>bool true if OK was pressed, false if cancel</returns> /// <returns>bool true if OK was pressed, false if cancel</returns>
public bool ShowConfigDialog() { public bool ShowConfigDialog()
{
DialogResult result = new SettingsForm().ShowDialog(); DialogResult result = new SettingsForm().ShowDialog();
if (result == DialogResult.OK) { if (result == DialogResult.OK)
{
return true; return true;
} }
return false; return false;
} }
} }

View file

@ -24,10 +24,14 @@ using System.Drawing;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
namespace Greenshot.Plugin.Flickr { namespace Greenshot.Plugin.Flickr
public class FlickrDestination : AbstractDestination { {
public class FlickrDestination : AbstractDestination
{
private readonly FlickrPlugin _plugin; private readonly FlickrPlugin _plugin;
public FlickrDestination(FlickrPlugin plugin) {
public FlickrDestination(FlickrPlugin plugin)
{
_plugin = plugin; _plugin = plugin;
} }
@ -35,20 +39,25 @@ namespace Greenshot.Plugin.Flickr {
public override string Description => Language.GetString("flickr", LangKey.upload_menu_item); public override string Description => Language.GetString("flickr", LangKey.upload_menu_item);
public override Image DisplayIcon { public override Image DisplayIcon
get { {
get
{
ComponentResourceManager resources = new ComponentResourceManager(typeof(FlickrPlugin)); ComponentResourceManager resources = new ComponentResourceManager(typeof(FlickrPlugin));
return (Image)resources.GetObject("flickr"); return (Image) resources.GetObject("flickr");
} }
} }
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails)
{
ExportInformation exportInformation = new ExportInformation(Designation, Description); ExportInformation exportInformation = new ExportInformation(Designation, Description);
bool uploaded = _plugin.Upload(captureDetails, surface, out var uploadUrl); bool uploaded = _plugin.Upload(captureDetails, surface, out var uploadUrl);
if (uploaded) { if (uploaded)
{
exportInformation.ExportMade = true; exportInformation.ExportMade = true;
exportInformation.Uri = uploadUrl; exportInformation.Uri = uploadUrl;
} }
ProcessExport(exportInformation, surface); ProcessExport(exportInformation, surface);
return exportInformation; return exportInformation;
} }

View file

@ -37,24 +37,31 @@ namespace Greenshot.Plugin.Flickr
/// This is the Flickr base code /// This is the Flickr base code
/// </summary> /// </summary>
[Plugin("Flickr", true)] [Plugin("Flickr", true)]
public class FlickrPlugin : IGreenshotPlugin { public class FlickrPlugin : IGreenshotPlugin
{
private static readonly ILog Log = LogManager.GetLogger(typeof(FlickrPlugin)); private static readonly ILog Log = LogManager.GetLogger(typeof(FlickrPlugin));
private static FlickrConfiguration _config; private static FlickrConfiguration _config;
private ComponentResourceManager _resources; private ComponentResourceManager _resources;
private ToolStripMenuItem _itemPlugInConfig; private ToolStripMenuItem _itemPlugInConfig;
public void Dispose() { public void Dispose()
{
Dispose(true); Dispose(true);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
protected void Dispose(bool disposing) { protected void Dispose(bool disposing)
if (!disposing) { {
if (!disposing)
{
return; return;
} }
if (_itemPlugInConfig == null) {
if (_itemPlugInConfig == null)
{
return; return;
} }
_itemPlugInConfig.Dispose(); _itemPlugInConfig.Dispose();
_itemPlugInConfig = null; _itemPlugInConfig = null;
} }
@ -62,7 +69,8 @@ namespace Greenshot.Plugin.Flickr
/// <summary> /// <summary>
/// Implementation of the IGreenshotPlugin.Initialize /// Implementation of the IGreenshotPlugin.Initialize
/// </summary> /// </summary>
public bool Initialize() { public bool Initialize()
{
// Register configuration (don't need the configuration itself) // Register configuration (don't need the configuration itself)
_config = IniConfig.GetIniSection<FlickrConfiguration>(); _config = IniConfig.GetIniSection<FlickrConfiguration>();
_resources = new ComponentResourceManager(typeof(FlickrPlugin)); _resources = new ComponentResourceManager(typeof(FlickrPlugin));
@ -79,52 +87,67 @@ namespace Greenshot.Plugin.Flickr
return true; return true;
} }
public void OnLanguageChanged(object sender, EventArgs e) { public void OnLanguageChanged(object sender, EventArgs e)
if (_itemPlugInConfig != null) { {
if (_itemPlugInConfig != null)
{
_itemPlugInConfig.Text = Language.GetString("flickr", LangKey.Configure); _itemPlugInConfig.Text = Language.GetString("flickr", LangKey.Configure);
} }
} }
public void Shutdown() { public void Shutdown()
{
Log.Debug("Flickr Plugin shutdown."); Log.Debug("Flickr Plugin shutdown.");
} }
/// <summary> /// <summary>
/// Implementation of the IPlugin.Configure /// Implementation of the IPlugin.Configure
/// </summary> /// </summary>
public void Configure() { public void Configure()
{
_config.ShowConfigDialog(); _config.ShowConfigDialog();
} }
public void ConfigMenuClick(object sender, EventArgs eventArgs) { public void ConfigMenuClick(object sender, EventArgs eventArgs)
{
_config.ShowConfigDialog(); _config.ShowConfigDialog();
} }
public bool Upload(ICaptureDetails captureDetails, ISurface surface, out string uploadUrl) { public bool Upload(ICaptureDetails captureDetails, ISurface surface, out string uploadUrl)
{
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, false); SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, false);
uploadUrl = null; uploadUrl = null;
try { try
{
string flickrUrl = null; string flickrUrl = null;
new PleaseWaitForm().ShowAndWait("Flickr", Language.GetString("flickr", LangKey.communication_wait), new PleaseWaitForm().ShowAndWait("Flickr", Language.GetString("flickr", LangKey.communication_wait),
delegate { delegate
{
string filename = Path.GetFileName(FilenameHelper.GetFilename(_config.UploadFormat, captureDetails)); string filename = Path.GetFileName(FilenameHelper.GetFilename(_config.UploadFormat, captureDetails));
flickrUrl = FlickrUtils.UploadToFlickr(surface, outputSettings, captureDetails.Title, filename); flickrUrl = FlickrUtils.UploadToFlickr(surface, outputSettings, captureDetails.Title, filename);
} }
); );
if (flickrUrl == null) { if (flickrUrl == null)
{
return false; return false;
} }
uploadUrl = flickrUrl; uploadUrl = flickrUrl;
if (_config.AfterUploadLinkToClipBoard) { if (_config.AfterUploadLinkToClipBoard)
{
ClipboardHelper.SetClipboardData(flickrUrl); ClipboardHelper.SetClipboardData(flickrUrl);
} }
return true; return true;
} catch (Exception e) { }
catch (Exception e)
{
Log.Error("Error uploading.", e); Log.Error("Error uploading.", e);
MessageBox.Show(Language.GetString("flickr", LangKey.upload_failure) + " " + e.Message); MessageBox.Show(Language.GetString("flickr", LangKey.upload_failure) + " " + e.Message);
} }
return false; return false;
} }
} }

View file

@ -30,21 +30,27 @@ using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin; using GreenshotPlugin.Interfaces.Plugin;
using log4net; using log4net;
namespace Greenshot.Plugin.Flickr { namespace Greenshot.Plugin.Flickr
{
/// <summary> /// <summary>
/// Description of FlickrUtils. /// Description of FlickrUtils.
/// </summary> /// </summary>
public static class FlickrUtils { public static class FlickrUtils
{
private static readonly ILog LOG = LogManager.GetLogger(typeof(FlickrUtils)); private static readonly ILog LOG = LogManager.GetLogger(typeof(FlickrUtils));
private static readonly FlickrConfiguration config = IniConfig.GetIniSection<FlickrConfiguration>(); private static readonly FlickrConfiguration config = IniConfig.GetIniSection<FlickrConfiguration>();
private const string FLICKR_API_BASE_URL = "https://api.flickr.com/services/"; private const string FLICKR_API_BASE_URL = "https://api.flickr.com/services/";
private const string FLICKR_UPLOAD_URL = FLICKR_API_BASE_URL + "upload/"; private const string FLICKR_UPLOAD_URL = FLICKR_API_BASE_URL + "upload/";
// OAUTH // OAUTH
private const string FLICKR_OAUTH_BASE_URL = FLICKR_API_BASE_URL + "oauth/"; private const string FLICKR_OAUTH_BASE_URL = FLICKR_API_BASE_URL + "oauth/";
private const string FLICKR_ACCESS_TOKEN_URL = FLICKR_OAUTH_BASE_URL + "access_token"; private const string FLICKR_ACCESS_TOKEN_URL = FLICKR_OAUTH_BASE_URL + "access_token";
private const string FLICKR_AUTHORIZE_URL = FLICKR_OAUTH_BASE_URL + "authorize"; private const string FLICKR_AUTHORIZE_URL = FLICKR_OAUTH_BASE_URL + "authorize";
private const string FLICKR_REQUEST_TOKEN_URL = FLICKR_OAUTH_BASE_URL + "request_token"; private const string FLICKR_REQUEST_TOKEN_URL = FLICKR_OAUTH_BASE_URL + "request_token";
private const string FLICKR_FARM_URL = "https://farm{0}.staticflickr.com/{1}/{2}_{3}_o.{4}"; private const string FLICKR_FARM_URL = "https://farm{0}.staticflickr.com/{1}/{2}_{3}_o.{4}";
// REST // REST
private const string FLICKR_REST_URL = FLICKR_API_BASE_URL + "rest/"; private const string FLICKR_REST_URL = FLICKR_API_BASE_URL + "rest/";
private const string FLICKR_GET_INFO_URL = FLICKR_REST_URL + "?method=flickr.photos.getInfo"; private const string FLICKR_GET_INFO_URL = FLICKR_REST_URL + "?method=flickr.photos.getInfo";
@ -58,7 +64,8 @@ namespace Greenshot.Plugin.Flickr {
/// <param name="title"></param> /// <param name="title"></param>
/// <param name="filename"></param> /// <param name="filename"></param>
/// <returns>url to image</returns> /// <returns>url to image</returns>
public static string UploadToFlickr(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename) { public static string UploadToFlickr(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename)
{
var oAuth = new OAuthSession(FlickrCredentials.ConsumerKey, FlickrCredentials.ConsumerSecret) var oAuth = new OAuthSession(FlickrCredentials.ConsumerKey, FlickrCredentials.ConsumerSecret)
{ {
BrowserSize = new Size(520, 800), BrowserSize = new Size(520, 800),
@ -70,70 +77,116 @@ namespace Greenshot.Plugin.Flickr {
Token = config.FlickrToken, Token = config.FlickrToken,
TokenSecret = config.FlickrTokenSecret TokenSecret = config.FlickrTokenSecret
}; };
if (string.IsNullOrEmpty(oAuth.Token)) { if (string.IsNullOrEmpty(oAuth.Token))
if (!oAuth.Authorize()) { {
if (!oAuth.Authorize())
{
return null; return null;
} }
if (!string.IsNullOrEmpty(oAuth.Token)) {
if (!string.IsNullOrEmpty(oAuth.Token))
{
config.FlickrToken = oAuth.Token; config.FlickrToken = oAuth.Token;
} }
if (!string.IsNullOrEmpty(oAuth.TokenSecret)) {
if (!string.IsNullOrEmpty(oAuth.TokenSecret))
{
config.FlickrTokenSecret = oAuth.TokenSecret; config.FlickrTokenSecret = oAuth.TokenSecret;
} }
IniConfig.Save(); IniConfig.Save();
} }
try {
try
{
IDictionary<string, object> signedParameters = new Dictionary<string, object> IDictionary<string, object> signedParameters = new Dictionary<string, object>
{ {
{ "content_type", "2" }, // Screenshot {
{ "tags", "Greenshot" }, "content_type", "2"
{ "is_public", config.IsPublic ? "1" : "0" }, }, // Screenshot
{ "is_friend", config.IsFriend ? "1" : "0" }, {
{ "is_family", config.IsFamily ? "1" : "0" }, "tags", "Greenshot"
{ "safety_level", $"{(int)config.SafetyLevel}" }, },
{ "hidden", config.HiddenFromSearch ? "1" : "2" } {
"is_public", config.IsPublic ? "1" : "0"
},
{
"is_friend", config.IsFriend ? "1" : "0"
},
{
"is_family", config.IsFamily ? "1" : "0"
},
{
"safety_level", $"{(int) config.SafetyLevel}"
},
{
"hidden", config.HiddenFromSearch ? "1" : "2"
}
}; };
IDictionary<string, object> otherParameters = new Dictionary<string, object> IDictionary<string, object> otherParameters = new Dictionary<string, object>
{ {
{ "photo", new SurfaceContainer(surfaceToUpload, outputSettings, filename) } {
"photo", new SurfaceContainer(surfaceToUpload, outputSettings, filename)
}
}; };
string response = oAuth.MakeOAuthRequest(HTTPMethod.POST, FLICKR_UPLOAD_URL, signedParameters, otherParameters, null); string response = oAuth.MakeOAuthRequest(HTTPMethod.POST, FLICKR_UPLOAD_URL, signedParameters, otherParameters, null);
string photoId = GetPhotoId(response); string photoId = GetPhotoId(response);
// Get Photo Info // Get Photo Info
signedParameters = new Dictionary<string, object> { { "photo_id", photoId } }; signedParameters = new Dictionary<string, object>
{
{
"photo_id", photoId
}
};
string photoInfo = oAuth.MakeOAuthRequest(HTTPMethod.POST, FLICKR_GET_INFO_URL, signedParameters, null, null); string photoInfo = oAuth.MakeOAuthRequest(HTTPMethod.POST, FLICKR_GET_INFO_URL, signedParameters, null, null);
return GetUrl(photoInfo); return GetUrl(photoInfo);
} catch (Exception ex) { }
catch (Exception ex)
{
LOG.Error("Upload error: ", ex); LOG.Error("Upload error: ", ex);
throw; throw;
} finally { }
if (!string.IsNullOrEmpty(oAuth.Token)) { finally
{
if (!string.IsNullOrEmpty(oAuth.Token))
{
config.FlickrToken = oAuth.Token; config.FlickrToken = oAuth.Token;
} }
if (!string.IsNullOrEmpty(oAuth.TokenSecret)) {
if (!string.IsNullOrEmpty(oAuth.TokenSecret))
{
config.FlickrTokenSecret = oAuth.TokenSecret; config.FlickrTokenSecret = oAuth.TokenSecret;
} }
} }
} }
private static string GetUrl(string response) { private static string GetUrl(string response)
try { {
try
{
XmlDocument doc = new XmlDocument(); XmlDocument doc = new XmlDocument();
doc.LoadXml(response); doc.LoadXml(response);
if (config.UsePageLink) { if (config.UsePageLink)
{
XmlNodeList nodes = doc.GetElementsByTagName("url"); XmlNodeList nodes = doc.GetElementsByTagName("url");
if (nodes.Count > 0) { if (nodes.Count > 0)
{
var xmlNode = nodes.Item(0); var xmlNode = nodes.Item(0);
if (xmlNode != null) { if (xmlNode != null)
{
return xmlNode.InnerText; return xmlNode.InnerText;
} }
} }
} else { }
else
{
XmlNodeList nodes = doc.GetElementsByTagName("photo"); XmlNodeList nodes = doc.GetElementsByTagName("photo");
if (nodes.Count > 0) { if (nodes.Count > 0)
{
var item = nodes.Item(0); var item = nodes.Item(0);
if (item?.Attributes != null) { if (item?.Attributes != null)
{
string farmId = item.Attributes["farm"].Value; string farmId = item.Attributes["farm"].Value;
string serverId = item.Attributes["server"].Value; string serverId = item.Attributes["server"].Value;
string photoId = item.Attributes["id"].Value; string photoId = item.Attributes["id"].Value;
@ -143,26 +196,36 @@ namespace Greenshot.Plugin.Flickr {
} }
} }
} }
} catch (Exception ex) { }
catch (Exception ex)
{
LOG.Error("Error parsing Flickr Response.", ex); LOG.Error("Error parsing Flickr Response.", ex);
} }
return null; return null;
} }
private static string GetPhotoId(string response) { private static string GetPhotoId(string response)
try { {
try
{
XmlDocument doc = new XmlDocument(); XmlDocument doc = new XmlDocument();
doc.LoadXml(response); doc.LoadXml(response);
XmlNodeList nodes = doc.GetElementsByTagName("photoid"); XmlNodeList nodes = doc.GetElementsByTagName("photoid");
if (nodes.Count > 0) { if (nodes.Count > 0)
{
var xmlNode = nodes.Item(0); var xmlNode = nodes.Item(0);
if (xmlNode != null) { if (xmlNode != null)
{
return xmlNode.InnerText; return xmlNode.InnerText;
} }
} }
} catch (Exception ex) { }
catch (Exception ex)
{
LOG.Error("Error parsing Flickr Response.", ex); LOG.Error("Error parsing Flickr Response.", ex);
} }
return null; return null;
} }
} }

View file

@ -21,7 +21,9 @@
using GreenshotPlugin.Controls; using GreenshotPlugin.Controls;
namespace Greenshot.Plugin.Flickr.Forms { namespace Greenshot.Plugin.Flickr.Forms
public class FlickrForm : GreenshotForm { {
public class FlickrForm : GreenshotForm
{
} }
} }

View file

@ -19,12 +19,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Greenshot.Plugin.Flickr.Forms { namespace Greenshot.Plugin.Flickr.Forms
{
/// <summary> /// <summary>
/// Description of PasswordRequestForm. /// Description of PasswordRequestForm.
/// </summary> /// </summary>
public partial class SettingsForm : FlickrForm { public partial class SettingsForm : FlickrForm
public SettingsForm() { {
public SettingsForm()
{
// //
// The InitializeComponent() call is required for Windows Forms designer support. // The InitializeComponent() call is required for Windows Forms designer support.
// //
@ -32,6 +35,5 @@ namespace Greenshot.Plugin.Flickr.Forms {
CancelButton = buttonCancel; CancelButton = buttonCancel;
AcceptButton = buttonOK; AcceptButton = buttonOK;
} }
} }
} }

View file

@ -18,8 +18,11 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Greenshot.Plugin.Flickr {
public enum LangKey { namespace Greenshot.Plugin.Flickr
{
public enum LangKey
{
upload_menu_item, upload_menu_item,
upload_failure, upload_failure,
communication_wait, communication_wait,

View file

@ -20,7 +20,9 @@
using GreenshotPlugin.Controls; using GreenshotPlugin.Controls;
namespace Greenshot.Plugin.GooglePhotos.Forms { namespace Greenshot.Plugin.GooglePhotos.Forms
public class GooglePhotosForm : GreenshotForm { {
public class GooglePhotosForm : GreenshotForm
{
} }
} }

View file

@ -18,12 +18,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Greenshot.Plugin.GooglePhotos.Forms { namespace Greenshot.Plugin.GooglePhotos.Forms
{
/// <summary> /// <summary>
/// Description of PasswordRequestForm. /// Description of PasswordRequestForm.
/// </summary> /// </summary>
public partial class SettingsForm : GooglePhotosForm { public partial class SettingsForm : GooglePhotosForm
{
public SettingsForm() public SettingsForm()
{ {
// //
@ -33,6 +34,5 @@ namespace Greenshot.Plugin.GooglePhotos.Forms {
CancelButton = buttonCancel; CancelButton = buttonCancel;
AcceptButton = buttonOK; AcceptButton = buttonOK;
} }
} }
} }

View file

@ -24,71 +24,58 @@ using Greenshot.Plugin.GooglePhotos.Forms;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
namespace Greenshot.Plugin.GooglePhotos { namespace Greenshot.Plugin.GooglePhotos
{
/// <summary> /// <summary>
/// Description of GooglePhotosConfiguration. /// Description of GooglePhotosConfiguration.
/// </summary> /// </summary>
[IniSection("GooglePhotos", Description = "Greenshot GooglePhotos Plugin configuration")] [IniSection("GooglePhotos", Description = "Greenshot GooglePhotos Plugin configuration")]
public class GooglePhotosConfiguration : IniSection { public class GooglePhotosConfiguration : IniSection
[IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")] {
[IniProperty("UploadFormat", Description = "What file type to use for uploading", DefaultValue = "png")]
public OutputFormat UploadFormat { get; set; } public OutputFormat UploadFormat { get; set; }
[IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")] [IniProperty("UploadJpegQuality", Description = "JPEG file save quality in %.", DefaultValue = "80")]
public int UploadJpegQuality { get; set; } public int UploadJpegQuality { get; set; }
[IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send GooglePhotos link to clipboard.", DefaultValue = "true")] [IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send GooglePhotos link to clipboard.", DefaultValue = "true")]
public bool AfterUploadLinkToClipBoard { get; set; } public bool AfterUploadLinkToClipBoard { get; set; }
[IniProperty("AddFilename", Description = "Is the filename passed on to GooglePhotos", DefaultValue = "False")] [IniProperty("AddFilename", Description = "Is the filename passed on to GooglePhotos", DefaultValue = "False")]
public bool AddFilename { public bool AddFilename { get; set; }
get;
set;
}
[IniProperty("UploadUser", Description = "The GooglePhotos user to upload to", DefaultValue = "default")] [IniProperty("UploadUser", Description = "The GooglePhotos user to upload to", DefaultValue = "default")]
public string UploadUser { public string UploadUser { get; set; }
get;
set;
}
[IniProperty("UploadAlbum", Description = "The GooglePhotos album to upload to", DefaultValue = "default")] [IniProperty("UploadAlbum", Description = "The GooglePhotos album to upload to", DefaultValue = "default")]
public string UploadAlbum { public string UploadAlbum { get; set; }
get;
set;
}
[IniProperty("RefreshToken", Description = "GooglePhotos authorization refresh Token", Encrypted = true)] [IniProperty("RefreshToken", Description = "GooglePhotos authorization refresh Token", Encrypted = true)]
public string RefreshToken { public string RefreshToken { get; set; }
get;
set;
}
/// <summary> /// <summary>
/// Not stored /// Not stored
/// </summary> /// </summary>
public string AccessToken { public string AccessToken { get; set; }
get;
set;
}
/// <summary> /// <summary>
/// Not stored /// Not stored
/// </summary> /// </summary>
public DateTimeOffset AccessTokenExpires { public DateTimeOffset AccessTokenExpires { get; set; }
get;
set;
}
/// <summary> /// <summary>
/// A form for token /// A form for token
/// </summary> /// </summary>
/// <returns>bool true if OK was pressed, false if cancel</returns> /// <returns>bool true if OK was pressed, false if cancel</returns>
public bool ShowConfigDialog() { public bool ShowConfigDialog()
{
DialogResult result = new SettingsForm().ShowDialog(); DialogResult result = new SettingsForm().ShowDialog();
if (result == DialogResult.OK) { if (result == DialogResult.OK)
{
return true; return true;
} }
return false; return false;
} }
} }
} }

View file

@ -23,10 +23,14 @@ using System.Drawing;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
namespace Greenshot.Plugin.GooglePhotos { namespace Greenshot.Plugin.GooglePhotos
public class GooglePhotosDestination : AbstractDestination { {
public class GooglePhotosDestination : AbstractDestination
{
private readonly GooglePhotosPlugin _plugin; private readonly GooglePhotosPlugin _plugin;
public GooglePhotosDestination(GooglePhotosPlugin plugin) {
public GooglePhotosDestination(GooglePhotosPlugin plugin)
{
_plugin = plugin; _plugin = plugin;
} }
@ -34,20 +38,25 @@ namespace Greenshot.Plugin.GooglePhotos {
public override string Description => Language.GetString("googlephotos", LangKey.upload_menu_item); public override string Description => Language.GetString("googlephotos", LangKey.upload_menu_item);
public override Image DisplayIcon { public override Image DisplayIcon
get { {
get
{
ComponentResourceManager resources = new ComponentResourceManager(typeof(GooglePhotosPlugin)); ComponentResourceManager resources = new ComponentResourceManager(typeof(GooglePhotosPlugin));
return (Image)resources.GetObject("GooglePhotos"); return (Image) resources.GetObject("GooglePhotos");
} }
} }
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails)
{
ExportInformation exportInformation = new ExportInformation(Designation, Description); ExportInformation exportInformation = new ExportInformation(Designation, Description);
bool uploaded = _plugin.Upload(captureDetails, surface, out var uploadUrl); bool uploaded = _plugin.Upload(captureDetails, surface, out var uploadUrl);
if (uploaded) { if (uploaded)
{
exportInformation.ExportMade = true; exportInformation.ExportMade = true;
exportInformation.Uri = uploadUrl; exportInformation.Uri = uploadUrl;
} }
ProcessExport(exportInformation, surface); ProcessExport(exportInformation, surface);
return exportInformation; return exportInformation;
} }

View file

@ -29,18 +29,21 @@ using GreenshotPlugin.IniFile;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin; using GreenshotPlugin.Interfaces.Plugin;
namespace Greenshot.Plugin.GooglePhotos { namespace Greenshot.Plugin.GooglePhotos
{
/// <summary> /// <summary>
/// This is the GooglePhotos base code /// This is the GooglePhotos base code
/// </summary> /// </summary>
[Plugin("GooglePhotos", true)] [Plugin("GooglePhotos", true)]
public class GooglePhotosPlugin : IGreenshotPlugin { public class GooglePhotosPlugin : IGreenshotPlugin
{
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(GooglePhotosPlugin)); private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(GooglePhotosPlugin));
private static GooglePhotosConfiguration _config; private static GooglePhotosConfiguration _config;
private ComponentResourceManager _resources; private ComponentResourceManager _resources;
private ToolStripMenuItem _itemPlugInRoot; private ToolStripMenuItem _itemPlugInRoot;
public void Dispose() { public void Dispose()
{
Dispose(true); Dispose(true);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
@ -56,7 +59,8 @@ namespace Greenshot.Plugin.GooglePhotos {
/// <summary> /// <summary>
/// Implementation of the IGreenshotPlugin.Initialize /// Implementation of the IGreenshotPlugin.Initialize
/// </summary> /// </summary>
public bool Initialize() { public bool Initialize()
{
SimpleServiceProvider.Current.AddService<IDestination>(new GooglePhotosDestination(this)); SimpleServiceProvider.Current.AddService<IDestination>(new GooglePhotosDestination(this));
// Get configuration // Get configuration
@ -74,13 +78,16 @@ namespace Greenshot.Plugin.GooglePhotos {
return true; return true;
} }
public void OnLanguageChanged(object sender, EventArgs e) { public void OnLanguageChanged(object sender, EventArgs e)
if (_itemPlugInRoot != null) { {
if (_itemPlugInRoot != null)
{
_itemPlugInRoot.Text = Language.GetString("googlephotos", LangKey.Configure); _itemPlugInRoot.Text = Language.GetString("googlephotos", LangKey.Configure);
} }
} }
public void Shutdown() { public void Shutdown()
{
Log.Debug("GooglePhotos Plugin shutdown."); Log.Debug("GooglePhotos Plugin shutdown.");
Language.LanguageChanged -= OnLanguageChanged; Language.LanguageChanged -= OnLanguageChanged;
//host.OnImageEditorOpen -= new OnImageEditorOpenHandler(ImageEditorOpened); //host.OnImageEditorOpen -= new OnImageEditorOpenHandler(ImageEditorOpened);
@ -89,17 +96,21 @@ namespace Greenshot.Plugin.GooglePhotos {
/// <summary> /// <summary>
/// Implementation of the IPlugin.Configure /// Implementation of the IPlugin.Configure
/// </summary> /// </summary>
public void Configure() { public void Configure()
{
_config.ShowConfigDialog(); _config.ShowConfigDialog();
} }
public void ConfigMenuClick(object sender, EventArgs eventArgs) { public void ConfigMenuClick(object sender, EventArgs eventArgs)
{
Configure(); Configure();
} }
public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, out string uploadUrl) { public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, out string uploadUrl)
{
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality); SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality);
try { try
{
string url = null; string url = null;
new PleaseWaitForm().ShowAndWait("GooglePhotos", Language.GetString("googlephotos", LangKey.communication_wait), new PleaseWaitForm().ShowAndWait("GooglePhotos", Language.GetString("googlephotos", LangKey.communication_wait),
delegate delegate
@ -110,14 +121,19 @@ namespace Greenshot.Plugin.GooglePhotos {
); );
uploadUrl = url; uploadUrl = url;
if (uploadUrl != null && _config.AfterUploadLinkToClipBoard) { if (uploadUrl != null && _config.AfterUploadLinkToClipBoard)
{
ClipboardHelper.SetClipboardData(uploadUrl); ClipboardHelper.SetClipboardData(uploadUrl);
} }
return true; return true;
} catch (Exception e) { }
catch (Exception e)
{
Log.Error("Error uploading.", e); Log.Error("Error uploading.", e);
MessageBox.Show(Language.GetString("googlephotos", LangKey.upload_failure) + " " + e.Message); MessageBox.Show(Language.GetString("googlephotos", LangKey.upload_failure) + " " + e.Message);
} }
uploadUrl = null; uploadUrl = null;
return false; return false;
} }

View file

@ -26,15 +26,20 @@ using GreenshotPlugin.IniFile;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin; using GreenshotPlugin.Interfaces.Plugin;
namespace Greenshot.Plugin.GooglePhotos { namespace Greenshot.Plugin.GooglePhotos
{
/// <summary> /// <summary>
/// Description of GooglePhotosUtils. /// Description of GooglePhotosUtils.
/// </summary> /// </summary>
public static class GooglePhotosUtils { public static class GooglePhotosUtils
{
private const string GooglePhotosScope = "https://picasaweb.google.com/data/"; private const string GooglePhotosScope = "https://picasaweb.google.com/data/";
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(GooglePhotosUtils)); private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(GooglePhotosUtils));
private static readonly GooglePhotosConfiguration Config = IniConfig.GetIniSection<GooglePhotosConfiguration>(); private static readonly GooglePhotosConfiguration Config = IniConfig.GetIniSection<GooglePhotosConfiguration>();
private const string AuthUrl = "https://accounts.google.com/o/oauth2/auth?response_type=code&client_id={ClientId}&redirect_uri={RedirectUrl}&state={State}&scope=" + GooglePhotosScope;
private const string AuthUrl = "https://accounts.google.com/o/oauth2/auth?response_type=code&client_id={ClientId}&redirect_uri={RedirectUrl}&state={State}&scope=" +
GooglePhotosScope;
private const string TokenUrl = "https://www.googleapis.com/oauth2/v3/token"; private const string TokenUrl = "https://www.googleapis.com/oauth2/v3/token";
private const string UploadUrl = "https://picasaweb.google.com/data/feed/api/user/{0}/albumid/{1}"; private const string UploadUrl = "https://picasaweb.google.com/data/feed/api/user/{0}/albumid/{1}";
@ -46,7 +51,8 @@ namespace Greenshot.Plugin.GooglePhotos {
/// <param name="title">string</param> /// <param name="title">string</param>
/// <param name="filename">string</param> /// <param name="filename">string</param>
/// <returns>GooglePhotosResponse</returns> /// <returns>GooglePhotosResponse</returns>
public static string UploadToGooglePhotos(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename) { public static string UploadToGooglePhotos(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename)
{
// Fill the OAuth2Settings // Fill the OAuth2Settings
var settings = new OAuth2Settings var settings = new OAuth2Settings
{ {
@ -63,18 +69,23 @@ namespace Greenshot.Plugin.GooglePhotos {
// Copy the settings from the config, which is kept in memory and on the disk // Copy the settings from the config, which is kept in memory and on the disk
try { try
{
var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, string.Format(UploadUrl, Config.UploadUser, Config.UploadAlbum), settings); var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, string.Format(UploadUrl, Config.UploadUser, Config.UploadAlbum), settings);
if (Config.AddFilename) { if (Config.AddFilename)
{
webRequest.Headers.Add("Slug", NetworkHelper.EscapeDataString(filename)); webRequest.Headers.Add("Slug", NetworkHelper.EscapeDataString(filename));
} }
SurfaceContainer container = new SurfaceContainer(surfaceToUpload, outputSettings, filename); SurfaceContainer container = new SurfaceContainer(surfaceToUpload, outputSettings, filename);
container.Upload(webRequest); container.Upload(webRequest);
string response = NetworkHelper.GetResponseAsString(webRequest); string response = NetworkHelper.GetResponseAsString(webRequest);
return ParseResponse(response); return ParseResponse(response);
} finally { }
finally
{
// Copy the settings back to the config, so they are stored. // Copy the settings back to the config, so they are stored.
Config.RefreshToken = settings.RefreshToken; Config.RefreshToken = settings.RefreshToken;
Config.AccessToken = settings.AccessToken; Config.AccessToken = settings.AccessToken;
@ -89,31 +100,43 @@ namespace Greenshot.Plugin.GooglePhotos {
/// </summary> /// </summary>
/// <param name="response"></param> /// <param name="response"></param>
/// <returns></returns> /// <returns></returns>
public static string ParseResponse(string response) { public static string ParseResponse(string response)
if (response == null) { {
if (response == null)
{
return null; return null;
} }
try {
try
{
XmlDocument doc = new XmlDocument(); XmlDocument doc = new XmlDocument();
doc.LoadXml(response); doc.LoadXml(response);
XmlNodeList nodes = doc.GetElementsByTagName("link", "*"); XmlNodeList nodes = doc.GetElementsByTagName("link", "*");
if(nodes.Count > 0) { if (nodes.Count > 0)
{
string url = null; string url = null;
foreach(XmlNode node in nodes) { foreach (XmlNode node in nodes)
if (node.Attributes != null) { {
if (node.Attributes != null)
{
url = node.Attributes["href"].Value; url = node.Attributes["href"].Value;
string rel = node.Attributes["rel"].Value; string rel = node.Attributes["rel"].Value;
// Pictures with rel="http://schemas.google.com/photos/2007#canonical" are the direct link // Pictures with rel="http://schemas.google.com/photos/2007#canonical" are the direct link
if (rel != null && rel.EndsWith("canonical")) { if (rel != null && rel.EndsWith("canonical"))
{
break; break;
} }
} }
} }
return url; return url;
} }
} catch(Exception e) { }
catch (Exception e)
{
Log.ErrorFormat("Could not parse GooglePhotos response due to error {0}, response was: {1}", e.Message, response); Log.ErrorFormat("Could not parse GooglePhotos response due to error {0}, response was: {1}", e.Message, response);
} }
return null; return null;
} }
} }

View file

@ -18,7 +18,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Greenshot.Plugin.GooglePhotos { namespace Greenshot.Plugin.GooglePhotos
{
public enum LangKey public enum LangKey
{ {
upload_menu_item, upload_menu_item,

View file

@ -21,10 +21,12 @@
using GreenshotPlugin.Controls; using GreenshotPlugin.Controls;
namespace Greenshot.Plugin.Imgur.Forms { namespace Greenshot.Plugin.Imgur.Forms
{
/// <summary> /// <summary>
/// This class is needed for design-time resolving of the language files /// This class is needed for design-time resolving of the language files
/// </summary> /// </summary>
public class ImgurForm : GreenshotForm { public class ImgurForm : GreenshotForm
{
} }
} }

View file

@ -27,18 +27,21 @@ using GreenshotPlugin.Controls;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
namespace Greenshot.Plugin.Imgur.Forms { namespace Greenshot.Plugin.Imgur.Forms
{
/// <summary> /// <summary>
/// Imgur history form /// Imgur history form
/// </summary> /// </summary>
public sealed partial class ImgurHistory : ImgurForm { public sealed partial class ImgurHistory : ImgurForm
{
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurHistory)); private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurHistory));
private readonly GreenshotColumnSorter _columnSorter; private readonly GreenshotColumnSorter _columnSorter;
private static readonly object Lock = new object(); private static readonly object Lock = new object();
private static readonly ImgurConfiguration Config = IniConfig.GetIniSection<ImgurConfiguration>(); private static readonly ImgurConfiguration Config = IniConfig.GetIniSection<ImgurConfiguration>();
private static ImgurHistory _instance; private static ImgurHistory _instance;
public static void ShowHistory() { public static void ShowHistory()
{
lock (Lock) lock (Lock)
{ {
if (ImgurUtils.IsHistoryLoadingNeeded()) if (ImgurUtils.IsHistoryLoadingNeeded())
@ -54,15 +57,18 @@ namespace Greenshot.Plugin.Imgur.Forms {
{ {
_instance = new ImgurHistory(); _instance = new ImgurHistory();
} }
if (!_instance.Visible) if (!_instance.Visible)
{ {
_instance.Show(); _instance.Show();
} }
_instance.Redraw(); _instance.Redraw();
} }
} }
private ImgurHistory() { private ImgurHistory()
{
ManualLanguageApply = true; ManualLanguageApply = true;
// //
// The InitializeComponent() call is required for Windows Forms designer support. // The InitializeComponent() call is required for Windows Forms designer support.
@ -76,26 +82,36 @@ namespace Greenshot.Plugin.Imgur.Forms {
_columnSorter.SortColumn = 3; _columnSorter.SortColumn = 3;
_columnSorter.Order = SortOrder.Descending; _columnSorter.Order = SortOrder.Descending;
Redraw(); Redraw();
if (listview_imgur_uploads.Items.Count > 0) { if (listview_imgur_uploads.Items.Count > 0)
{
listview_imgur_uploads.Items[0].Selected = true; listview_imgur_uploads.Items[0].Selected = true;
} }
ApplyLanguage(); ApplyLanguage();
if (Config.Credits > 0) { if (Config.Credits > 0)
{
Text = Text + " (" + Config.Credits + " credits)"; Text = Text + " (" + Config.Credits + " credits)";
} }
} }
private void Redraw() { private void Redraw()
{
// Should fix Bug #3378699 // Should fix Bug #3378699
pictureBox1.Image = pictureBox1.ErrorImage; pictureBox1.Image = pictureBox1.ErrorImage;
listview_imgur_uploads.BeginUpdate(); listview_imgur_uploads.BeginUpdate();
listview_imgur_uploads.Items.Clear(); listview_imgur_uploads.Items.Clear();
listview_imgur_uploads.Columns.Clear(); listview_imgur_uploads.Columns.Clear();
string[] columns = { "hash", "title", "deleteHash", "Date"}; string[] columns =
foreach (string column in columns) { {
"hash", "title", "deleteHash", "Date"
};
foreach (string column in columns)
{
listview_imgur_uploads.Columns.Add(column); listview_imgur_uploads.Columns.Add(column);
} }
foreach (ImgurInfo imgurInfo in Config.runtimeImgurHistory.Values) {
foreach (ImgurInfo imgurInfo in Config.runtimeImgurHistory.Values)
{
var item = new ListViewItem(imgurInfo.Hash) var item = new ListViewItem(imgurInfo.Hash)
{ {
Tag = imgurInfo Tag = imgurInfo
@ -105,7 +121,9 @@ namespace Greenshot.Plugin.Imgur.Forms {
item.SubItems.Add(imgurInfo.Timestamp.ToString("yyyy-MM-dd HH:mm:ss", DateTimeFormatInfo.InvariantInfo)); item.SubItems.Add(imgurInfo.Timestamp.ToString("yyyy-MM-dd HH:mm:ss", DateTimeFormatInfo.InvariantInfo));
listview_imgur_uploads.Items.Add(item); listview_imgur_uploads.Items.Add(item);
} }
for (int i = 0; i < columns.Length; i++) {
for (int i = 0; i < columns.Length; i++)
{
listview_imgur_uploads.AutoResizeColumn(i, ColumnHeaderAutoResizeStyle.ColumnContent); listview_imgur_uploads.AutoResizeColumn(i, ColumnHeaderAutoResizeStyle.ColumnContent);
} }
@ -116,17 +134,22 @@ namespace Greenshot.Plugin.Imgur.Forms {
clipboardButton.Enabled = false; clipboardButton.Enabled = false;
} }
private void Listview_imgur_uploadsSelectedIndexChanged(object sender, EventArgs e) { private void Listview_imgur_uploadsSelectedIndexChanged(object sender, EventArgs e)
{
pictureBox1.Image = pictureBox1.ErrorImage; pictureBox1.Image = pictureBox1.ErrorImage;
if (listview_imgur_uploads.SelectedItems.Count > 0) { if (listview_imgur_uploads.SelectedItems.Count > 0)
{
deleteButton.Enabled = true; deleteButton.Enabled = true;
openButton.Enabled = true; openButton.Enabled = true;
clipboardButton.Enabled = true; clipboardButton.Enabled = true;
if (listview_imgur_uploads.SelectedItems.Count == 1) { if (listview_imgur_uploads.SelectedItems.Count == 1)
ImgurInfo imgurInfo = (ImgurInfo)listview_imgur_uploads.SelectedItems[0].Tag; {
ImgurInfo imgurInfo = (ImgurInfo) listview_imgur_uploads.SelectedItems[0].Tag;
pictureBox1.Image = imgurInfo.Image; pictureBox1.Image = imgurInfo.Image;
} }
} else { }
else
{
pictureBox1.Image = pictureBox1.ErrorImage; pictureBox1.Image = pictureBox1.ErrorImage;
deleteButton.Enabled = false; deleteButton.Enabled = false;
openButton.Enabled = false; openButton.Enabled = false;
@ -134,48 +157,60 @@ namespace Greenshot.Plugin.Imgur.Forms {
} }
} }
private void DeleteButtonClick(object sender, EventArgs e) { private void DeleteButtonClick(object sender, EventArgs e)
if (listview_imgur_uploads.SelectedItems.Count > 0) { {
for (int i = 0; i < listview_imgur_uploads.SelectedItems.Count; i++) { if (listview_imgur_uploads.SelectedItems.Count > 0)
ImgurInfo imgurInfo = (ImgurInfo)listview_imgur_uploads.SelectedItems[i].Tag; {
DialogResult result = MessageBox.Show(Language.GetFormattedString("imgur", LangKey.delete_question, imgurInfo.Title), Language.GetFormattedString("imgur", LangKey.delete_title, imgurInfo.Hash), MessageBoxButtons.YesNo, MessageBoxIcon.Question); for (int i = 0; i < listview_imgur_uploads.SelectedItems.Count; i++)
{
ImgurInfo imgurInfo = (ImgurInfo) listview_imgur_uploads.SelectedItems[i].Tag;
DialogResult result = MessageBox.Show(Language.GetFormattedString("imgur", LangKey.delete_question, imgurInfo.Title),
Language.GetFormattedString("imgur", LangKey.delete_title, imgurInfo.Hash), MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result != DialogResult.Yes) if (result != DialogResult.Yes)
{ {
continue; continue;
} }
// Should fix Bug #3378699 // Should fix Bug #3378699
pictureBox1.Image = pictureBox1.ErrorImage; pictureBox1.Image = pictureBox1.ErrorImage;
try { try
{
new PleaseWaitForm().ShowAndWait("Imgur", Language.GetString("imgur", LangKey.communication_wait), new PleaseWaitForm().ShowAndWait("Imgur", Language.GetString("imgur", LangKey.communication_wait),
delegate { delegate { ImgurUtils.DeleteImgurImage(imgurInfo); }
ImgurUtils.DeleteImgurImage(imgurInfo);
}
); );
} catch (Exception ex) { }
catch (Exception ex)
{
Log.Warn("Problem communicating with Imgur: ", ex); Log.Warn("Problem communicating with Imgur: ", ex);
} }
imgurInfo.Dispose(); imgurInfo.Dispose();
} }
} }
Redraw(); Redraw();
} }
private void ClipboardButtonClick(object sender, EventArgs e) { private void ClipboardButtonClick(object sender, EventArgs e)
{
StringBuilder links = new StringBuilder(); StringBuilder links = new StringBuilder();
if (listview_imgur_uploads.SelectedItems.Count > 0) { if (listview_imgur_uploads.SelectedItems.Count > 0)
{
for (int i = 0; i < listview_imgur_uploads.SelectedItems.Count; i++) for (int i = 0; i < listview_imgur_uploads.SelectedItems.Count; i++)
{ {
ImgurInfo imgurInfo = (ImgurInfo)listview_imgur_uploads.SelectedItems[i].Tag; ImgurInfo imgurInfo = (ImgurInfo) listview_imgur_uploads.SelectedItems[i].Tag;
links.AppendLine(Config.UsePageLink ? imgurInfo.Page : imgurInfo.Original); links.AppendLine(Config.UsePageLink ? imgurInfo.Page : imgurInfo.Original);
} }
} }
ClipboardHelper.SetClipboardData(links.ToString()); ClipboardHelper.SetClipboardData(links.ToString());
} }
private void ClearHistoryButtonClick(object sender, EventArgs e) { private void ClearHistoryButtonClick(object sender, EventArgs e)
{
DialogResult result = MessageBox.Show(Language.GetString("imgur", LangKey.clear_question), "Imgur", MessageBoxButtons.YesNo, MessageBoxIcon.Question); DialogResult result = MessageBox.Show(Language.GetString("imgur", LangKey.clear_question), "Imgur", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.Yes) { if (result == DialogResult.Yes)
{
Config.runtimeImgurHistory.Clear(); Config.runtimeImgurHistory.Clear();
Config.ImgurUploadHistory.Clear(); Config.ImgurUploadHistory.Clear();
IniConfig.Save(); IniConfig.Save();
@ -188,21 +223,28 @@ namespace Greenshot.Plugin.Imgur.Forms {
Hide(); Hide();
} }
private void OpenButtonClick(object sender, EventArgs e) { private void OpenButtonClick(object sender, EventArgs e)
if (listview_imgur_uploads.SelectedItems.Count > 0) { {
for (int i = 0; i < listview_imgur_uploads.SelectedItems.Count; i++) { if (listview_imgur_uploads.SelectedItems.Count > 0)
ImgurInfo imgurInfo = (ImgurInfo)listview_imgur_uploads.SelectedItems[i].Tag; {
for (int i = 0; i < listview_imgur_uploads.SelectedItems.Count; i++)
{
ImgurInfo imgurInfo = (ImgurInfo) listview_imgur_uploads.SelectedItems[i].Tag;
System.Diagnostics.Process.Start(imgurInfo.Page); System.Diagnostics.Process.Start(imgurInfo.Page);
} }
} }
} }
private void listview_imgur_uploads_ColumnClick(object sender, ColumnClickEventArgs e) { private void listview_imgur_uploads_ColumnClick(object sender, ColumnClickEventArgs e)
{
// Determine if clicked column is already the column that is being sorted. // Determine if clicked column is already the column that is being sorted.
if (e.Column == _columnSorter.SortColumn) { if (e.Column == _columnSorter.SortColumn)
{
// Reverse the current sort direction for this column. // Reverse the current sort direction for this column.
_columnSorter.Order = _columnSorter.Order == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending; _columnSorter.Order = _columnSorter.Order == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
} else { }
else
{
// Set the column number that is to be sorted; default to ascending. // Set the column number that is to be sorted; default to ascending.
_columnSorter.SortColumn = e.Column; _columnSorter.SortColumn = e.Column;
_columnSorter.Order = SortOrder.Ascending; _columnSorter.Order = SortOrder.Ascending;

View file

@ -21,11 +21,13 @@
using System; using System;
namespace Greenshot.Plugin.Imgur.Forms { namespace Greenshot.Plugin.Imgur.Forms
{
/// <summary> /// <summary>
/// Description of PasswordRequestForm. /// Description of PasswordRequestForm.
/// </summary> /// </summary>
public partial class SettingsForm : ImgurForm { public partial class SettingsForm : ImgurForm
{
public SettingsForm() public SettingsForm()
{ {
// //
@ -38,7 +40,8 @@ namespace Greenshot.Plugin.Imgur.Forms {
historyButton.Enabled = ImgurUtils.IsHistoryLoadingNeeded(); historyButton.Enabled = ImgurUtils.IsHistoryLoadingNeeded();
} }
private void ButtonHistoryClick(object sender, EventArgs e) { private void ButtonHistoryClick(object sender, EventArgs e)
{
ImgurHistory.ShowHistory(); ImgurHistory.ShowHistory();
} }
} }

View file

@ -26,26 +26,33 @@ using Greenshot.Plugin.Imgur.Forms;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
namespace Greenshot.Plugin.Imgur { namespace Greenshot.Plugin.Imgur
{
/// <summary> /// <summary>
/// Description of ImgurConfiguration. /// Description of ImgurConfiguration.
/// </summary> /// </summary>
[IniSection("Imgur", Description="Greenshot Imgur Plugin configuration")] [IniSection("Imgur", Description = "Greenshot Imgur Plugin configuration")]
public class ImgurConfiguration : IniSection { public class ImgurConfiguration : IniSection
{
[IniProperty("ImgurApi3Url", Description = "Url to Imgur system.", DefaultValue = "https://api.imgur.com/3")] [IniProperty("ImgurApi3Url", Description = "Url to Imgur system.", DefaultValue = "https://api.imgur.com/3")]
public string ImgurApi3Url { get; set; } public string ImgurApi3Url { get; set; }
[IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")] [IniProperty("UploadFormat", Description = "What file type to use for uploading", DefaultValue = "png")]
public OutputFormat UploadFormat { get; set; } public OutputFormat UploadFormat { get; set; }
[IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
[IniProperty("UploadJpegQuality", Description = "JPEG file save quality in %.", DefaultValue = "80")]
public int UploadJpegQuality { get; set; } public int UploadJpegQuality { get; set; }
[IniProperty("UploadReduceColors", Description="Reduce color amount of the uploaded image to 256", DefaultValue="False")]
[IniProperty("UploadReduceColors", Description = "Reduce color amount of the uploaded image to 256", DefaultValue = "False")]
public bool UploadReduceColors { get; set; } public bool UploadReduceColors { get; set; }
[IniProperty("CopyLinkToClipboard", Description = "Copy the link, which one is controlled by the UsePageLink, on the clipboard", DefaultValue = "True")] [IniProperty("CopyLinkToClipboard", Description = "Copy the link, which one is controlled by the UsePageLink, on the clipboard", DefaultValue = "True")]
public bool CopyLinkToClipboard { get; set; } public bool CopyLinkToClipboard { get; set; }
[IniProperty("UsePageLink", Description = "Use pagelink instead of direct link on the clipboard", DefaultValue = "False")] [IniProperty("UsePageLink", Description = "Use pagelink instead of direct link on the clipboard", DefaultValue = "False")]
public bool UsePageLink { get; set; } public bool UsePageLink { get; set; }
[IniProperty("AnonymousAccess", Description = "Use anonymous access to Imgur", DefaultValue="true")]
[IniProperty("AnonymousAccess", Description = "Use anonymous access to Imgur", DefaultValue = "true")]
public bool AnonymousAccess { get; set; } public bool AnonymousAccess { get; set; }
[IniProperty("RefreshToken", Description = "Imgur refresh Token", Encrypted = true, ExcludeIfNull = true)] [IniProperty("RefreshToken", Description = "Imgur refresh Token", Encrypted = true, ExcludeIfNull = true)]
@ -63,20 +70,19 @@ namespace Greenshot.Plugin.Imgur {
[IniProperty("AddTitle", Description = "Is the title passed on to Imgur", DefaultValue = "False")] [IniProperty("AddTitle", Description = "Is the title passed on to Imgur", DefaultValue = "False")]
public bool AddTitle { get; set; } public bool AddTitle { get; set; }
[IniProperty("AddFilename", Description = "Is the filename passed on to Imgur", DefaultValue = "False")] [IniProperty("AddFilename", Description = "Is the filename passed on to Imgur", DefaultValue = "False")]
public bool AddFilename { get; set; } public bool AddFilename { get; set; }
[IniProperty("FilenamePattern", Description = "Filename for the Imgur upload", DefaultValue = "${capturetime:d\"yyyyMMdd-HHmm\"}")] [IniProperty("FilenamePattern", Description = "Filename for the Imgur upload", DefaultValue = "${capturetime:d\"yyyyMMdd-HHmm\"}")]
public string FilenamePattern { get; set; } public string FilenamePattern { get; set; }
[IniProperty("ImgurUploadHistory", Description="Imgur upload history (ImgurUploadHistory.hash=deleteHash)")] [IniProperty("ImgurUploadHistory", Description = "Imgur upload history (ImgurUploadHistory.hash=deleteHash)")]
public Dictionary<string, string> ImgurUploadHistory { get; set; } public Dictionary<string, string> ImgurUploadHistory { get; set; }
// Not stored, only run-time! // Not stored, only run-time!
public Dictionary<string, ImgurInfo> runtimeImgurHistory = new Dictionary<string, ImgurInfo>(); public Dictionary<string, ImgurInfo> runtimeImgurHistory = new Dictionary<string, ImgurInfo>();
public int Credits { public int Credits { get; set; }
get;
set;
}
/// <summary> /// <summary>
/// Supply values we can't put as defaults /// Supply values we can't put as defaults
@ -94,7 +100,8 @@ namespace Greenshot.Plugin.Imgur {
/// A form for username/password /// A form for username/password
/// </summary> /// </summary>
/// <returns>bool true if OK was pressed, false if cancel</returns> /// <returns>bool true if OK was pressed, false if cancel</returns>
public bool ShowConfigDialog() { public bool ShowConfigDialog()
{
SettingsForm settingsForm = new SettingsForm(); SettingsForm settingsForm = new SettingsForm();
DialogResult result = settingsForm.ShowDialog(); DialogResult result = settingsForm.ShowDialog();
return result == DialogResult.OK; return result == DialogResult.OK;

View file

@ -24,14 +24,17 @@ using System.Drawing;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
namespace Greenshot.Plugin.Imgur { namespace Greenshot.Plugin.Imgur
{
/// <summary> /// <summary>
/// Description of ImgurDestination. /// Description of ImgurDestination.
/// </summary> /// </summary>
public class ImgurDestination : AbstractDestination { public class ImgurDestination : AbstractDestination
{
private readonly ImgurPlugin _plugin; private readonly ImgurPlugin _plugin;
public ImgurDestination(ImgurPlugin plugin) { public ImgurDestination(ImgurPlugin plugin)
{
_plugin = plugin; _plugin = plugin;
} }
@ -39,17 +42,21 @@ namespace Greenshot.Plugin.Imgur {
public override string Description => Language.GetString("imgur", LangKey.upload_menu_item); public override string Description => Language.GetString("imgur", LangKey.upload_menu_item);
public override Image DisplayIcon { public override Image DisplayIcon
get { {
get
{
ComponentResourceManager resources = new ComponentResourceManager(typeof(ImgurPlugin)); ComponentResourceManager resources = new ComponentResourceManager(typeof(ImgurPlugin));
return (Image)resources.GetObject("Imgur"); return (Image) resources.GetObject("Imgur");
} }
} }
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails)
{
ExportInformation exportInformation = new ExportInformation(Designation, Description) ExportInformation exportInformation = new ExportInformation(Designation, Description)
{ {
ExportMade = _plugin.Upload(captureDetails, surface, out var uploadUrl), Uri = uploadUrl ExportMade = _plugin.Upload(captureDetails, surface, out var uploadUrl),
Uri = uploadUrl
}; };
ProcessExport(exportInformation, surface); ProcessExport(exportInformation, surface);
return exportInformation; return exportInformation;

View file

@ -32,13 +32,10 @@ namespace Greenshot.Plugin.Imgur
{ {
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurInfo)); private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurInfo));
public string Hash public string Hash { get; set; }
{
get;
set;
}
private string _deleteHash; private string _deleteHash;
public string DeleteHash public string DeleteHash
{ {
get { return _deleteHash; } get { return _deleteHash; }
@ -49,55 +46,24 @@ namespace Greenshot.Plugin.Imgur
} }
} }
public string Title public string Title { get; set; }
{
get;
set;
}
public string ImageType public string ImageType { get; set; }
{
get;
set;
}
public DateTime Timestamp public DateTime Timestamp { get; set; }
{
get;
set;
}
public string Original public string Original { get; set; }
{
get;
set;
}
public string Page public string Page { get; set; }
{
get;
set;
}
public string SmallSquare public string SmallSquare { get; set; }
{
get;
set;
}
public string LargeThumbnail public string LargeThumbnail { get; set; }
{
get;
set;
}
public string DeletePage public string DeletePage { get; set; }
{
get;
set;
}
private Image _image; private Image _image;
public Image Image public Image Image
{ {
get { return _image; } get { return _image; }
@ -129,8 +95,10 @@ namespace Greenshot.Plugin.Imgur
{ {
_image?.Dispose(); _image?.Dispose();
} }
_image = null; _image = null;
} }
public static ImgurInfo ParseResponse(string response) public static ImgurInfo ParseResponse(string response)
{ {
Log.Debug(response); Log.Debug(response);
@ -154,26 +122,31 @@ namespace Greenshot.Plugin.Imgur
{ {
imgurInfo.Hash = nodes.Item(0)?.InnerText; imgurInfo.Hash = nodes.Item(0)?.InnerText;
} }
nodes = doc.GetElementsByTagName("hash"); nodes = doc.GetElementsByTagName("hash");
if (nodes.Count > 0) if (nodes.Count > 0)
{ {
imgurInfo.Hash = nodes.Item(0)?.InnerText; imgurInfo.Hash = nodes.Item(0)?.InnerText;
} }
nodes = doc.GetElementsByTagName("deletehash"); nodes = doc.GetElementsByTagName("deletehash");
if (nodes.Count > 0) if (nodes.Count > 0)
{ {
imgurInfo.DeleteHash = nodes.Item(0)?.InnerText; imgurInfo.DeleteHash = nodes.Item(0)?.InnerText;
} }
nodes = doc.GetElementsByTagName("type"); nodes = doc.GetElementsByTagName("type");
if (nodes.Count > 0) if (nodes.Count > 0)
{ {
imgurInfo.ImageType = nodes.Item(0)?.InnerText; imgurInfo.ImageType = nodes.Item(0)?.InnerText;
} }
nodes = doc.GetElementsByTagName("title"); nodes = doc.GetElementsByTagName("title");
if (nodes.Count > 0) if (nodes.Count > 0)
{ {
imgurInfo.Title = nodes.Item(0)?.InnerText; imgurInfo.Title = nodes.Item(0)?.InnerText;
} }
nodes = doc.GetElementsByTagName("datetime"); nodes = doc.GetElementsByTagName("datetime");
if (nodes.Count > 0) if (nodes.Count > 0)
{ {
@ -184,17 +157,20 @@ namespace Greenshot.Plugin.Imgur
imgurInfo.Timestamp = epoch.AddSeconds(secondsSince).DateTime; imgurInfo.Timestamp = epoch.AddSeconds(secondsSince).DateTime;
} }
} }
nodes = doc.GetElementsByTagName("original"); nodes = doc.GetElementsByTagName("original");
if (nodes.Count > 0) if (nodes.Count > 0)
{ {
imgurInfo.Original = nodes.Item(0)?.InnerText.Replace("http:", "https:"); imgurInfo.Original = nodes.Item(0)?.InnerText.Replace("http:", "https:");
} }
// Version 3 API only has Link // Version 3 API only has Link
nodes = doc.GetElementsByTagName("link"); nodes = doc.GetElementsByTagName("link");
if (nodes.Count > 0) if (nodes.Count > 0)
{ {
imgurInfo.Original = nodes.Item(0)?.InnerText.Replace("http:", "https:"); imgurInfo.Original = nodes.Item(0)?.InnerText.Replace("http:", "https:");
} }
nodes = doc.GetElementsByTagName("imgur_page"); nodes = doc.GetElementsByTagName("imgur_page");
if (nodes.Count > 0) if (nodes.Count > 0)
{ {
@ -205,6 +181,7 @@ namespace Greenshot.Plugin.Imgur
// Version 3 doesn't have a page link in the response // Version 3 doesn't have a page link in the response
imgurInfo.Page = $"https://imgur.com/{imgurInfo.Hash}"; imgurInfo.Page = $"https://imgur.com/{imgurInfo.Hash}";
} }
nodes = doc.GetElementsByTagName("small_square"); nodes = doc.GetElementsByTagName("small_square");
imgurInfo.SmallSquare = nodes.Count > 0 ? nodes.Item(0)?.InnerText : $"http://i.imgur.com/{imgurInfo.Hash}s.png"; imgurInfo.SmallSquare = nodes.Count > 0 ? nodes.Item(0)?.InnerText : $"http://i.imgur.com/{imgurInfo.Hash}s.png";
} }
@ -212,6 +189,7 @@ namespace Greenshot.Plugin.Imgur
{ {
Log.ErrorFormat("Could not parse Imgur response due to error {0}, response was: {1}", e.Message, response); Log.ErrorFormat("Could not parse Imgur response due to error {0}, response was: {1}", e.Message, response);
} }
return imgurInfo; return imgurInfo;
} }
} }

View file

@ -32,37 +32,46 @@ using GreenshotPlugin.IniFile;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin; using GreenshotPlugin.Interfaces.Plugin;
namespace Greenshot.Plugin.Imgur { namespace Greenshot.Plugin.Imgur
{
/// <summary> /// <summary>
/// This is the ImgurPlugin code /// This is the ImgurPlugin code
/// </summary> /// </summary>
[Plugin("Imgur", true)] [Plugin("Imgur", true)]
public class ImgurPlugin : IGreenshotPlugin { public class ImgurPlugin : IGreenshotPlugin
{
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurPlugin)); private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurPlugin));
private static ImgurConfiguration _config; private static ImgurConfiguration _config;
private ComponentResourceManager _resources; private ComponentResourceManager _resources;
private ToolStripMenuItem _historyMenuItem; private ToolStripMenuItem _historyMenuItem;
private ToolStripMenuItem _itemPlugInConfig; private ToolStripMenuItem _itemPlugInConfig;
public void Dispose() { public void Dispose()
{
Dispose(true); Dispose(true);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
protected virtual void Dispose(bool disposing) { protected virtual void Dispose(bool disposing)
if (disposing) { {
if (_historyMenuItem != null) { if (disposing)
{
if (_historyMenuItem != null)
{
_historyMenuItem.Dispose(); _historyMenuItem.Dispose();
_historyMenuItem = null; _historyMenuItem = null;
} }
if (_itemPlugInConfig != null) {
if (_itemPlugInConfig != null)
{
_itemPlugInConfig.Dispose(); _itemPlugInConfig.Dispose();
_itemPlugInConfig = null; _itemPlugInConfig = null;
} }
} }
} }
private IEnumerable<IDestination> Destinations() { private IEnumerable<IDestination> Destinations()
{
yield return new ImgurDestination(this); yield return new ImgurDestination(this);
} }
@ -70,7 +79,8 @@ namespace Greenshot.Plugin.Imgur {
/// Implementation of the IGreenshotPlugin.Initialize /// Implementation of the IGreenshotPlugin.Initialize
/// </summary> /// </summary>
/// <returns>true if plugin is initialized, false if not (doesn't show)</returns> /// <returns>true if plugin is initialized, false if not (doesn't show)</returns>
public bool Initialize() { public bool Initialize()
{
// Get configuration // Get configuration
_config = IniConfig.GetIniSection<ImgurConfiguration>(); _config = IniConfig.GetIniSection<ImgurConfiguration>();
_resources = new ComponentResourceManager(typeof(ImgurPlugin)); _resources = new ComponentResourceManager(typeof(ImgurPlugin));
@ -83,15 +93,11 @@ namespace Greenshot.Plugin.Imgur {
// Provide the IDestination // Provide the IDestination
SimpleServiceProvider.Current.AddService(Destinations()); SimpleServiceProvider.Current.AddService(Destinations());
_historyMenuItem = new ToolStripMenuItem(Language.GetString("imgur", LangKey.history)); _historyMenuItem = new ToolStripMenuItem(Language.GetString("imgur", LangKey.history));
_historyMenuItem.Click += delegate { _historyMenuItem.Click += delegate { ImgurHistory.ShowHistory(); };
ImgurHistory.ShowHistory();
};
itemPlugInRoot.DropDownItems.Add(_historyMenuItem); itemPlugInRoot.DropDownItems.Add(_historyMenuItem);
_itemPlugInConfig = new ToolStripMenuItem(Language.GetString("imgur", LangKey.configure)); _itemPlugInConfig = new ToolStripMenuItem(Language.GetString("imgur", LangKey.configure));
_itemPlugInConfig.Click += delegate { _itemPlugInConfig.Click += delegate { _config.ShowConfigDialog(); };
_config.ShowConfigDialog();
};
itemPlugInRoot.DropDownItems.Add(_itemPlugInConfig); itemPlugInRoot.DropDownItems.Add(_itemPlugInConfig);
PluginUtils.AddToContextMenu(itemPlugInRoot); PluginUtils.AddToContextMenu(itemPlugInRoot);
@ -102,42 +108,55 @@ namespace Greenshot.Plugin.Imgur {
return true; return true;
} }
public void OnLanguageChanged(object sender, EventArgs e) { public void OnLanguageChanged(object sender, EventArgs e)
if (_itemPlugInConfig != null) { {
if (_itemPlugInConfig != null)
{
_itemPlugInConfig.Text = Language.GetString("imgur", LangKey.configure); _itemPlugInConfig.Text = Language.GetString("imgur", LangKey.configure);
} }
if (_historyMenuItem != null) {
if (_historyMenuItem != null)
{
_historyMenuItem.Text = Language.GetString("imgur", LangKey.history); _historyMenuItem.Text = Language.GetString("imgur", LangKey.history);
} }
} }
private void UpdateHistoryMenuItem() { private void UpdateHistoryMenuItem()
{
if (_historyMenuItem == null) if (_historyMenuItem == null)
{ {
return; return;
} }
try try
{ {
var form = SimpleServiceProvider.Current.GetInstance<Form>(); var form = SimpleServiceProvider.Current.GetInstance<Form>();
form.BeginInvoke((MethodInvoker)delegate form.BeginInvoke((MethodInvoker) delegate
{ {
var historyMenuItem = _historyMenuItem; var historyMenuItem = _historyMenuItem;
if (historyMenuItem == null) if (historyMenuItem == null)
{ {
return; return;
} }
if (_config?.ImgurUploadHistory != null && _config.ImgurUploadHistory.Count > 0) {
if (_config?.ImgurUploadHistory != null && _config.ImgurUploadHistory.Count > 0)
{
historyMenuItem.Enabled = true; historyMenuItem.Enabled = true;
} else { }
else
{
historyMenuItem.Enabled = false; historyMenuItem.Enabled = false;
} }
}); });
} catch (Exception ex) { }
catch (Exception ex)
{
Log.Error("Error loading history", ex); Log.Error("Error loading history", ex);
} }
} }
public virtual void Shutdown() { public virtual void Shutdown()
{
Log.Debug("Imgur Plugin shutdown."); Log.Debug("Imgur Plugin shutdown.");
Language.LanguageChanged -= OnLanguageChanged; Language.LanguageChanged -= OnLanguageChanged;
} }
@ -145,7 +164,8 @@ namespace Greenshot.Plugin.Imgur {
/// <summary> /// <summary>
/// Implementation of the IPlugin.Configure /// Implementation of the IPlugin.Configure
/// </summary> /// </summary>
public virtual void Configure() { public virtual void Configure()
{
_config.ShowConfigDialog(); _config.ShowConfigDialog();
} }
@ -156,9 +176,11 @@ namespace Greenshot.Plugin.Imgur {
/// <param name="surfaceToUpload">ISurface</param> /// <param name="surfaceToUpload">ISurface</param>
/// <param name="uploadUrl">out string for the url</param> /// <param name="uploadUrl">out string for the url</param>
/// <returns>true if the upload succeeded</returns> /// <returns>true if the upload succeeded</returns>
public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, out string uploadUrl) { public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, out string uploadUrl)
{
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, _config.UploadReduceColors); SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, _config.UploadReduceColors);
try { try
{
string filename = Path.GetFileName(FilenameHelper.GetFilenameFromPattern(_config.FilenamePattern, _config.UploadFormat, captureDetails)); string filename = Path.GetFileName(FilenameHelper.GetFilenameFromPattern(_config.FilenamePattern, _config.UploadFormat, captureDetails));
ImgurInfo imgurInfo = null; ImgurInfo imgurInfo = null;
@ -167,7 +189,8 @@ namespace Greenshot.Plugin.Imgur {
delegate delegate
{ {
imgurInfo = ImgurUtils.UploadToImgur(surfaceToUpload, outputSettings, captureDetails.Title, filename); imgurInfo = ImgurUtils.UploadToImgur(surfaceToUpload, outputSettings, captureDetails.Title, filename);
if (imgurInfo != null && _config.AnonymousAccess) { if (imgurInfo != null && _config.AnonymousAccess)
{
Log.InfoFormat("Storing imgur upload for hash {0} and delete hash {1}", imgurInfo.Hash, imgurInfo.DeleteHash); Log.InfoFormat("Storing imgur upload for hash {0} and delete hash {1}", imgurInfo.Hash, imgurInfo.DeleteHash);
_config.ImgurUploadHistory.Add(imgurInfo.Hash, imgurInfo.DeleteHash); _config.ImgurUploadHistory.Add(imgurInfo.Hash, imgurInfo.DeleteHash);
_config.runtimeImgurHistory.Add(imgurInfo.Hash, imgurInfo); _config.runtimeImgurHistory.Add(imgurInfo.Hash, imgurInfo);
@ -176,11 +199,14 @@ namespace Greenshot.Plugin.Imgur {
} }
); );
if (imgurInfo != null) { if (imgurInfo != null)
{
// TODO: Optimize a second call for export // TODO: Optimize a second call for export
using (Image tmpImage = surfaceToUpload.GetImageForExport()) { using (Image tmpImage = surfaceToUpload.GetImageForExport())
{
imgurInfo.Image = ImageHelper.CreateThumbnail(tmpImage, 90, 90); imgurInfo.Image = ImageHelper.CreateThumbnail(tmpImage, 90, 90);
} }
IniConfig.Save(); IniConfig.Save();
if (_config.UsePageLink) if (_config.UsePageLink)
@ -191,12 +217,12 @@ namespace Greenshot.Plugin.Imgur {
{ {
uploadUrl = imgurInfo.Original; uploadUrl = imgurInfo.Original;
} }
if (!string.IsNullOrEmpty(uploadUrl) && _config.CopyLinkToClipboard) if (!string.IsNullOrEmpty(uploadUrl) && _config.CopyLinkToClipboard)
{ {
try try
{ {
ClipboardHelper.SetClipboardData(uploadUrl); ClipboardHelper.SetClipboardData(uploadUrl);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -204,12 +230,16 @@ namespace Greenshot.Plugin.Imgur {
uploadUrl = null; uploadUrl = null;
} }
} }
return true; return true;
} }
} catch (Exception e) { }
catch (Exception e)
{
Log.Error("Error uploading.", e); Log.Error("Error uploading.", e);
MessageBox.Show(Language.GetString("imgur", LangKey.upload_failure) + " " + e.Message); MessageBox.Show(Language.GetString("imgur", LangKey.upload_failure) + " " + e.Message);
} }
uploadUrl = null; uploadUrl = null;
return false; return false;
} }

View file

@ -30,11 +30,13 @@ using GreenshotPlugin.IniFile;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin; using GreenshotPlugin.Interfaces.Plugin;
namespace Greenshot.Plugin.Imgur { namespace Greenshot.Plugin.Imgur
{
/// <summary> /// <summary>
/// A collection of Imgur helper methods /// A collection of Imgur helper methods
/// </summary> /// </summary>
public static class ImgurUtils { public static class ImgurUtils
{
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurUtils)); private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurUtils));
private const string SmallUrlPattern = "http://i.imgur.com/{0}s.jpg"; private const string SmallUrlPattern = "http://i.imgur.com/{0}s.jpg";
private static readonly ImgurConfiguration Config = IniConfig.GetIniSection<ImgurConfiguration>(); private static readonly ImgurConfiguration Config = IniConfig.GetIniSection<ImgurConfiguration>();
@ -45,14 +47,16 @@ namespace Greenshot.Plugin.Imgur {
/// <returns></returns> /// <returns></returns>
public static bool IsHistoryLoadingNeeded() public static bool IsHistoryLoadingNeeded()
{ {
Log.InfoFormat("Checking if imgur cache loading needed, configuration has {0} imgur hashes, loaded are {1} hashes.", Config.ImgurUploadHistory.Count, Config.runtimeImgurHistory.Count); Log.InfoFormat("Checking if imgur cache loading needed, configuration has {0} imgur hashes, loaded are {1} hashes.", Config.ImgurUploadHistory.Count,
Config.runtimeImgurHistory.Count);
return Config.runtimeImgurHistory.Count != Config.ImgurUploadHistory.Count; return Config.runtimeImgurHistory.Count != Config.ImgurUploadHistory.Count;
} }
/// <summary> /// <summary>
/// Load the complete history of the imgur uploads, with the corresponding information /// Load the complete history of the imgur uploads, with the corresponding information
/// </summary> /// </summary>
public static void LoadHistory() { public static void LoadHistory()
{
if (!IsHistoryLoadingNeeded()) if (!IsHistoryLoadingNeeded())
{ {
return; return;
@ -61,8 +65,10 @@ namespace Greenshot.Plugin.Imgur {
bool saveNeeded = false; bool saveNeeded = false;
// Load the ImUr history // Load the ImUr history
foreach (string hash in Config.ImgurUploadHistory.Keys.ToList()) { foreach (string hash in Config.ImgurUploadHistory.Keys.ToList())
if (Config.runtimeImgurHistory.ContainsKey(hash)) { {
if (Config.runtimeImgurHistory.ContainsKey(hash))
{
// Already loaded // Already loaded
continue; continue;
} }
@ -71,41 +77,55 @@ namespace Greenshot.Plugin.Imgur {
{ {
var deleteHash = Config.ImgurUploadHistory[hash]; var deleteHash = Config.ImgurUploadHistory[hash];
ImgurInfo imgurInfo = RetrieveImgurInfo(hash, deleteHash); ImgurInfo imgurInfo = RetrieveImgurInfo(hash, deleteHash);
if (imgurInfo != null) { if (imgurInfo != null)
{
RetrieveImgurThumbnail(imgurInfo); RetrieveImgurThumbnail(imgurInfo);
Config.runtimeImgurHistory[hash] = imgurInfo; Config.runtimeImgurHistory[hash] = imgurInfo;
} else { }
else
{
Log.InfoFormat("Deleting unknown ImgUr {0} from config, delete hash was {1}.", hash, deleteHash); Log.InfoFormat("Deleting unknown ImgUr {0} from config, delete hash was {1}.", hash, deleteHash);
Config.ImgurUploadHistory.Remove(hash); Config.ImgurUploadHistory.Remove(hash);
Config.runtimeImgurHistory.Remove(hash); Config.runtimeImgurHistory.Remove(hash);
saveNeeded = true; saveNeeded = true;
} }
} catch (WebException wE) { }
catch (WebException wE)
{
bool redirected = false; bool redirected = false;
if (wE.Status == WebExceptionStatus.ProtocolError) { if (wE.Status == WebExceptionStatus.ProtocolError)
HttpWebResponse response = (HttpWebResponse)wE.Response; {
HttpWebResponse response = (HttpWebResponse) wE.Response;
if (response.StatusCode == HttpStatusCode.Forbidden) if (response.StatusCode == HttpStatusCode.Forbidden)
{ {
Log.Error("Imgur loading forbidden", wE); Log.Error("Imgur loading forbidden", wE);
break; break;
} }
// Image no longer available? // Image no longer available?
if (response.StatusCode == HttpStatusCode.Redirect) { if (response.StatusCode == HttpStatusCode.Redirect)
{
Log.InfoFormat("ImgUr image for hash {0} is no longer available, removing it from the history", hash); Log.InfoFormat("ImgUr image for hash {0} is no longer available, removing it from the history", hash);
Config.ImgurUploadHistory.Remove(hash); Config.ImgurUploadHistory.Remove(hash);
Config.runtimeImgurHistory.Remove(hash); Config.runtimeImgurHistory.Remove(hash);
redirected = true; redirected = true;
} }
} }
if (!redirected) {
if (!redirected)
{
Log.Error("Problem loading ImgUr history for hash " + hash, wE); Log.Error("Problem loading ImgUr history for hash " + hash, wE);
} }
} catch (Exception e) { }
catch (Exception e)
{
Log.Error("Problem loading ImgUr history for hash " + hash, e); Log.Error("Problem loading ImgUr history for hash " + hash, e);
} }
} }
if (saveNeeded) {
if (saveNeeded)
{
// Save needed changes // Save needed changes
IniConfig.Save(); IniConfig.Save();
} }
@ -115,7 +135,8 @@ namespace Greenshot.Plugin.Imgur {
/// Use this to make sure Imgur knows from where the upload comes. /// Use this to make sure Imgur knows from where the upload comes.
/// </summary> /// </summary>
/// <param name="webRequest"></param> /// <param name="webRequest"></param>
private static void SetClientId(HttpWebRequest webRequest) { private static void SetClientId(HttpWebRequest webRequest)
{
webRequest.Headers.Add("Authorization", "Client-ID " + ImgurCredentials.CONSUMER_KEY); webRequest.Headers.Add("Authorization", "Client-ID " + ImgurCredentials.CONSUMER_KEY);
} }
@ -128,27 +149,36 @@ namespace Greenshot.Plugin.Imgur {
/// <param name="title">Title</param> /// <param name="title">Title</param>
/// <param name="filename">Filename</param> /// <param name="filename">Filename</param>
/// <returns>ImgurInfo with details</returns> /// <returns>ImgurInfo with details</returns>
public static ImgurInfo UploadToImgur(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename) { public static ImgurInfo UploadToImgur(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename)
{
IDictionary<string, object> otherParameters = new Dictionary<string, object>(); IDictionary<string, object> otherParameters = new Dictionary<string, object>();
// add title // add title
if (title != null && Config.AddTitle) { if (title != null && Config.AddTitle)
otherParameters["title"]= title; {
otherParameters["title"] = title;
} }
// add filename // add filename
if (filename != null && Config.AddFilename) { if (filename != null && Config.AddFilename)
{
otherParameters["name"] = filename; otherParameters["name"] = filename;
} }
string responseString = null; string responseString = null;
if (Config.AnonymousAccess) { if (Config.AnonymousAccess)
{
// add key, we only use the other parameters for the AnonymousAccess // add key, we only use the other parameters for the AnonymousAccess
//otherParameters.Add("key", IMGUR_ANONYMOUS_API_KEY); //otherParameters.Add("key", IMGUR_ANONYMOUS_API_KEY);
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(Config.ImgurApi3Url + "/upload.xml?" + NetworkHelper.GenerateQueryParameters(otherParameters), HTTPMethod.POST); HttpWebRequest webRequest =
NetworkHelper.CreateWebRequest(Config.ImgurApi3Url + "/upload.xml?" + NetworkHelper.GenerateQueryParameters(otherParameters), HTTPMethod.POST);
webRequest.ContentType = "image/" + outputSettings.Format; webRequest.ContentType = "image/" + outputSettings.Format;
webRequest.ServicePoint.Expect100Continue = false; webRequest.ServicePoint.Expect100Continue = false;
SetClientId(webRequest); SetClientId(webRequest);
try { try
using (var requestStream = webRequest.GetRequestStream()) { {
using (var requestStream = webRequest.GetRequestStream())
{
ImageOutput.SaveToStream(surfaceToUpload, requestStream, outputSettings); ImageOutput.SaveToStream(surfaceToUpload, requestStream, outputSettings);
} }
@ -160,12 +190,15 @@ namespace Greenshot.Plugin.Imgur {
using StreamReader reader = new StreamReader(responseStream, true); using StreamReader reader = new StreamReader(responseStream, true);
responseString = reader.ReadToEnd(); responseString = reader.ReadToEnd();
} }
} catch (Exception ex) { }
catch (Exception ex)
{
Log.Error("Upload to imgur gave an exception: ", ex); Log.Error("Upload to imgur gave an exception: ", ex);
throw; throw;
} }
} else { }
else
{
var oauth2Settings = new OAuth2Settings var oauth2Settings = new OAuth2Settings
{ {
AuthUrlPattern = "https://api.imgur.com/oauth2/authorize?response_type=token&client_id={ClientId}&state={State}", AuthUrlPattern = "https://api.imgur.com/oauth2/authorize?response_type=token&client_id={ClientId}&state={State}",
@ -201,10 +234,12 @@ namespace Greenshot.Plugin.Imgur {
IniConfig.Save(); IniConfig.Save();
} }
} }
if (string.IsNullOrEmpty(responseString)) if (string.IsNullOrEmpty(responseString))
{ {
return null; return null;
} }
return ImgurInfo.ParseResponse(responseString); return ImgurInfo.ParseResponse(responseString);
} }
@ -212,11 +247,14 @@ namespace Greenshot.Plugin.Imgur {
/// Retrieve the thumbnail of an imgur image /// Retrieve the thumbnail of an imgur image
/// </summary> /// </summary>
/// <param name="imgurInfo"></param> /// <param name="imgurInfo"></param>
public static void RetrieveImgurThumbnail(ImgurInfo imgurInfo) { public static void RetrieveImgurThumbnail(ImgurInfo imgurInfo)
if (imgurInfo.SmallSquare == null) { {
if (imgurInfo.SmallSquare == null)
{
Log.Warn("Imgur URL was null, not retrieving thumbnail."); Log.Warn("Imgur URL was null, not retrieving thumbnail.");
return; return;
} }
Log.InfoFormat("Retrieving Imgur image for {0} with url {1}", imgurInfo.Hash, imgurInfo.SmallSquare); Log.InfoFormat("Retrieving Imgur image for {0} with url {1}", imgurInfo.Hash, imgurInfo.SmallSquare);
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(string.Format(SmallUrlPattern, imgurInfo.Hash), HTTPMethod.GET); HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(string.Format(SmallUrlPattern, imgurInfo.Hash), HTTPMethod.GET);
webRequest.ServicePoint.Expect100Continue = false; webRequest.ServicePoint.Expect100Continue = false;
@ -237,7 +275,8 @@ namespace Greenshot.Plugin.Imgur {
/// <param name="hash"></param> /// <param name="hash"></param>
/// <param name="deleteHash"></param> /// <param name="deleteHash"></param>
/// <returns>ImgurInfo</returns> /// <returns>ImgurInfo</returns>
public static ImgurInfo RetrieveImgurInfo(string hash, string deleteHash) { public static ImgurInfo RetrieveImgurInfo(string hash, string deleteHash)
{
string url = Config.ImgurApi3Url + "/image/" + hash + ".xml"; string url = Config.ImgurApi3Url + "/image/" + hash + ".xml";
Log.InfoFormat("Retrieving Imgur info for {0} with url {1}", hash, url); Log.InfoFormat("Retrieving Imgur info for {0} with url {1}", hash, url);
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, HTTPMethod.GET); HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, HTTPMethod.GET);
@ -254,14 +293,20 @@ namespace Greenshot.Plugin.Imgur {
using StreamReader reader = new StreamReader(responseStream, true); using StreamReader reader = new StreamReader(responseStream, true);
responseString = reader.ReadToEnd(); responseString = reader.ReadToEnd();
} }
} catch (WebException wE) { }
if (wE.Status == WebExceptionStatus.ProtocolError) { catch (WebException wE)
if (((HttpWebResponse)wE.Response).StatusCode == HttpStatusCode.NotFound) { {
if (wE.Status == WebExceptionStatus.ProtocolError)
{
if (((HttpWebResponse) wE.Response).StatusCode == HttpStatusCode.NotFound)
{
return null; return null;
} }
} }
throw; throw;
} }
ImgurInfo imgurInfo = null; ImgurInfo imgurInfo = null;
if (responseString != null) if (responseString != null)
{ {
@ -269,6 +314,7 @@ namespace Greenshot.Plugin.Imgur {
imgurInfo = ImgurInfo.ParseResponse(responseString); imgurInfo = ImgurInfo.ParseResponse(responseString);
imgurInfo.DeleteHash = deleteHash; imgurInfo.DeleteHash = deleteHash;
} }
return imgurInfo; return imgurInfo;
} }
@ -276,16 +322,19 @@ namespace Greenshot.Plugin.Imgur {
/// Delete an imgur image, this is done by specifying the delete hash /// Delete an imgur image, this is done by specifying the delete hash
/// </summary> /// </summary>
/// <param name="imgurInfo"></param> /// <param name="imgurInfo"></param>
public static void DeleteImgurImage(ImgurInfo imgurInfo) { public static void DeleteImgurImage(ImgurInfo imgurInfo)
{
Log.InfoFormat("Deleting Imgur image for {0}", imgurInfo.DeleteHash); Log.InfoFormat("Deleting Imgur image for {0}", imgurInfo.DeleteHash);
try { try
{
string url = Config.ImgurApi3Url + "/image/" + imgurInfo.DeleteHash + ".xml"; string url = Config.ImgurApi3Url + "/image/" + imgurInfo.DeleteHash + ".xml";
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, HTTPMethod.DELETE); HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, HTTPMethod.DELETE);
webRequest.ServicePoint.Expect100Continue = false; webRequest.ServicePoint.Expect100Continue = false;
SetClientId(webRequest); SetClientId(webRequest);
string responseString = null; string responseString = null;
using (WebResponse response = webRequest.GetResponse()) { using (WebResponse response = webRequest.GetResponse())
{
LogRateLimitInfo(response); LogRateLimitInfo(response);
var responseStream = response.GetResponseStream(); var responseStream = response.GetResponseStream();
if (responseStream != null) if (responseStream != null)
@ -294,15 +343,21 @@ namespace Greenshot.Plugin.Imgur {
responseString = reader.ReadToEnd(); responseString = reader.ReadToEnd();
} }
} }
Log.InfoFormat("Delete result: {0}", responseString); Log.InfoFormat("Delete result: {0}", responseString);
} catch (WebException wE) { }
catch (WebException wE)
{
// Allow "Bad request" this means we already deleted it // Allow "Bad request" this means we already deleted it
if (wE.Status == WebExceptionStatus.ProtocolError) { if (wE.Status == WebExceptionStatus.ProtocolError)
if (((HttpWebResponse)wE.Response).StatusCode != HttpStatusCode.BadRequest) { {
throw ; if (((HttpWebResponse) wE.Response).StatusCode != HttpStatusCode.BadRequest)
{
throw;
} }
} }
} }
// Make sure we remove it from the history, if no error occurred // Make sure we remove it from the history, if no error occurred
Config.runtimeImgurHistory.Remove(imgurInfo.Hash); Config.runtimeImgurHistory.Remove(imgurInfo.Hash);
Config.ImgurUploadHistory.Remove(imgurInfo.Hash); Config.ImgurUploadHistory.Remove(imgurInfo.Hash);
@ -314,8 +369,10 @@ namespace Greenshot.Plugin.Imgur {
/// </summary> /// </summary>
/// <param name="nameValues"></param> /// <param name="nameValues"></param>
/// <param name="key"></param> /// <param name="key"></param>
private static void LogHeader(IDictionary<string, string> nameValues, string key) { private static void LogHeader(IDictionary<string, string> nameValues, string key)
if (nameValues.ContainsKey(key)) { {
if (nameValues.ContainsKey(key))
{
Log.InfoFormat("{0}={1}", key, nameValues[key]); Log.InfoFormat("{0}={1}", key, nameValues[key]);
} }
} }
@ -324,13 +381,17 @@ namespace Greenshot.Plugin.Imgur {
/// Log the current rate-limit information /// Log the current rate-limit information
/// </summary> /// </summary>
/// <param name="response"></param> /// <param name="response"></param>
private static void LogRateLimitInfo(WebResponse response) { private static void LogRateLimitInfo(WebResponse response)
{
IDictionary<string, string> nameValues = new Dictionary<string, string>(); IDictionary<string, string> nameValues = new Dictionary<string, string>();
foreach (string key in response.Headers.AllKeys) { foreach (string key in response.Headers.AllKeys)
if (!nameValues.ContainsKey(key)) { {
if (!nameValues.ContainsKey(key))
{
nameValues.Add(key, response.Headers[key]); nameValues.Add(key, response.Headers[key]);
} }
} }
LogHeader(nameValues, "X-RateLimit-Limit"); LogHeader(nameValues, "X-RateLimit-Limit");
LogHeader(nameValues, "X-RateLimit-Remaining"); LogHeader(nameValues, "X-RateLimit-Remaining");
LogHeader(nameValues, "X-RateLimit-UserLimit"); LogHeader(nameValues, "X-RateLimit-UserLimit");
@ -340,7 +401,8 @@ namespace Greenshot.Plugin.Imgur {
LogHeader(nameValues, "X-RateLimit-ClientRemaining"); LogHeader(nameValues, "X-RateLimit-ClientRemaining");
// Update the credits in the config, this is shown in a form // Update the credits in the config, this is shown in a form
if (nameValues.ContainsKey("X-RateLimit-Remaining") && int.TryParse(nameValues["X-RateLimit-Remaining"], out var credits)) { if (nameValues.ContainsKey("X-RateLimit-Remaining") && int.TryParse(nameValues["X-RateLimit-Remaining"], out var credits))
{
Config.Credits = credits; Config.Credits = credits;
} }
} }

View file

@ -19,8 +19,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Greenshot.Plugin.Imgur { namespace Greenshot.Plugin.Imgur
public enum LangKey { {
public enum LangKey
{
upload_menu_item, upload_menu_item,
upload_failure, upload_failure,
communication_wait, communication_wait,

View file

@ -114,6 +114,7 @@ namespace Greenshot.Plugin.Jira
{ {
cacheItemPolicy.UpdateCallback = UpdateCallback; cacheItemPolicy.UpdateCallback = UpdateCallback;
} }
if (ActivateRemovedCallback) if (ActivateRemovedCallback)
{ {
cacheItemPolicy.RemovedCallback = RemovedCallback; cacheItemPolicy.RemovedCallback = RemovedCallback;

View file

@ -30,15 +30,18 @@ using GreenshotPlugin.Controls;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
namespace Greenshot.Plugin.Jira.Forms { namespace Greenshot.Plugin.Jira.Forms
public partial class JiraForm : Form { {
public partial class JiraForm : Form
{
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(JiraForm)); private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(JiraForm));
private readonly JiraConnector _jiraConnector; private readonly JiraConnector _jiraConnector;
private Issue _selectedIssue; private Issue _selectedIssue;
private readonly GreenshotColumnSorter _columnSorter; private readonly GreenshotColumnSorter _columnSorter;
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>(); private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
public JiraForm(JiraConnector jiraConnector) { public JiraForm(JiraConnector jiraConnector)
{
InitializeComponent(); InitializeComponent();
Icon = GreenshotResources.GetGreenshotIcon(); Icon = GreenshotResources.GetGreenshotIcon();
AcceptButton = uploadButton; AcceptButton = uploadButton;
@ -70,6 +73,7 @@ namespace Greenshot.Plugin.Jira.Forms {
{ {
MessageBox.Show(Language.GetFormattedString("jira", LangKey.login_error, e.Message)); MessageBox.Show(Language.GetFormattedString("jira", LangKey.login_error, e.Message));
} }
if (_jiraConnector.IsLoggedIn) if (_jiraConnector.IsLoggedIn)
{ {
var filters = await _jiraConnector.GetFavoriteFiltersAsync(); var filters = await _jiraConnector.GetFavoriteFiltersAsync();
@ -79,8 +83,10 @@ namespace Greenshot.Plugin.Jira.Forms {
{ {
jiraFilterBox.Items.Add(filter); jiraFilterBox.Items.Add(filter);
} }
jiraFilterBox.SelectedIndex = 0; jiraFilterBox.SelectedIndex = 0;
} }
ChangeModus(true); ChangeModus(true);
if (_jiraConnector.Monitor.RecentJiras.Any()) if (_jiraConnector.Monitor.RecentJiras.Any())
{ {
@ -91,44 +97,53 @@ namespace Greenshot.Plugin.Jira.Forms {
} }
} }
private void InitializeComponentText() { private void InitializeComponentText()
{
label_jirafilter.Text = Language.GetString("jira", LangKey.label_jirafilter); label_jirafilter.Text = Language.GetString("jira", LangKey.label_jirafilter);
label_comment.Text = Language.GetString("jira", LangKey.label_comment); label_comment.Text = Language.GetString("jira", LangKey.label_comment);
label_filename.Text = Language.GetString("jira", LangKey.label_filename); label_filename.Text = Language.GetString("jira", LangKey.label_filename);
} }
private void ChangeModus(bool enabled) { private void ChangeModus(bool enabled)
{
jiraFilterBox.Enabled = enabled; jiraFilterBox.Enabled = enabled;
jiraListView.Enabled = enabled; jiraListView.Enabled = enabled;
jiraFilenameBox.Enabled = enabled; jiraFilenameBox.Enabled = enabled;
jiraCommentBox.Enabled = enabled; jiraCommentBox.Enabled = enabled;
} }
public void SetFilename(string filename) { public void SetFilename(string filename)
{
jiraFilenameBox.Text = filename; jiraFilenameBox.Text = filename;
} }
public Issue GetJiraIssue() { public Issue GetJiraIssue()
{
return _selectedIssue; return _selectedIssue;
} }
public async Task UploadAsync(IBinaryContainer attachment) { public async Task UploadAsync(IBinaryContainer attachment)
{
attachment.Filename = jiraFilenameBox.Text; attachment.Filename = jiraFilenameBox.Text;
await _jiraConnector.AttachAsync(_selectedIssue.Key, attachment); await _jiraConnector.AttachAsync(_selectedIssue.Key, attachment);
if (!string.IsNullOrEmpty(jiraCommentBox.Text)) { if (!string.IsNullOrEmpty(jiraCommentBox.Text))
{
await _jiraConnector.AddCommentAsync(_selectedIssue.Key, jiraCommentBox.Text); await _jiraConnector.AddCommentAsync(_selectedIssue.Key, jiraCommentBox.Text);
} }
} }
private async void JiraFilterBox_SelectedIndexChanged(object sender, EventArgs e) { private async void JiraFilterBox_SelectedIndexChanged(object sender, EventArgs e)
if (_jiraConnector.IsLoggedIn) { {
if (_jiraConnector.IsLoggedIn)
{
uploadButton.Enabled = false; uploadButton.Enabled = false;
var filter = (Filter)jiraFilterBox.SelectedItem; var filter = (Filter) jiraFilterBox.SelectedItem;
if (filter == null) { if (filter == null)
{
return; return;
} }
IList<Issue> issues = null; IList<Issue> issues = null;
try try
{ {
@ -141,25 +156,33 @@ namespace Greenshot.Plugin.Jira.Forms {
} }
jiraListView.Items.Clear(); jiraListView.Items.Clear();
if (issues?.Count > 0) { if (issues?.Count > 0)
{
jiraListView.Columns.Clear(); jiraListView.Columns.Clear();
LangKey[] columns = { LangKey.column_issueType, LangKey.column_id, LangKey.column_created, LangKey.column_assignee, LangKey.column_reporter, LangKey.column_summary }; LangKey[] columns =
{
LangKey.column_issueType, LangKey.column_id, LangKey.column_created, LangKey.column_assignee, LangKey.column_reporter, LangKey.column_summary
};
foreach (LangKey column in columns) foreach (LangKey column in columns)
{ {
if (!Language.TryGetString("jira", column, out var translation)) if (!Language.TryGetString("jira", column, out var translation))
{ {
translation = string.Empty; translation = string.Empty;
} }
jiraListView.Columns.Add(translation); jiraListView.Columns.Add(translation);
} }
var scaledIconSize = DpiHelper.ScaleWithDpi(CoreConfig.IconSize, DpiHelper.GetDpi(Handle)); var scaledIconSize = DpiHelper.ScaleWithDpi(CoreConfig.IconSize, DpiHelper.GetDpi(Handle));
var imageList = new ImageList { var imageList = new ImageList
{
ImageSize = scaledIconSize ImageSize = scaledIconSize
}; };
jiraListView.SmallImageList = imageList; jiraListView.SmallImageList = imageList;
jiraListView.LargeImageList = imageList; jiraListView.LargeImageList = imageList;
foreach (var issue in issues) { foreach (var issue in issues)
{
var item = new ListViewItem var item = new ListViewItem
{ {
Tag = issue Tag = issue
@ -187,6 +210,7 @@ namespace Greenshot.Plugin.Jira.Forms {
{ {
jiraListView.AutoResizeColumn(i, ColumnHeaderAutoResizeStyle.ColumnContent); jiraListView.AutoResizeColumn(i, ColumnHeaderAutoResizeStyle.ColumnContent);
} }
jiraListView.Invalidate(); jiraListView.Invalidate();
jiraListView.Update(); jiraListView.Update();
} }
@ -196,22 +220,30 @@ namespace Greenshot.Plugin.Jira.Forms {
} }
} }
private void JiraListView_SelectedIndexChanged(object sender, EventArgs e) { private void JiraListView_SelectedIndexChanged(object sender, EventArgs e)
if (jiraListView.SelectedItems.Count > 0) { {
_selectedIssue = (Issue)jiraListView.SelectedItems[0].Tag; if (jiraListView.SelectedItems.Count > 0)
{
_selectedIssue = (Issue) jiraListView.SelectedItems[0].Tag;
jiraKey.Text = _selectedIssue.Key; jiraKey.Text = _selectedIssue.Key;
uploadButton.Enabled = true; uploadButton.Enabled = true;
} else { }
else
{
uploadButton.Enabled = false; uploadButton.Enabled = false;
} }
} }
private void JiraListView_ColumnClick(object sender, ColumnClickEventArgs e) { private void JiraListView_ColumnClick(object sender, ColumnClickEventArgs e)
{
// Determine if clicked column is already the column that is being sorted. // Determine if clicked column is already the column that is being sorted.
if (e.Column == _columnSorter.SortColumn) { if (e.Column == _columnSorter.SortColumn)
{
// Reverse the current sort direction for this column. // Reverse the current sort direction for this column.
_columnSorter.Order = _columnSorter.Order == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending; _columnSorter.Order = _columnSorter.Order == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
} else { }
else
{
// Set the column number that is to be sorted; default to ascending. // Set the column number that is to be sorted; default to ascending.
_columnSorter.SortColumn = e.Column; _columnSorter.SortColumn = e.Column;
_columnSorter.Order = SortOrder.Ascending; _columnSorter.Order = SortOrder.Ascending;
@ -221,13 +253,16 @@ namespace Greenshot.Plugin.Jira.Forms {
jiraListView.Sort(); jiraListView.Sort();
} }
private async void JiraKeyTextChanged(object sender, EventArgs e) { private async void JiraKeyTextChanged(object sender, EventArgs e)
{
string jiranumber = jiraKey.Text; string jiranumber = jiraKey.Text;
uploadButton.Enabled = false; uploadButton.Enabled = false;
int dashIndex = jiranumber.IndexOf('-'); int dashIndex = jiranumber.IndexOf('-');
if (dashIndex > 0 && jiranumber.Length > dashIndex+1) { if (dashIndex > 0 && jiranumber.Length > dashIndex + 1)
{
_selectedIssue = await _jiraConnector.GetIssueAsync(jiraKey.Text); _selectedIssue = await _jiraConnector.GetIssueAsync(jiraKey.Text);
if (_selectedIssue != null) { if (_selectedIssue != null)
{
uploadButton.Enabled = true; uploadButton.Enabled = true;
} }
} }

View file

@ -21,7 +21,9 @@
using GreenshotPlugin.Controls; using GreenshotPlugin.Controls;
namespace Greenshot.Plugin.Jira.Forms { namespace Greenshot.Plugin.Jira.Forms
public class JiraFormBase : GreenshotForm { {
public class JiraFormBase : GreenshotForm
{
} }
} }

View file

@ -19,11 +19,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Greenshot.Plugin.Jira.Forms { namespace Greenshot.Plugin.Jira.Forms
{
/// <summary> /// <summary>
/// Description of PasswordRequestForm. /// Description of PasswordRequestForm.
/// </summary> /// </summary>
public partial class SettingsForm : JiraFormBase { public partial class SettingsForm : JiraFormBase
{
public SettingsForm() public SettingsForm()
{ {
// //

View file

@ -22,25 +22,27 @@
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
namespace Greenshot.Plugin.Jira { namespace Greenshot.Plugin.Jira
{
/// <summary> /// <summary>
/// Description of JiraConfiguration. /// Description of JiraConfiguration.
/// </summary> /// </summary>
[IniSection("Jira", Description="Greenshot Jira Plugin configuration")] [IniSection("Jira", Description = "Greenshot Jira Plugin configuration")]
public class JiraConfiguration : IniSection { public class JiraConfiguration : IniSection
{
public const string DefaultPrefix = "http://"; public const string DefaultPrefix = "http://";
private const string DefaultUrl = DefaultPrefix + "jira"; private const string DefaultUrl = DefaultPrefix + "jira";
[IniProperty("Url", Description="Base url to Jira system, without anything else", DefaultValue=DefaultUrl)] [IniProperty("Url", Description = "Base url to Jira system, without anything else", DefaultValue = DefaultUrl)]
public string Url { get; set; } public string Url { get; set; }
[IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")] [IniProperty("UploadFormat", Description = "What file type to use for uploading", DefaultValue = "png")]
public OutputFormat UploadFormat { get; set; } public OutputFormat UploadFormat { get; set; }
[IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")] [IniProperty("UploadJpegQuality", Description = "JPEG file save quality in %.", DefaultValue = "80")]
public int UploadJpegQuality { get; set; } public int UploadJpegQuality { get; set; }
[IniProperty("UploadReduceColors", Description="Reduce color amount of the uploaded image to 256", DefaultValue="False")] [IniProperty("UploadReduceColors", Description = "Reduce color amount of the uploaded image to 256", DefaultValue = "False")]
public bool UploadReduceColors { get; set; } public bool UploadReduceColors { get; set; }
} }
} }

View file

@ -34,14 +34,18 @@ using Dapplo.Jira.SvgWinForms.Converters;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
namespace Greenshot.Plugin.Jira { namespace Greenshot.Plugin.Jira
{
/// <summary> /// <summary>
/// This encapsulates the JiraClient to make it possible to change as less old Greenshot code as needed /// This encapsulates the JiraClient to make it possible to change as less old Greenshot code as needed
/// </summary> /// </summary>
public sealed class JiraConnector : IDisposable { public sealed class JiraConnector : IDisposable
{
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(JiraConnector)); private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(JiraConnector));
private static readonly JiraConfiguration JiraConfig = IniConfig.GetIniSection<JiraConfiguration>(); private static readonly JiraConfiguration JiraConfig = IniConfig.GetIniSection<JiraConfiguration>();
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>(); private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
// Used to remove the wsdl information from the old SOAP Uri // Used to remove the wsdl information from the old SOAP Uri
public const string DefaultPostfix = "/rpc/soap/jirasoapservice-v2?wsdl"; public const string DefaultPostfix = "/rpc/soap/jirasoapservice-v2?wsdl";
private IJiraClient _jiraClient; private IJiraClient _jiraClient;
@ -57,20 +61,25 @@ namespace Greenshot.Plugin.Jira {
if (args.PropertyName == nameof(CoreConfig.IconSize)) if (args.PropertyName == nameof(CoreConfig.IconSize))
{ {
var jiraConnector = SimpleServiceProvider.Current.GetInstance<JiraConnector>(); var jiraConnector = SimpleServiceProvider.Current.GetInstance<JiraConnector>();
jiraConnector._jiraClient?.Behaviour.SetConfig(new SvgConfiguration { Width = CoreConfig.ScaledIconSize.Width, Height = CoreConfig.ScaledIconSize.Height }); jiraConnector._jiraClient?.Behaviour.SetConfig(new SvgConfiguration
{
Width = CoreConfig.ScaledIconSize.Width,
Height = CoreConfig.ScaledIconSize.Height
});
} }
}; };
} }
/// <summary> /// <summary>
/// Dispose, logout the users /// Dispose, logout the users
/// </summary> /// </summary>
public void Dispose() { public void Dispose()
{
if (_jiraClient != null) if (_jiraClient != null)
{ {
Logout(); Logout();
} }
FavIcon?.Dispose(); FavIcon?.Dispose();
} }
@ -99,8 +108,13 @@ namespace Greenshot.Plugin.Jira {
{ {
return false; return false;
} }
_jiraClient = JiraClient.Create(new Uri(JiraConfig.Url)); _jiraClient = JiraClient.Create(new Uri(JiraConfig.Url));
_jiraClient.Behaviour.SetConfig(new SvgConfiguration { Width = CoreConfig.ScaledIconSize.Width, Height = CoreConfig.ScaledIconSize.Height }); _jiraClient.Behaviour.SetConfig(new SvgConfiguration
{
Width = CoreConfig.ScaledIconSize.Width,
Height = CoreConfig.ScaledIconSize.Height
});
_jiraClient.SetBasicAuthentication(user, password); _jiraClient.SetBasicAuthentication(user, password);
_issueTypeBitmapCache = new IssueTypeBitmapCache(_jiraClient); _issueTypeBitmapCache = new IssueTypeBitmapCache(_jiraClient);
@ -126,6 +140,7 @@ namespace Greenshot.Plugin.Jira {
Log.Warn("Exception details: ", ex2); Log.Warn("Exception details: ", ex2);
return false; return false;
} }
return true; return true;
} }
@ -134,45 +149,58 @@ namespace Greenshot.Plugin.Jira {
/// If there are credentials, call the real login. /// If there are credentials, call the real login.
/// </summary> /// </summary>
/// <returns>Task</returns> /// <returns>Task</returns>
public async Task LoginAsync(CancellationToken cancellationToken = default) { public async Task LoginAsync(CancellationToken cancellationToken = default)
{
Logout(); Logout();
try { try
{
// Get the system name, so the user knows where to login to // Get the system name, so the user knows where to login to
var credentialsDialog = new CredentialsDialog(JiraConfig.Url) var credentialsDialog = new CredentialsDialog(JiraConfig.Url)
{ {
Name = null Name = null
}; };
while (credentialsDialog.Show(credentialsDialog.Name) == DialogResult.OK) { while (credentialsDialog.Show(credentialsDialog.Name) == DialogResult.OK)
if (await DoLoginAsync(credentialsDialog.Name, credentialsDialog.Password, cancellationToken)) { {
if (credentialsDialog.SaveChecked) { if (await DoLoginAsync(credentialsDialog.Name, credentialsDialog.Password, cancellationToken))
{
if (credentialsDialog.SaveChecked)
{
credentialsDialog.Confirm(true); credentialsDialog.Confirm(true);
} }
IsLoggedIn = true; IsLoggedIn = true;
return; return;
} }
// Login failed, confirm this // Login failed, confirm this
try { try
{
credentialsDialog.Confirm(false); credentialsDialog.Confirm(false);
} catch (ApplicationException e) { }
catch (ApplicationException e)
{
// exception handling ... // exception handling ...
Log.Error("Problem using the credentials dialog", e); Log.Error("Problem using the credentials dialog", e);
} }
// For every windows version after XP show an incorrect password baloon // For every windows version after XP show an incorrect password baloon
credentialsDialog.IncorrectPassword = true; credentialsDialog.IncorrectPassword = true;
// Make sure the dialog is display, the password was false! // Make sure the dialog is display, the password was false!
credentialsDialog.AlwaysDisplay = true; credentialsDialog.AlwaysDisplay = true;
} }
} catch (ApplicationException e) { }
catch (ApplicationException e)
{
// exception handling ... // exception handling ...
Log.Error("Problem using the credentials dialog", e); Log.Error("Problem using the credentials dialog", e);
} }
} }
/// <summary> /// <summary>
/// End the session, if there was one /// End the session, if there was one
/// </summary> /// </summary>
public void Logout() { public void Logout()
{
if (_jiraClient == null || !IsLoggedIn) return; if (_jiraClient == null || !IsLoggedIn) return;
Monitor.Dispose(); Monitor.Dispose();
IsLoggedIn = false; IsLoggedIn = false;
@ -183,8 +211,10 @@ namespace Greenshot.Plugin.Jira {
/// Do not use ConfigureAwait to call this, as it will move await from the UI thread. /// Do not use ConfigureAwait to call this, as it will move await from the UI thread.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
private async Task CheckCredentialsAsync(CancellationToken cancellationToken = default) { private async Task CheckCredentialsAsync(CancellationToken cancellationToken = default)
if (!IsLoggedIn) { {
if (!IsLoggedIn)
{
await LoginAsync(cancellationToken); await LoginAsync(cancellationToken);
} }
} }
@ -256,7 +286,10 @@ namespace Greenshot.Plugin.Jira {
public async Task<IList<Issue>> SearchAsync(Filter filter, CancellationToken cancellationToken = default) public async Task<IList<Issue>> SearchAsync(Filter filter, CancellationToken cancellationToken = default)
{ {
await CheckCredentialsAsync(cancellationToken); await CheckCredentialsAsync(cancellationToken);
var searchResult = await _jiraClient.Issue.SearchAsync(filter.Jql, null, new[] { "summary", "reporter", "assignee", "created", "issuetype" }, null, cancellationToken).ConfigureAwait(false); var searchResult = await _jiraClient.Issue.SearchAsync(filter.Jql, null, new[]
{
"summary", "reporter", "assignee", "created", "issuetype"
}, null, cancellationToken).ConfigureAwait(false);
return searchResult.Issues; return searchResult.Issues;
} }

View file

@ -34,27 +34,33 @@ using GreenshotPlugin.IniFile;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin; using GreenshotPlugin.Interfaces.Plugin;
namespace Greenshot.Plugin.Jira { namespace Greenshot.Plugin.Jira
{
/// <summary> /// <summary>
/// Description of JiraDestination. /// Description of JiraDestination.
/// </summary> /// </summary>
public class JiraDestination : AbstractDestination { public class JiraDestination : AbstractDestination
{
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(JiraDestination)); private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(JiraDestination));
private static readonly JiraConfiguration Config = IniConfig.GetIniSection<JiraConfiguration>(); private static readonly JiraConfiguration Config = IniConfig.GetIniSection<JiraConfiguration>();
private readonly Issue _jiraIssue; private readonly Issue _jiraIssue;
public JiraDestination(Issue jiraIssue = null) { public JiraDestination(Issue jiraIssue = null)
{
_jiraIssue = jiraIssue; _jiraIssue = jiraIssue;
} }
public override string Designation => "Jira"; public override string Designation => "Jira";
public override string Description { public override string Description
{
get get
{ {
if (_jiraIssue?.Fields?.Summary == null) { if (_jiraIssue?.Fields?.Summary == null)
{
return Language.GetString("jira", LangKey.upload_menu_item); return Language.GetString("jira", LangKey.upload_menu_item);
} }
// Format the title of this destination // Format the title of this destination
return _jiraIssue.Key + ": " + _jiraIssue.Fields.Summary.Substring(0, Math.Min(20, _jiraIssue.Fields.Summary.Length)); return _jiraIssue.Key + ": " + _jiraIssue.Fields.Summary.Substring(0, Math.Min(20, _jiraIssue.Fields.Summary.Length));
} }
@ -64,7 +70,8 @@ namespace Greenshot.Plugin.Jira {
public override bool IsDynamic => true; public override bool IsDynamic => true;
public override Image DisplayIcon { public override Image DisplayIcon
{
get get
{ {
Image displayIcon = null; Image displayIcon = null;
@ -83,16 +90,19 @@ namespace Greenshot.Plugin.Jira {
Log.Warn($"Problem loading issue type for {_jiraIssue.Key}, ignoring", ex); Log.Warn($"Problem loading issue type for {_jiraIssue.Key}, ignoring", ex);
} }
} }
if (displayIcon == null) if (displayIcon == null)
{ {
displayIcon = jiraConnector.FavIcon; displayIcon = jiraConnector.FavIcon;
} }
} }
if (displayIcon == null) if (displayIcon == null)
{ {
var resources = new ComponentResourceManager(typeof(JiraPlugin)); var resources = new ComponentResourceManager(typeof(JiraPlugin));
displayIcon = (Image)resources.GetObject("Jira"); displayIcon = (Image) resources.GetObject("Jira");
} }
return displayIcon; return displayIcon;
} }
} }
@ -100,22 +110,27 @@ namespace Greenshot.Plugin.Jira {
public override IEnumerable<IDestination> DynamicDestinations() public override IEnumerable<IDestination> DynamicDestinations()
{ {
var jiraConnector = SimpleServiceProvider.Current.GetInstance<JiraConnector>(); var jiraConnector = SimpleServiceProvider.Current.GetInstance<JiraConnector>();
if (jiraConnector == null || !jiraConnector.IsLoggedIn) { if (jiraConnector == null || !jiraConnector.IsLoggedIn)
{
yield break; yield break;
} }
foreach(var jiraDetails in jiraConnector.Monitor.RecentJiras)
foreach (var jiraDetails in jiraConnector.Monitor.RecentJiras)
{ {
yield return new JiraDestination(jiraDetails.JiraIssue); yield return new JiraDestination(jiraDetails.JiraIssue);
} }
} }
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surfaceToUpload, ICaptureDetails captureDetails) { public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surfaceToUpload, ICaptureDetails captureDetails)
{
ExportInformation exportInformation = new ExportInformation(Designation, Description); ExportInformation exportInformation = new ExportInformation(Designation, Description);
string filename = Path.GetFileName(FilenameHelper.GetFilename(Config.UploadFormat, captureDetails)); string filename = Path.GetFileName(FilenameHelper.GetFilename(Config.UploadFormat, captureDetails));
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(Config.UploadFormat, Config.UploadJpegQuality, Config.UploadReduceColors); SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(Config.UploadFormat, Config.UploadJpegQuality, Config.UploadReduceColors);
var jiraConnector = SimpleServiceProvider.Current.GetInstance<JiraConnector>(); var jiraConnector = SimpleServiceProvider.Current.GetInstance<JiraConnector>();
if (_jiraIssue != null) { if (_jiraIssue != null)
try { {
try
{
// Run upload in the background // Run upload in the background
new PleaseWaitForm().ShowAndWait(Description, Language.GetString("jira", LangKey.communication_wait), new PleaseWaitForm().ShowAndWait(Description, Language.GetString("jira", LangKey.communication_wait),
async () => async () =>
@ -128,31 +143,37 @@ namespace Greenshot.Plugin.Jira {
Log.DebugFormat("Uploaded to Jira {0}", _jiraIssue.Key); Log.DebugFormat("Uploaded to Jira {0}", _jiraIssue.Key);
exportInformation.ExportMade = true; exportInformation.ExportMade = true;
exportInformation.Uri = surfaceToUpload.UploadUrl; exportInformation.Uri = surfaceToUpload.UploadUrl;
} catch (Exception e) { }
catch (Exception e)
{
MessageBox.Show(Language.GetString("jira", LangKey.upload_failure) + " " + e.Message); MessageBox.Show(Language.GetString("jira", LangKey.upload_failure) + " " + e.Message);
} }
} else { }
else
{
var jiraForm = new JiraForm(jiraConnector); var jiraForm = new JiraForm(jiraConnector);
jiraForm.SetFilename(filename); jiraForm.SetFilename(filename);
var dialogResult = jiraForm.ShowDialog(); var dialogResult = jiraForm.ShowDialog();
if (dialogResult == DialogResult.OK) { if (dialogResult == DialogResult.OK)
try { {
try
{
surfaceToUpload.UploadUrl = jiraConnector.JiraBaseUri.AppendSegments("browse", jiraForm.GetJiraIssue().Key).AbsoluteUri; surfaceToUpload.UploadUrl = jiraConnector.JiraBaseUri.AppendSegments("browse", jiraForm.GetJiraIssue().Key).AbsoluteUri;
// Run upload in the background // Run upload in the background
new PleaseWaitForm().ShowAndWait(Description, Language.GetString("jira", LangKey.communication_wait), new PleaseWaitForm().ShowAndWait(Description, Language.GetString("jira", LangKey.communication_wait),
async () => async () => { await jiraForm.UploadAsync(new SurfaceContainer(surfaceToUpload, outputSettings, filename)); }
{
await jiraForm.UploadAsync(new SurfaceContainer(surfaceToUpload, outputSettings, filename));
}
); );
Log.DebugFormat("Uploaded to Jira {0}", jiraForm.GetJiraIssue().Key); Log.DebugFormat("Uploaded to Jira {0}", jiraForm.GetJiraIssue().Key);
exportInformation.ExportMade = true; exportInformation.ExportMade = true;
exportInformation.Uri = surfaceToUpload.UploadUrl; exportInformation.Uri = surfaceToUpload.UploadUrl;
} catch(Exception e) { }
catch (Exception e)
{
MessageBox.Show(Language.GetString("jira", LangKey.upload_failure) + " " + e.Message); MessageBox.Show(Language.GetString("jira", LangKey.upload_failure) + " " + e.Message);
} }
} }
} }
ProcessExport(exportInformation, surfaceToUpload); ProcessExport(exportInformation, surfaceToUpload);
return exportInformation; return exportInformation;
} }

View file

@ -31,37 +31,17 @@ namespace Greenshot.Plugin.Jira
FirstSeenAt = SeenAt = DateTimeOffset.Now; FirstSeenAt = SeenAt = DateTimeOffset.Now;
} }
public string ProjectKey public string ProjectKey { get; set; }
{
get;
set;
}
public string Id public string Id { get; set; }
{
get;
set;
}
public string JiraKey => ProjectKey + "-" + Id; public string JiraKey => ProjectKey + "-" + Id;
public Issue JiraIssue public Issue JiraIssue { get; set; }
{
get;
set;
}
public DateTimeOffset FirstSeenAt public DateTimeOffset FirstSeenAt { get; private set; }
{
get;
private set;
}
public DateTimeOffset SeenAt public DateTimeOffset SeenAt { get; set; }
{
get;
set;
}
public int CompareTo(JiraDetails other) public int CompareTo(JiraDetails other)
{ {

View file

@ -25,16 +25,8 @@ namespace Greenshot.Plugin.Jira
{ {
public class JiraEventArgs : EventArgs public class JiraEventArgs : EventArgs
{ {
public JiraEventTypes EventType public JiraEventTypes EventType { get; set; }
{
get;
set;
}
public JiraDetails Details public JiraDetails Details { get; set; }
{
get;
set;
}
} }
} }

View file

@ -31,7 +31,6 @@ using GreenshotPlugin.Hooking;
namespace Greenshot.Plugin.Jira namespace Greenshot.Plugin.Jira
{ {
/// <summary> /// <summary>
/// This class will monitor all _jira activity by registering for title changes /// This class will monitor all _jira activity by registering for title changes
/// It keeps a list of the last "accessed" jiras, and makes it easy to upload to one. /// It keeps a list of the last "accessed" jiras, and makes it easy to upload to one.
@ -44,7 +43,9 @@ namespace Greenshot.Plugin.Jira
private readonly WindowsTitleMonitor _monitor; private readonly WindowsTitleMonitor _monitor;
private readonly IList<IJiraClient> _jiraInstances = new List<IJiraClient>(); private readonly IList<IJiraClient> _jiraInstances = new List<IJiraClient>();
private readonly IDictionary<string, IJiraClient> _projectJiraClientMap = new Dictionary<string, IJiraClient>(); private readonly IDictionary<string, IJiraClient> _projectJiraClientMap = new Dictionary<string, IJiraClient>();
private readonly int _maxEntries; private readonly int _maxEntries;
// TODO: Add issues from issueHistory (JQL -> Where.IssueKey.InIssueHistory()) // TODO: Add issues from issueHistory (JQL -> Where.IssueKey.InIssueHistory())
private IDictionary<string, JiraDetails> _recentJiras = new Dictionary<string, JiraDetails>(); private IDictionary<string, JiraDetails> _recentJiras = new Dictionary<string, JiraDetails>();
@ -79,6 +80,7 @@ namespace Greenshot.Plugin.Jira
{ {
return; return;
} }
// free managed resources // free managed resources
_monitor.TitleChangeEvent -= MonitorTitleChangeEvent; _monitor.TitleChangeEvent -= MonitorTitleChangeEvent;
_monitor.Dispose(); _monitor.Dispose();
@ -143,8 +145,13 @@ namespace Greenshot.Plugin.Jira
var issue = await jiraClient.Issue.GetAsync(jiraDetails.JiraKey).ConfigureAwait(false); var issue = await jiraClient.Issue.GetAsync(jiraDetails.JiraKey).ConfigureAwait(false);
jiraDetails.JiraIssue = issue; jiraDetails.JiraIssue = issue;
} }
// Send event // Send event
JiraEvent?.Invoke(this, new JiraEventArgs { Details = jiraDetails, EventType = JiraEventTypes.DetectedNewJiraIssue }); JiraEvent?.Invoke(this, new JiraEventArgs
{
Details = jiraDetails,
EventType = JiraEventTypes.DetectedNewJiraIssue
});
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -163,11 +170,13 @@ namespace Greenshot.Plugin.Jira
{ {
return; return;
} }
var jiraKeyMatch = _jiraKeyPattern.Match(windowTitle); var jiraKeyMatch = _jiraKeyPattern.Match(windowTitle);
if (!jiraKeyMatch.Success) if (!jiraKeyMatch.Success)
{ {
return; return;
} }
// Found a possible JIRA title // Found a possible JIRA title
var jiraKey = jiraKeyMatch.Value; var jiraKey = jiraKeyMatch.Value;
var jiraKeyParts = jiraKey.Split('-'); var jiraKeyParts = jiraKey.Split('-');
@ -184,11 +193,16 @@ namespace Greenshot.Plugin.Jira
currentJiraDetails.SeenAt = DateTimeOffset.Now; currentJiraDetails.SeenAt = DateTimeOffset.Now;
// Notify the order change // Notify the order change
JiraEvent?.Invoke(this, new JiraEventArgs { Details = currentJiraDetails, EventType = JiraEventTypes.OrderChanged }); JiraEvent?.Invoke(this, new JiraEventArgs
{
Details = currentJiraDetails,
EventType = JiraEventTypes.OrderChanged
});
// Nothing else to do // Nothing else to do
return; return;
} }
// We detected an unknown JIRA, so add it to our list // We detected an unknown JIRA, so add it to our list
currentJiraDetails = new JiraDetails currentJiraDetails = new JiraDetails
{ {
@ -205,6 +219,7 @@ namespace Greenshot.Plugin.Jira
orderby jiraDetails.SeenAt descending orderby jiraDetails.SeenAt descending
select jiraDetails).Take(_maxEntries).ToDictionary(jd => jd.JiraKey, jd => jd); select jiraDetails).Take(_maxEntries).ToDictionary(jd => jd.JiraKey, jd => jd);
} }
// Now we can get the title from JIRA itself // Now we can get the title from JIRA itself
// ReSharper disable once UnusedVariable // ReSharper disable once UnusedVariable
var updateTitleTask = DetectedNewJiraIssueAsync(currentJiraDetails); var updateTitleTask = DetectedNewJiraIssueAsync(currentJiraDetails);

View file

@ -30,21 +30,25 @@ using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin; using GreenshotPlugin.Interfaces.Plugin;
using log4net; using log4net;
namespace Greenshot.Plugin.Jira { namespace Greenshot.Plugin.Jira
{
/// <summary> /// <summary>
/// This is the JiraPlugin base code /// This is the JiraPlugin base code
/// </summary> /// </summary>
[Plugin("Jira", true)] [Plugin("Jira", true)]
public class JiraPlugin : IGreenshotPlugin { public class JiraPlugin : IGreenshotPlugin
{
private static readonly ILog Log = LogManager.GetLogger(typeof(JiraPlugin)); private static readonly ILog Log = LogManager.GetLogger(typeof(JiraPlugin));
private JiraConfiguration _config; private JiraConfiguration _config;
public void Dispose() { public void Dispose()
{
Dispose(true); Dispose(true);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
protected void Dispose(bool disposing) { protected void Dispose(bool disposing)
{
if (disposing) if (disposing)
{ {
var jiraConnector = SimpleServiceProvider.Current.GetInstance<JiraConnector>(); var jiraConnector = SimpleServiceProvider.Current.GetInstance<JiraConnector>();
@ -56,7 +60,8 @@ namespace Greenshot.Plugin.Jira {
/// Implementation of the IGreenshotPlugin.Initialize /// Implementation of the IGreenshotPlugin.Initialize
/// </summary> /// </summary>
/// <returns>true if plugin is initialized, false if not (doesn't show)</returns> /// <returns>true if plugin is initialized, false if not (doesn't show)</returns>
public bool Initialize() { public bool Initialize()
{
// Register configuration (don't need the configuration itself) // Register configuration (don't need the configuration itself)
_config = IniConfig.GetIniSection<JiraConfiguration>(); _config = IniConfig.GetIniSection<JiraConfiguration>();
@ -94,7 +99,8 @@ namespace Greenshot.Plugin.Jira {
return true; return true;
} }
public void Shutdown() { public void Shutdown()
{
Log.Debug("Jira Plugin shutdown."); Log.Debug("Jira Plugin shutdown.");
var jiraConnector = SimpleServiceProvider.Current.GetInstance<JiraConnector>(); var jiraConnector = SimpleServiceProvider.Current.GetInstance<JiraConnector>();
jiraConnector?.Logout(); jiraConnector?.Logout();
@ -103,18 +109,19 @@ namespace Greenshot.Plugin.Jira {
/// <summary> /// <summary>
/// Implementation of the IPlugin.Configure /// Implementation of the IPlugin.Configure
/// </summary> /// </summary>
public void Configure() { public void Configure()
{
string url = _config.Url; string url = _config.Url;
if (ShowConfigDialog()) { if (ShowConfigDialog())
{
// check for re-login // check for re-login
var jiraConnector = SimpleServiceProvider.Current.GetInstance<JiraConnector>(); var jiraConnector = SimpleServiceProvider.Current.GetInstance<JiraConnector>();
if (jiraConnector != null && jiraConnector.IsLoggedIn && !string.IsNullOrEmpty(url)) { if (jiraConnector != null && jiraConnector.IsLoggedIn && !string.IsNullOrEmpty(url))
if (!url.Equals(_config.Url)) {
jiraConnector.Logout();
Task.Run(async () =>
{ {
await jiraConnector.LoginAsync(); if (!url.Equals(_config.Url))
}); {
jiraConnector.Logout();
Task.Run(async () => { await jiraConnector.LoginAsync(); });
} }
} }
} }
@ -132,6 +139,7 @@ namespace Greenshot.Plugin.Jira {
{ {
return true; return true;
} }
return false; return false;
} }
} }

View file

@ -19,8 +19,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Greenshot.Plugin.Jira { namespace Greenshot.Plugin.Jira
public enum LangKey { {
public enum LangKey
{
upload_menu_item, upload_menu_item,
column_assignee, column_assignee,
column_created, column_created,

View file

@ -114,6 +114,7 @@ namespace Greenshot.Plugin.Jira
case LogLevels.Warn: case LogLevels.Warn:
return log.IsWarnEnabled; return log.IsWarnEnabled;
} }
return false; return false;
} }
} }

View file

@ -1,5 +1,6 @@
// Copyright (c) Dapplo and contributors. All rights reserved. // Copyright (c) Dapplo and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Greenshot.Plugin.Office.Com namespace Greenshot.Plugin.Office.Com
{ {
/// <summary> /// <summary>

View file

@ -38,6 +38,7 @@ namespace Greenshot.Plugin.Office.Com
{ {
return; return;
} }
// Do not catch an exception from this. // Do not catch an exception from this.
// You may want to remove these guards depending on // You may want to remove these guards depending on
// what you think the semantics should be. // what you think the semantics should be.
@ -45,6 +46,7 @@ namespace Greenshot.Plugin.Office.Com
{ {
Marshal.ReleaseComObject(ComObject); Marshal.ReleaseComObject(ComObject);
} }
ComObject = default; ComObject = default;
} }
} }

View file

@ -24,6 +24,7 @@ namespace Greenshot.Plugin.Office.Com
{ {
return clsId; return clsId;
} }
return clsId; return clsId;
} }

View file

@ -23,7 +23,7 @@ namespace Greenshot.Plugin.Office.Com
{ {
if (GetActiveObject(ref clsId, IntPtr.Zero, out object comObject).Succeeded()) if (GetActiveObject(ref clsId, IntPtr.Zero, out object comObject).Succeeded())
{ {
return DisposableCom.Create((T)comObject); return DisposableCom.Create((T) comObject);
} }
return null; return null;

View file

@ -28,29 +28,37 @@ using GreenshotPlugin.Core;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin; using GreenshotPlugin.Interfaces.Plugin;
namespace Greenshot.Plugin.Office.Destinations { namespace Greenshot.Plugin.Office.Destinations
{
/// <summary> /// <summary>
/// Description of PowerpointDestination. /// Description of PowerpointDestination.
/// </summary> /// </summary>
public class ExcelDestination : AbstractDestination { public class ExcelDestination : AbstractDestination
{
private const int IconApplication = 0; private const int IconApplication = 0;
private const int IconWorkbook = 1; private const int IconWorkbook = 1;
private static readonly string ExePath; private static readonly string ExePath;
private readonly string _workbookName; private readonly string _workbookName;
static ExcelDestination() { static ExcelDestination()
{
ExePath = PluginUtils.GetExePath("EXCEL.EXE"); ExePath = PluginUtils.GetExePath("EXCEL.EXE");
if (ExePath != null && File.Exists(ExePath)) { if (ExePath != null && File.Exists(ExePath))
{
WindowDetails.AddProcessToExcludeFromFreeze("excel"); WindowDetails.AddProcessToExcludeFromFreeze("excel");
} else { }
else
{
ExePath = null; ExePath = null;
} }
} }
public ExcelDestination() { public ExcelDestination()
{
} }
public ExcelDestination(string workbookName) { public ExcelDestination(string workbookName)
{
_workbookName = workbookName; _workbookName = workbookName;
} }
@ -66,31 +74,42 @@ namespace Greenshot.Plugin.Office.Destinations {
public override Image DisplayIcon => PluginUtils.GetCachedExeIcon(ExePath, !string.IsNullOrEmpty(_workbookName) ? IconWorkbook : IconApplication); public override Image DisplayIcon => PluginUtils.GetCachedExeIcon(ExePath, !string.IsNullOrEmpty(_workbookName) ? IconWorkbook : IconApplication);
public override IEnumerable<IDestination> DynamicDestinations() { public override IEnumerable<IDestination> DynamicDestinations()
foreach (string workbookName in ExcelExporter.GetWorkbooks()) { {
foreach (string workbookName in ExcelExporter.GetWorkbooks())
{
yield return new ExcelDestination(workbookName); yield return new ExcelDestination(workbookName);
} }
} }
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails)
{
ExportInformation exportInformation = new ExportInformation(Designation, Description); ExportInformation exportInformation = new ExportInformation(Designation, Description);
bool createdFile = false; bool createdFile = false;
string imageFile = captureDetails.Filename; string imageFile = captureDetails.Filename;
if (imageFile == null || surface.Modified || !Regex.IsMatch(imageFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$")) { if (imageFile == null || surface.Modified || !Regex.IsMatch(imageFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$"))
{
imageFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat()); imageFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat());
createdFile = true; createdFile = true;
} }
if (_workbookName != null) {
if (_workbookName != null)
{
ExcelExporter.InsertIntoExistingWorkbook(_workbookName, imageFile, surface.Image.Size); ExcelExporter.InsertIntoExistingWorkbook(_workbookName, imageFile, surface.Image.Size);
} else { }
else
{
ExcelExporter.InsertIntoNewWorkbook(imageFile, surface.Image.Size); ExcelExporter.InsertIntoNewWorkbook(imageFile, surface.Image.Size);
} }
exportInformation.ExportMade = true; exportInformation.ExportMade = true;
ProcessExport(exportInformation, surface); ProcessExport(exportInformation, surface);
// Cleanup imageFile if we created it here, so less tmp-files are generated and left // Cleanup imageFile if we created it here, so less tmp-files are generated and left
if (createdFile) { if (createdFile)
{
ImageOutput.DeleteNamedTmpFile(imageFile); ImageOutput.DeleteNamedTmpFile(imageFile);
} }
return exportInformation; return exportInformation;
} }
} }

View file

@ -28,8 +28,10 @@ using Greenshot.Plugin.Office.OfficeExport.Entities;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
namespace Greenshot.Plugin.Office.Destinations { namespace Greenshot.Plugin.Office.Destinations
public class OneNoteDestination : AbstractDestination { {
public class OneNoteDestination : AbstractDestination
{
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(WordDestination)); private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(WordDestination));
private const int ICON_APPLICATION = 0; private const int ICON_APPLICATION = 0;
public const string DESIGNATION = "OneNote"; public const string DESIGNATION = "OneNote";
@ -37,87 +39,105 @@ namespace Greenshot.Plugin.Office.Destinations {
private readonly OneNotePage page; private readonly OneNotePage page;
private readonly OneNoteExporter _oneNoteExporter = new OneNoteExporter(); private readonly OneNoteExporter _oneNoteExporter = new OneNoteExporter();
static OneNoteDestination() { static OneNoteDestination()
{
exePath = PluginUtils.GetExePath("ONENOTE.EXE"); exePath = PluginUtils.GetExePath("ONENOTE.EXE");
if (exePath != null && File.Exists(exePath)) { if (exePath != null && File.Exists(exePath))
{
WindowDetails.AddProcessToExcludeFromFreeze("onenote"); WindowDetails.AddProcessToExcludeFromFreeze("onenote");
} else { }
else
{
exePath = null; exePath = null;
} }
} }
public OneNoteDestination() { public OneNoteDestination()
{
} }
public OneNoteDestination(OneNotePage page) { public OneNoteDestination(OneNotePage page)
{
this.page = page; this.page = page;
} }
public override string Designation { public override string Designation
get { {
return DESIGNATION; get { return DESIGNATION; }
}
} }
public override string Description { public override string Description
get { {
if (page == null) { get
{
if (page == null)
{
return "Microsoft OneNote"; return "Microsoft OneNote";
} else { }
else
{
return page.DisplayName; return page.DisplayName;
} }
} }
} }
public override int Priority { public override int Priority
get { {
return 4; get { return 4; }
}
} }
public override bool IsDynamic { public override bool IsDynamic
get { {
return true; get { return true; }
}
} }
public override bool IsActive { public override bool IsActive
get { {
return base.IsActive && exePath != null; get { return base.IsActive && exePath != null; }
}
} }
public override Image DisplayIcon { public override Image DisplayIcon
get { {
return PluginUtils.GetCachedExeIcon(exePath, ICON_APPLICATION); get { return PluginUtils.GetCachedExeIcon(exePath, ICON_APPLICATION); }
}
} }
public override IEnumerable<IDestination> DynamicDestinations() { public override IEnumerable<IDestination> DynamicDestinations()
foreach (OneNotePage page in _oneNoteExporter.GetPages()) { {
foreach (OneNotePage page in _oneNoteExporter.GetPages())
{
yield return new OneNoteDestination(page); yield return new OneNoteDestination(page);
} }
} }
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails)
{
ExportInformation exportInformation = new ExportInformation(Designation, Description); ExportInformation exportInformation = new ExportInformation(Designation, Description);
if (page == null) { if (page == null)
try { {
try
{
exportInformation.ExportMade = _oneNoteExporter.ExportToNewPage(surface); exportInformation.ExportMade = _oneNoteExporter.ExportToNewPage(surface);
} catch(Exception ex) { }
catch (Exception ex)
{
exportInformation.ErrorMessage = ex.Message; exportInformation.ErrorMessage = ex.Message;
LOG.Error(ex); LOG.Error(ex);
} }
} else { }
try { else
{
try
{
exportInformation.ExportMade = _oneNoteExporter.ExportToPage(surface, page); exportInformation.ExportMade = _oneNoteExporter.ExportToPage(surface, page);
} catch(Exception ex) { }
catch (Exception ex)
{
exportInformation.ErrorMessage = ex.Message; exportInformation.ErrorMessage = ex.Message;
LOG.Error(ex); LOG.Error(ex);
} }
} }
return exportInformation; return exportInformation;
} }
} }

View file

@ -32,11 +32,13 @@ using GreenshotPlugin.Interfaces.Plugin;
using Microsoft.Office.Interop.Outlook; using Microsoft.Office.Interop.Outlook;
using Microsoft.Win32; using Microsoft.Win32;
namespace Greenshot.Plugin.Office.Destinations { namespace Greenshot.Plugin.Office.Destinations
{
/// <summary> /// <summary>
/// Description of OutlookDestination. /// Description of OutlookDestination.
/// </summary> /// </summary>
public class OutlookDestination : AbstractDestination { public class OutlookDestination : AbstractDestination
{
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(OutlookDestination)); private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(OutlookDestination));
private const int IconApplication = 0; private const int IconApplication = 0;
private const int IconMeeting = 2; private const int IconMeeting = 2;
@ -50,17 +52,25 @@ namespace Greenshot.Plugin.Office.Destinations {
private readonly OlObjectClass _outlookInspectorType; private readonly OlObjectClass _outlookInspectorType;
private readonly OutlookEmailExporter _outlookEmailExporter = new(); private readonly OutlookEmailExporter _outlookEmailExporter = new();
static OutlookDestination() { static OutlookDestination()
if (HasOutlook()) { {
if (HasOutlook())
{
IsActiveFlag = true; IsActiveFlag = true;
} }
ExePath = PluginUtils.GetExePath("OUTLOOK.EXE"); ExePath = PluginUtils.GetExePath("OUTLOOK.EXE");
if (ExePath != null && File.Exists(ExePath)) { if (ExePath != null && File.Exists(ExePath))
{
WindowDetails.AddProcessToExcludeFromFreeze("outlook"); WindowDetails.AddProcessToExcludeFromFreeze("outlook");
} else { }
else
{
ExePath = GetOutlookExePath(); ExePath = GetOutlookExePath();
} }
if (ExePath == null) {
if (ExePath == null)
{
IsActiveFlag = false; IsActiveFlag = false;
} }
} }
@ -79,13 +89,16 @@ namespace Greenshot.Plugin.Office.Destinations {
{ {
return false; return false;
} }
return File.Exists(outlookPath); return File.Exists(outlookPath);
} }
public OutlookDestination() { public OutlookDestination()
{
} }
public OutlookDestination(string outlookInspectorCaption, OlObjectClass outlookInspectorType) { public OutlookDestination(string outlookInspectorCaption, OlObjectClass outlookInspectorType)
{
_outlookInspectorCaption = outlookInspectorCaption; _outlookInspectorCaption = outlookInspectorCaption;
_outlookInspectorType = outlookInspectorType; _outlookInspectorType = outlookInspectorType;
} }
@ -102,25 +115,32 @@ namespace Greenshot.Plugin.Office.Destinations {
public override Keys EditorShortcutKeys => Keys.Control | Keys.E; public override Keys EditorShortcutKeys => Keys.Control | Keys.E;
public override Image DisplayIcon { public override Image DisplayIcon
{
get get
{ {
if (_outlookInspectorCaption == null) if (_outlookInspectorCaption == null)
{ {
return PluginUtils.GetCachedExeIcon(ExePath, IconApplication); return PluginUtils.GetCachedExeIcon(ExePath, IconApplication);
} }
if (OlObjectClass.olAppointment.Equals(_outlookInspectorType)) {
if (OlObjectClass.olAppointment.Equals(_outlookInspectorType))
{
// Make sure we loaded the icon, maybe the configuration has been changed! // Make sure we loaded the icon, maybe the configuration has been changed!
return PluginUtils.GetCachedExeIcon(ExePath, IconMeeting); return PluginUtils.GetCachedExeIcon(ExePath, IconMeeting);
} }
return MailIcon; return MailIcon;
} }
} }
public override IEnumerable<IDestination> DynamicDestinations() { public override IEnumerable<IDestination> DynamicDestinations()
{
IDictionary<string, OlObjectClass> inspectorCaptions = _outlookEmailExporter.RetrievePossibleTargets(); IDictionary<string, OlObjectClass> inspectorCaptions = _outlookEmailExporter.RetrievePossibleTargets();
if (inspectorCaptions != null) { if (inspectorCaptions != null)
foreach (string inspectorCaption in inspectorCaptions.Keys) { {
foreach (string inspectorCaption in inspectorCaptions.Keys)
{
yield return new OutlookDestination(inspectorCaption, inspectorCaptions[inspectorCaption]); yield return new OutlookDestination(inspectorCaption, inspectorCaptions[inspectorCaption]);
} }
} }
@ -133,49 +153,69 @@ namespace Greenshot.Plugin.Office.Destinations {
/// <param name="surface"></param> /// <param name="surface"></param>
/// <param name="captureDetails"></param> /// <param name="captureDetails"></param>
/// <returns></returns> /// <returns></returns>
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails)
{
ExportInformation exportInformation = new ExportInformation(Designation, Description); ExportInformation exportInformation = new ExportInformation(Designation, Description);
// Outlook logic // Outlook logic
string tmpFile = captureDetails.Filename; string tmpFile = captureDetails.Filename;
if (tmpFile == null || surface.Modified || !Regex.IsMatch(tmpFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$")) { if (tmpFile == null || surface.Modified || !Regex.IsMatch(tmpFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$"))
{
tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat()); tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat());
} else { }
else
{
Log.InfoFormat("Using already available file: {0}", tmpFile); Log.InfoFormat("Using already available file: {0}", tmpFile);
} }
// Create a attachment name for the image // Create a attachment name for the image
string attachmentName = captureDetails.Title; string attachmentName = captureDetails.Title;
if (!string.IsNullOrEmpty(attachmentName)) { if (!string.IsNullOrEmpty(attachmentName))
{
attachmentName = attachmentName.Trim(); attachmentName = attachmentName.Trim();
} }
// Set default if non is set // Set default if non is set
if (string.IsNullOrEmpty(attachmentName)) { if (string.IsNullOrEmpty(attachmentName))
{
attachmentName = "Greenshot Capture"; attachmentName = "Greenshot Capture";
} }
// Make sure it's "clean" so it doesn't corrupt the header // Make sure it's "clean" so it doesn't corrupt the header
attachmentName = Regex.Replace(attachmentName, @"[^\x20\d\w]", string.Empty); attachmentName = Regex.Replace(attachmentName, @"[^\x20\d\w]", string.Empty);
if (_outlookInspectorCaption != null) { if (_outlookInspectorCaption != null)
{
_outlookEmailExporter.ExportToInspector(_outlookInspectorCaption, tmpFile, attachmentName); _outlookEmailExporter.ExportToInspector(_outlookInspectorCaption, tmpFile, attachmentName);
exportInformation.ExportMade = true; exportInformation.ExportMade = true;
} else { }
if (!manuallyInitiated) { else
{
if (!manuallyInitiated)
{
var inspectorCaptions = _outlookEmailExporter.RetrievePossibleTargets(); var inspectorCaptions = _outlookEmailExporter.RetrievePossibleTargets();
if (inspectorCaptions != null && inspectorCaptions.Count > 0) { if (inspectorCaptions != null && inspectorCaptions.Count > 0)
{
var destinations = new List<IDestination> var destinations = new List<IDestination>
{ {
new OutlookDestination() new OutlookDestination()
}; };
foreach (string inspectorCaption in inspectorCaptions.Keys) { foreach (string inspectorCaption in inspectorCaptions.Keys)
{
destinations.Add(new OutlookDestination(inspectorCaption, inspectorCaptions[inspectorCaption])); destinations.Add(new OutlookDestination(inspectorCaption, inspectorCaptions[inspectorCaption]));
} }
// Return the ExportInformation from the picker without processing, as this indirectly comes from us self // Return the ExportInformation from the picker without processing, as this indirectly comes from us self
return ShowPickerMenu(false, surface, captureDetails, destinations); return ShowPickerMenu(false, surface, captureDetails, destinations);
} }
} else { }
exportInformation.ExportMade = _outlookEmailExporter.ExportToOutlook(OfficeConfig.OutlookEmailFormat, tmpFile, FilenameHelper.FillPattern(OfficeConfig.EmailSubjectPattern, captureDetails, false), attachmentName, OfficeConfig.EmailTo, OfficeConfig.EmailCC, OfficeConfig.EmailBCC, null); else
{
exportInformation.ExportMade = _outlookEmailExporter.ExportToOutlook(OfficeConfig.OutlookEmailFormat, tmpFile,
FilenameHelper.FillPattern(OfficeConfig.EmailSubjectPattern, captureDetails, false), attachmentName, OfficeConfig.EmailTo, OfficeConfig.EmailCC,
OfficeConfig.EmailBCC, null);
} }
} }
ProcessExport(exportInformation, surface); ProcessExport(exportInformation, surface);
return exportInformation; return exportInformation;
} }

View file

@ -29,11 +29,13 @@ using GreenshotPlugin.Core;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin; using GreenshotPlugin.Interfaces.Plugin;
namespace Greenshot.Plugin.Office.Destinations { namespace Greenshot.Plugin.Office.Destinations
{
/// <summary> /// <summary>
/// Description of PowerpointDestination. /// Description of PowerpointDestination.
/// </summary> /// </summary>
public class PowerpointDestination : AbstractDestination { public class PowerpointDestination : AbstractDestination
{
private const int IconApplication = 0; private const int IconApplication = 0;
private const int IconPresentation = 1; private const int IconPresentation = 1;
@ -41,30 +43,39 @@ namespace Greenshot.Plugin.Office.Destinations {
private readonly string _presentationName; private readonly string _presentationName;
private readonly PowerpointExporter _powerpointExporter = new PowerpointExporter(); private readonly PowerpointExporter _powerpointExporter = new PowerpointExporter();
static PowerpointDestination() { static PowerpointDestination()
{
ExePath = PluginUtils.GetExePath("POWERPNT.EXE"); ExePath = PluginUtils.GetExePath("POWERPNT.EXE");
if (ExePath != null && File.Exists(ExePath)) { if (ExePath != null && File.Exists(ExePath))
{
WindowDetails.AddProcessToExcludeFromFreeze("powerpnt"); WindowDetails.AddProcessToExcludeFromFreeze("powerpnt");
} else { }
else
{
ExePath = null; ExePath = null;
} }
} }
public PowerpointDestination() { public PowerpointDestination()
{
} }
public PowerpointDestination(string presentationName) { public PowerpointDestination(string presentationName)
{
_presentationName = presentationName; _presentationName = presentationName;
} }
public override string Designation => "Powerpoint"; public override string Designation => "Powerpoint";
public override string Description { public override string Description
{
get get
{ {
if (_presentationName == null) { if (_presentationName == null)
{
return "Microsoft Powerpoint"; return "Microsoft Powerpoint";
} }
return _presentationName; return _presentationName;
} }
} }
@ -75,9 +86,12 @@ namespace Greenshot.Plugin.Office.Destinations {
public override bool IsActive => base.IsActive && ExePath != null; public override bool IsActive => base.IsActive && ExePath != null;
public override Image DisplayIcon { public override Image DisplayIcon
get { {
if (!string.IsNullOrEmpty(_presentationName)) { get
{
if (!string.IsNullOrEmpty(_presentationName))
{
return PluginUtils.GetCachedExeIcon(ExePath, IconPresentation); return PluginUtils.GetCachedExeIcon(ExePath, IconPresentation);
} }
@ -85,37 +99,55 @@ namespace Greenshot.Plugin.Office.Destinations {
} }
} }
public override IEnumerable<IDestination> DynamicDestinations() { public override IEnumerable<IDestination> DynamicDestinations()
foreach (string presentationName in _powerpointExporter.GetPowerpointPresentations()) { {
foreach (string presentationName in _powerpointExporter.GetPowerpointPresentations())
{
yield return new PowerpointDestination(presentationName); yield return new PowerpointDestination(presentationName);
} }
} }
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails)
{
ExportInformation exportInformation = new ExportInformation(Designation, Description); ExportInformation exportInformation = new ExportInformation(Designation, Description);
string tmpFile = captureDetails.Filename; string tmpFile = captureDetails.Filename;
Size imageSize = Size.Empty; Size imageSize = Size.Empty;
if (tmpFile == null || surface.Modified || !Regex.IsMatch(tmpFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$")) { if (tmpFile == null || surface.Modified || !Regex.IsMatch(tmpFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$"))
{
tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat()); tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat());
imageSize = surface.Image.Size; imageSize = surface.Image.Size;
} }
if (_presentationName != null) {
if (_presentationName != null)
{
exportInformation.ExportMade = _powerpointExporter.ExportToPresentation(_presentationName, tmpFile, imageSize, captureDetails.Title); exportInformation.ExportMade = _powerpointExporter.ExportToPresentation(_presentationName, tmpFile, imageSize, captureDetails.Title);
} else { }
if (!manuallyInitiated) { else
{
if (!manuallyInitiated)
{
var presentations = _powerpointExporter.GetPowerpointPresentations().ToList(); var presentations = _powerpointExporter.GetPowerpointPresentations().ToList();
if (presentations != null && presentations.Count > 0) { if (presentations != null && presentations.Count > 0)
var destinations = new List<IDestination> {new PowerpointDestination()}; {
foreach (string presentation in presentations) { var destinations = new List<IDestination>
{
new PowerpointDestination()
};
foreach (string presentation in presentations)
{
destinations.Add(new PowerpointDestination(presentation)); destinations.Add(new PowerpointDestination(presentation));
} }
// Return the ExportInformation from the picker without processing, as this indirectly comes from us self // Return the ExportInformation from the picker without processing, as this indirectly comes from us self
return ShowPickerMenu(false, surface, captureDetails, destinations); return ShowPickerMenu(false, surface, captureDetails, destinations);
} }
} else if (!exportInformation.ExportMade) { }
else if (!exportInformation.ExportMade)
{
exportInformation.ExportMade = _powerpointExporter.InsertIntoNewPresentation(tmpFile, imageSize, captureDetails.Title); exportInformation.ExportMade = _powerpointExporter.InsertIntoNewPresentation(tmpFile, imageSize, captureDetails.Title);
} }
} }
ProcessExport(exportInformation, surface); ProcessExport(exportInformation, surface);
return exportInformation; return exportInformation;
} }

View file

@ -30,29 +30,35 @@ using GreenshotPlugin.Core;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin; using GreenshotPlugin.Interfaces.Plugin;
namespace Greenshot.Plugin.Office.Destinations { namespace Greenshot.Plugin.Office.Destinations
{
/// <summary> /// <summary>
/// Description of EmailDestination. /// Description of EmailDestination.
/// </summary> /// </summary>
public class WordDestination : AbstractDestination { public class WordDestination : AbstractDestination
{
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(WordDestination)); private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(WordDestination));
private const int IconApplication = 0; private const int IconApplication = 0;
private const int IconDocument = 1; private const int IconDocument = 1;
private static readonly string ExePath; private static readonly string ExePath;
private readonly string _documentCaption; private readonly string _documentCaption;
private readonly WordExporter _wordExporter = new WordExporter(); private readonly WordExporter _wordExporter = new WordExporter();
static WordDestination() {
static WordDestination()
{
ExePath = PluginUtils.GetExePath("WINWORD.EXE"); ExePath = PluginUtils.GetExePath("WINWORD.EXE");
if (ExePath != null && !File.Exists(ExePath)) { if (ExePath != null && !File.Exists(ExePath))
{
ExePath = null; ExePath = null;
} }
} }
public WordDestination() { public WordDestination()
{
} }
public WordDestination(string wordCaption) { public WordDestination(string wordCaption)
{
_documentCaption = wordCaption; _documentCaption = wordCaption;
} }
@ -68,62 +74,88 @@ namespace Greenshot.Plugin.Office.Destinations {
public override Image DisplayIcon => PluginUtils.GetCachedExeIcon(ExePath, !string.IsNullOrEmpty(_documentCaption) ? IconDocument : IconApplication); public override Image DisplayIcon => PluginUtils.GetCachedExeIcon(ExePath, !string.IsNullOrEmpty(_documentCaption) ? IconDocument : IconApplication);
public override IEnumerable<IDestination> DynamicDestinations() { public override IEnumerable<IDestination> DynamicDestinations()
foreach (string wordCaption in _wordExporter.GetWordDocuments()) { {
foreach (string wordCaption in _wordExporter.GetWordDocuments())
{
yield return new WordDestination(wordCaption); yield return new WordDestination(wordCaption);
} }
} }
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails)
{
ExportInformation exportInformation = new ExportInformation(Designation, Description); ExportInformation exportInformation = new ExportInformation(Designation, Description);
string tmpFile = captureDetails.Filename; string tmpFile = captureDetails.Filename;
if (tmpFile == null || surface.Modified || !Regex.IsMatch(tmpFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$")) { if (tmpFile == null || surface.Modified || !Regex.IsMatch(tmpFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$"))
{
tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat()); tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat());
} }
if (_documentCaption != null) {
try { if (_documentCaption != null)
{
try
{
_wordExporter.InsertIntoExistingDocument(_documentCaption, tmpFile); _wordExporter.InsertIntoExistingDocument(_documentCaption, tmpFile);
exportInformation.ExportMade = true; exportInformation.ExportMade = true;
} catch (Exception) { }
try { catch (Exception)
{
try
{
_wordExporter.InsertIntoExistingDocument(_documentCaption, tmpFile); _wordExporter.InsertIntoExistingDocument(_documentCaption, tmpFile);
exportInformation.ExportMade = true; exportInformation.ExportMade = true;
} catch (Exception ex) { }
catch (Exception ex)
{
Log.Error(ex); Log.Error(ex);
// TODO: Change to general logic in ProcessExport // TODO: Change to general logic in ProcessExport
surface.SendMessageEvent(this, SurfaceMessageTyp.Error, Language.GetFormattedString("destination_exportfailed", Description)); surface.SendMessageEvent(this, SurfaceMessageTyp.Error, Language.GetFormattedString("destination_exportfailed", Description));
} }
} }
} else { }
if (!manuallyInitiated) { else
{
if (!manuallyInitiated)
{
var documents = _wordExporter.GetWordDocuments().ToList(); var documents = _wordExporter.GetWordDocuments().ToList();
if (documents != null && documents.Count > 0) { if (documents != null && documents.Count > 0)
{
var destinations = new List<IDestination> var destinations = new List<IDestination>
{ {
new WordDestination() new WordDestination()
}; };
foreach (string document in documents) { foreach (string document in documents)
{
destinations.Add(new WordDestination(document)); destinations.Add(new WordDestination(document));
} }
// Return the ExportInformation from the picker without processing, as this indirectly comes from us self // Return the ExportInformation from the picker without processing, as this indirectly comes from us self
return ShowPickerMenu(false, surface, captureDetails, destinations); return ShowPickerMenu(false, surface, captureDetails, destinations);
} }
} }
try {
try
{
_wordExporter.InsertIntoNewDocument(tmpFile, null, null); _wordExporter.InsertIntoNewDocument(tmpFile, null, null);
exportInformation.ExportMade = true; exportInformation.ExportMade = true;
} catch(Exception) { }
catch (Exception)
{
// Retry once, just in case // Retry once, just in case
try { try
{
_wordExporter.InsertIntoNewDocument(tmpFile, null, null); _wordExporter.InsertIntoNewDocument(tmpFile, null, null);
exportInformation.ExportMade = true; exportInformation.ExportMade = true;
} catch (Exception ex) { }
catch (Exception ex)
{
Log.Error(ex); Log.Error(ex);
// TODO: Change to general logic in ProcessExport // TODO: Change to general logic in ProcessExport
surface.SendMessageEvent(this, SurfaceMessageTyp.Error, Language.GetFormattedString("destination_exportfailed", Description)); surface.SendMessageEvent(this, SurfaceMessageTyp.Error, Language.GetFormattedString("destination_exportfailed", Description));
} }
} }
} }
ProcessExport(exportInformation, surface); ProcessExport(exportInformation, surface);
return exportInformation; return exportInformation;
} }

View file

@ -23,32 +23,40 @@ using Greenshot.Plugin.Office.OfficeInterop;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
using Microsoft.Office.Interop.PowerPoint; using Microsoft.Office.Interop.PowerPoint;
namespace Greenshot.Plugin.Office { namespace Greenshot.Plugin.Office
{
/// <summary> /// <summary>
/// Description of CoreConfiguration. /// Description of CoreConfiguration.
/// </summary> /// </summary>
[IniSection("Office", Description="Greenshot Office configuration")] [IniSection("Office", Description = "Greenshot Office configuration")]
public class OfficeConfiguration : IniSection { public class OfficeConfiguration : IniSection
{
[IniProperty("OutlookEmailFormat", Description = "Default type for emails. (Text, HTML)", DefaultValue = "HTML")] [IniProperty("OutlookEmailFormat", Description = "Default type for emails. (Text, HTML)", DefaultValue = "HTML")]
public EmailFormat OutlookEmailFormat { get; set; } public EmailFormat OutlookEmailFormat { get; set; }
[IniProperty("EmailSubjectPattern", Description = "Email subject pattern, works like the OutputFileFilenamePattern", DefaultValue = "${title}")] [IniProperty("EmailSubjectPattern", Description = "Email subject pattern, works like the OutputFileFilenamePattern", DefaultValue = "${title}")]
public string EmailSubjectPattern { get; set; } public string EmailSubjectPattern { get; set; }
[IniProperty("EmailTo", Description = "Default value for the to in emails that are created", DefaultValue = "")] [IniProperty("EmailTo", Description = "Default value for the to in emails that are created", DefaultValue = "")]
public string EmailTo { get; set; } public string EmailTo { get; set; }
[IniProperty("EmailCC", Description = "Default value for the CC in emails that are created", DefaultValue = "")] [IniProperty("EmailCC", Description = "Default value for the CC in emails that are created", DefaultValue = "")]
public string EmailCC { get; set; } public string EmailCC { get; set; }
[IniProperty("EmailBCC", Description = "Default value for the BCC in emails that are created", DefaultValue = "")] [IniProperty("EmailBCC", Description = "Default value for the BCC in emails that are created", DefaultValue = "")]
public string EmailBCC { get; set; } public string EmailBCC { get; set; }
[IniProperty("OutlookAllowExportInMeetings", Description = "For Outlook: Allow export in meeting items", DefaultValue = "False")] [IniProperty("OutlookAllowExportInMeetings", Description = "For Outlook: Allow export in meeting items", DefaultValue = "False")]
public bool OutlookAllowExportInMeetings { get; set; } public bool OutlookAllowExportInMeetings { get; set; }
[IniProperty("WordLockAspectRatio", Description = "For Word: Lock the aspect ratio of the image", DefaultValue = "True")] [IniProperty("WordLockAspectRatio", Description = "For Word: Lock the aspect ratio of the image", DefaultValue = "True")]
public bool WordLockAspectRatio { get; set; } public bool WordLockAspectRatio { get; set; }
[IniProperty("PowerpointLockAspectRatio", Description = "For Powerpoint: Lock the aspect ratio of the image", DefaultValue = "True")] [IniProperty("PowerpointLockAspectRatio", Description = "For Powerpoint: Lock the aspect ratio of the image", DefaultValue = "True")]
public bool PowerpointLockAspectRatio { get; set; } public bool PowerpointLockAspectRatio { get; set; }
[IniProperty("PowerpointSlideLayout", Description = "For Powerpoint: Slide layout, changing this to a wrong value will fallback on ppLayoutBlank!!", DefaultValue = "ppLayoutPictureWithCaption")]
public PpSlideLayout PowerpointSlideLayout { get; set; }
[IniProperty("PowerpointSlideLayout", Description = "For Powerpoint: Slide layout, changing this to a wrong value will fallback on ppLayoutBlank!!",
DefaultValue = "ppLayoutPictureWithCaption")]
public PpSlideLayout PowerpointSlideLayout { get; set; }
} }
} }

View file

@ -34,6 +34,7 @@ namespace Greenshot.Plugin.Office.OfficeExport.Entities
{ {
return string.Format("{0} / {1}", Parent.Name, Name); return string.Format("{0} / {1}", Parent.Name, Name);
} }
return string.Format("{0} / {1} / {2}", Parent.Parent.Name, Parent.Name, Name); return string.Format("{0} / {1} / {2}", Parent.Parent.Name, Parent.Name, Name);
} }
} }

View file

@ -53,10 +53,12 @@ namespace Greenshot.Plugin.Office.OfficeExport
// Ignore, probably no excel running // Ignore, probably no excel running
return null; return null;
} }
if (excelApplication?.ComObject != null) if (excelApplication?.ComObject != null)
{ {
InitializeVariables(excelApplication); InitializeVariables(excelApplication);
} }
return excelApplication; return excelApplication;
} }
@ -71,6 +73,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
excelApplication = DisposableCom.Create(new Application()); excelApplication = DisposableCom.Create(new Application());
} }
InitializeVariables(excelApplication); InitializeVariables(excelApplication);
return excelApplication; return excelApplication;
} }
@ -108,10 +111,11 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
return; return;
} }
if (!Version.TryParse(excelApplication.ComObject.Version, out _excelVersion)) if (!Version.TryParse(excelApplication.ComObject.Version, out _excelVersion))
{ {
LOG.Warn("Assuming Excel version 1997."); LOG.Warn("Assuming Excel version 1997.");
_excelVersion = new Version((int)OfficeVersions.Office97, 0, 0, 0); _excelVersion = new Version((int) OfficeVersions.Office97, 0, 0, 0);
} }
} }
@ -132,7 +136,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
using var workbooks = DisposableCom.Create(excelApplication.ComObject.Workbooks); using var workbooks = DisposableCom.Create(excelApplication.ComObject.Workbooks);
for (int i = 1; i <= workbooks.ComObject.Count; i++) for (int i = 1; i <= workbooks.ComObject.Count; i++)
{ {
using var workbook = DisposableCom.Create((_Workbook)workbooks.ComObject[i]); using var workbook = DisposableCom.Create((_Workbook) workbooks.ComObject[i]);
if ((workbook != null) && workbook.ComObject.Name.StartsWith(workbookName)) if ((workbook != null) && workbook.ComObject.Name.StartsWith(workbookName))
{ {
InsertIntoExistingWorkbook(workbook, tmpFile, imageSize); InsertIntoExistingWorkbook(workbook, tmpFile, imageSize);
@ -191,9 +195,8 @@ namespace Greenshot.Plugin.Office.OfficeExport
excelApplication.ComObject.Visible = true; excelApplication.ComObject.Visible = true;
using var workbooks = DisposableCom.Create(excelApplication.ComObject.Workbooks); using var workbooks = DisposableCom.Create(excelApplication.ComObject.Workbooks);
using var workbook = DisposableCom.Create((_Workbook)workbooks.ComObject.Add()); using var workbook = DisposableCom.Create((_Workbook) workbooks.ComObject.Add());
InsertIntoExistingWorkbook(workbook, tmpFile, imageSize); InsertIntoExistingWorkbook(workbook, tmpFile, imageSize);
} }
} }
} }

View file

@ -38,7 +38,10 @@ namespace Greenshot.Plugin.Office.OfficeExport
public class OneNoteExporter public class OneNoteExporter
{ {
private const string XmlImageContent = "<one:Image format=\"png\"><one:Size width=\"{1}.0\" height=\"{2}.0\" isSetByUser=\"true\" /><one:Data>{0}</one:Data></one:Image>"; private const string XmlImageContent = "<one:Image format=\"png\"><one:Size width=\"{1}.0\" height=\"{2}.0\" isSetByUser=\"true\" /><one:Data>{0}</one:Data></one:Image>";
private const string XmlOutline = "<?xml version=\"1.0\"?><one:Page xmlns:one=\"{2}\" ID=\"{1}\"><one:Title><one:OE><one:T><![CDATA[{3}]]></one:T></one:OE></one:Title>{0}</one:Page>";
private const string XmlOutline =
"<?xml version=\"1.0\"?><one:Page xmlns:one=\"{2}\" ID=\"{1}\"><one:Title><one:OE><one:T><![CDATA[{3}]]></one:T></one:OE></one:Title>{0}</one:Page>";
private const string OnenoteNamespace2010 = "http://schemas.microsoft.com/office/onenote/2010/onenote"; private const string OnenoteNamespace2010 = "http://schemas.microsoft.com/office/onenote/2010/onenote";
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OneNoteExporter)); private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OneNoteExporter));
@ -107,6 +110,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
LOG.Warn("Unable to navigate to the target page", ex); LOG.Warn("Unable to navigate to the target page", ex);
} }
return true; return true;
} }
@ -126,6 +130,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
// Ignore, probably no OneNote running // Ignore, probably no OneNote running
return null; return null;
} }
return oneNoteApplication; return oneNoteApplication;
} }
@ -140,6 +145,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
oneNoteApplication = DisposableCom.Create(new Application()); oneNoteApplication = DisposableCom.Create(new Application());
} }
return oneNoteApplication; return oneNoteApplication;
} }
@ -183,6 +189,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
}; };
} }
} }
if ("one:Section".Equals(xmlReader.Name)) if ("one:Section".Equals(xmlReader.Name))
{ {
string id = xmlReader.GetAttribute("ID"); string id = xmlReader.GetAttribute("ID");
@ -196,6 +203,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
}; };
} }
} }
if ("one:Page".Equals(xmlReader.Name)) if ("one:Page".Equals(xmlReader.Name))
{ {
// Skip deleted items // Skip deleted items
@ -214,6 +222,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
continue; continue;
} }
page.IsCurrentlyViewed = "true".Equals(xmlReader.GetAttribute("isCurrentlyViewed")); page.IsCurrentlyViewed = "true".Equals(xmlReader.GetAttribute("isCurrentlyViewed"));
pages.Add(page); pages.Add(page);
} }
@ -231,22 +240,26 @@ namespace Greenshot.Plugin.Office.OfficeExport
} }
catch (COMException cEx) catch (COMException cEx)
{ {
if (cEx.ErrorCode == unchecked((int)0x8002801D)) if (cEx.ErrorCode == unchecked((int) 0x8002801D))
{ {
LOG.Warn("Wrong registry keys, to solve this remove the OneNote key as described here: http://microsoftmercenary.com/wp/outlook-excel-interop-calls-breaking-solved/"); LOG.Warn(
"Wrong registry keys, to solve this remove the OneNote key as described here: http://microsoftmercenary.com/wp/outlook-excel-interop-calls-breaking-solved/");
} }
LOG.Warn("Problem retrieving onenote destinations, ignoring: ", cEx); LOG.Warn("Problem retrieving onenote destinations, ignoring: ", cEx);
} }
catch (Exception ex) catch (Exception ex)
{ {
LOG.Warn("Problem retrieving onenote destinations, ignoring: ", ex); LOG.Warn("Problem retrieving onenote destinations, ignoring: ", ex);
} }
pages.Sort((page1, page2) => pages.Sort((page1, page2) =>
{ {
if (page1.IsCurrentlyViewed || page2.IsCurrentlyViewed) if (page1.IsCurrentlyViewed || page2.IsCurrentlyViewed)
{ {
return page2.IsCurrentlyViewed.CompareTo(page1.IsCurrentlyViewed); return page2.IsCurrentlyViewed.CompareTo(page1.IsCurrentlyViewed);
} }
return string.Compare(page1.DisplayName, page2.DisplayName, StringComparison.Ordinal); return string.Compare(page1.DisplayName, page2.DisplayName, StringComparison.Ordinal);
}); });
return pages; return pages;
@ -264,6 +277,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
return null; return null;
} }
// ReSharper disable once RedundantAssignment // ReSharper disable once RedundantAssignment
string unfiledNotesPath = ""; string unfiledNotesPath = "";
oneNoteApplication.ComObject.GetSpecialLocation(specialLocation, out unfiledNotesPath); oneNoteApplication.ComObject.GetSpecialLocation(specialLocation, out unfiledNotesPath);
@ -285,6 +299,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
continue; continue;
} }
string id = xmlReader.GetAttribute("ID"); string id = xmlReader.GetAttribute("ID");
string path = xmlReader.GetAttribute("path"); string path = xmlReader.GetAttribute("path");
if (unfiledNotesPath.Equals(path)) if (unfiledNotesPath.Equals(path))
@ -301,6 +316,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
} }
} }
} }
return null; return null;
} }
} }

View file

@ -47,7 +47,9 @@ namespace Greenshot.Plugin.Office.OfficeExport
private const string ProfilesKey = @"Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\"; private const string ProfilesKey = @"Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\";
private const string AccountKey = "9375CFF0413111d3B88A00104B2A6676"; private const string AccountKey = "9375CFF0413111d3B88A00104B2A6676";
private const string NewSignatureValue = "New Signature"; private const string NewSignatureValue = "New Signature";
private const string DefaultProfileValue = "DefaultProfile"; private const string DefaultProfileValue = "DefaultProfile";
// Schema definitions for the MAPI properties, see: http://msdn.microsoft.com/en-us/library/aa454438.aspx and: http://msdn.microsoft.com/en-us/library/bb446117.aspx // Schema definitions for the MAPI properties, see: http://msdn.microsoft.com/en-us/library/aa454438.aspx and: http://msdn.microsoft.com/en-us/library/bb446117.aspx
private const string AttachmentContentId = @"http://schemas.microsoft.com/mapi/proptag/0x3712001E"; private const string AttachmentContentId = @"http://schemas.microsoft.com/mapi/proptag/0x3712001E";
@ -73,10 +75,10 @@ namespace Greenshot.Plugin.Office.OfficeExport
} }
// The activeexplorer inline response only works with >= 2013, Microsoft Outlook 15.0 Object Library // The activeexplorer inline response only works with >= 2013, Microsoft Outlook 15.0 Object Library
if (_outlookVersion.Major >= (int)OfficeVersions.Office2013) if (_outlookVersion.Major >= (int) OfficeVersions.Office2013)
{ {
// Check inline "panel" for Outlook 2013 // Check inline "panel" for Outlook 2013
using var activeExplorer = DisposableCom.Create((_Explorer)outlookApplication.ComObject.ActiveExplorer()); using var activeExplorer = DisposableCom.Create((_Explorer) outlookApplication.ComObject.ActiveExplorer());
// Only if we have one and if the capture is the one we selected // Only if we have one and if the capture is the one we selected
if ((activeExplorer != null) && activeExplorer.ComObject.Caption.StartsWith(inspectorCaption)) if ((activeExplorer != null) && activeExplorer.ComObject.Caption.StartsWith(inspectorCaption))
{ {
@ -90,15 +92,17 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
return ExportToInspector(null, activeExplorer, mailItem.Class, mailItem, tmpFile, attachmentName); return ExportToInspector(null, activeExplorer, mailItem.Class, mailItem, tmpFile, attachmentName);
} }
break; break;
case AppointmentItem appointmentItem: case AppointmentItem appointmentItem:
if ((_outlookVersion.Major >= (int)OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings) if ((_outlookVersion.Major >= (int) OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
{ {
if (!string.IsNullOrEmpty(appointmentItem.Organizer) && appointmentItem.Organizer.Equals(_currentUser)) if (!string.IsNullOrEmpty(appointmentItem.Organizer) && appointmentItem.Organizer.Equals(_currentUser))
{ {
return ExportToInspector(null, activeExplorer, appointmentItem.Class, null, tmpFile, attachmentName); return ExportToInspector(null, activeExplorer, appointmentItem.Class, null, tmpFile, attachmentName);
} }
} }
break; break;
} }
} }
@ -110,10 +114,11 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
return false; return false;
} }
LOG.DebugFormat("Got {0} inspectors to check", inspectors.ComObject.Count); LOG.DebugFormat("Got {0} inspectors to check", inspectors.ComObject.Count);
for (int i = 1; i <= inspectors.ComObject.Count; i++) for (int i = 1; i <= inspectors.ComObject.Count; i++)
{ {
using var inspector = DisposableCom.Create((_Inspector)inspectors.ComObject[i]); using var inspector = DisposableCom.Create((_Inspector) inspectors.ComObject[i]);
string currentCaption = inspector.ComObject.Caption; string currentCaption = inspector.ComObject.Caption;
if (!currentCaption.StartsWith(inspectorCaption)) if (!currentCaption.StartsWith(inspectorCaption))
{ {
@ -130,6 +135,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
continue; continue;
} }
try try
{ {
return ExportToInspector(inspector, null, mailItem.Class, mailItem, tmpFile, attachmentName); return ExportToInspector(inspector, null, mailItem.Class, mailItem, tmpFile, attachmentName);
@ -138,9 +144,10 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
LOG.Error($"Export to {currentCaption} failed.", exExport); LOG.Error($"Export to {currentCaption} failed.", exExport);
} }
break; break;
case AppointmentItem appointmentItem: case AppointmentItem appointmentItem:
if ((_outlookVersion.Major >= (int)OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings) if ((_outlookVersion.Major >= (int) OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
{ {
if (!string.IsNullOrEmpty(appointmentItem.Organizer) && !appointmentItem.Organizer.Equals(_currentUser)) if (!string.IsNullOrEmpty(appointmentItem.Organizer) && !appointmentItem.Organizer.Equals(_currentUser))
{ {
@ -153,6 +160,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
// skip, can't export to olAppointment // skip, can't export to olAppointment
continue; continue;
} }
try try
{ {
return ExportToInspector(inspector, null, appointmentItem.Class, null, tmpFile, attachmentName); return ExportToInspector(inspector, null, appointmentItem.Class, null, tmpFile, attachmentName);
@ -161,6 +169,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
LOG.Error($"Export to {currentCaption} failed.", exExport); LOG.Error($"Export to {currentCaption} failed.", exExport);
} }
break; break;
default: default:
continue; continue;
@ -168,6 +177,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
} }
} }
} }
return false; return false;
} }
@ -181,7 +191,8 @@ namespace Greenshot.Plugin.Office.OfficeExport
/// <param name="explorer"></param> /// <param name="explorer"></param>
/// <param name="itemClass"></param> /// <param name="itemClass"></param>
/// <returns></returns> /// <returns></returns>
private bool ExportToInspector(IDisposableCom<_Inspector> inspector, IDisposableCom<_Explorer> explorer, OlObjectClass itemClass, MailItem mailItem, string tmpFile, string attachmentName) private bool ExportToInspector(IDisposableCom<_Inspector> inspector, IDisposableCom<_Explorer> explorer, OlObjectClass itemClass, MailItem mailItem, string tmpFile,
string attachmentName)
{ {
bool isMail = OlObjectClass.olMail.Equals(itemClass); bool isMail = OlObjectClass.olMail.Equals(itemClass);
bool isAppointment = OlObjectClass.olAppointment.Equals(itemClass); bool isAppointment = OlObjectClass.olAppointment.Equals(itemClass);
@ -190,6 +201,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
LOG.Warn("Item is no mail or appointment."); LOG.Warn("Item is no mail or appointment.");
return false; return false;
} }
try try
{ {
// Make sure the inspector is activated, only this way the word editor is active! // Make sure the inspector is activated, only this way the word editor is active!
@ -200,25 +212,27 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
isTextFormat = OlBodyFormat.olFormatPlain.Equals(mailItem.BodyFormat); isTextFormat = OlBodyFormat.olFormatPlain.Equals(mailItem.BodyFormat);
} }
if (isAppointment || !isTextFormat) if (isAppointment || !isTextFormat)
{ {
// Check for wordmail, if so use the wordexporter // Check for wordmail, if so use the wordexporter
// http://msdn.microsoft.com/en-us/library/dd492012%28v=office.12%29.aspx // http://msdn.microsoft.com/en-us/library/dd492012%28v=office.12%29.aspx
// Earlier versions of Outlook also supported an Inspector.HTMLEditor object property, but since Internet Explorer is no longer the rendering engine for HTML messages and posts, HTMLEditor is no longer supported. // Earlier versions of Outlook also supported an Inspector.HTMLEditor object property, but since Internet Explorer is no longer the rendering engine for HTML messages and posts, HTMLEditor is no longer supported.
IDisposableCom<_Document> wordDocument = null; IDisposableCom<_Document> wordDocument = null;
if ((explorer != null) && (_outlookVersion.Major >= (int)OfficeVersions.Office2013)) if ((explorer != null) && (_outlookVersion.Major >= (int) OfficeVersions.Office2013))
{ {
// TODO: Needs to have the Microsoft Outlook 15.0 Object Library installed // TODO: Needs to have the Microsoft Outlook 15.0 Object Library installed
wordDocument = DisposableCom.Create((_Document)explorer.ComObject.ActiveInlineResponseWordEditor); wordDocument = DisposableCom.Create((_Document) explorer.ComObject.ActiveInlineResponseWordEditor);
} }
else if (inspector != null) else if (inspector != null)
{ {
if (inspector.ComObject.IsWordMail() && (inspector.ComObject.EditorType == OlEditorType.olEditorWord)) if (inspector.ComObject.IsWordMail() && (inspector.ComObject.EditorType == OlEditorType.olEditorWord))
{ {
var tmpWordDocument = (_Document)inspector.ComObject.WordEditor; var tmpWordDocument = (_Document) inspector.ComObject.WordEditor;
wordDocument = DisposableCom.Create(tmpWordDocument); wordDocument = DisposableCom.Create(tmpWordDocument);
} }
} }
if (wordDocument != null) if (wordDocument != null)
{ {
using (wordDocument) using (wordDocument)
@ -248,6 +262,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
LOG.Info("Trying export for outlook < 2007."); LOG.Info("Trying export for outlook < 2007.");
} }
} }
// Only use mailitem as it should be filled!! // Only use mailitem as it should be filled!!
if (mailItem != null) if (mailItem != null)
{ {
@ -255,7 +270,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
} }
string contentId; string contentId;
if (_outlookVersion.Major >= (int)OfficeVersions.Office2007) if (_outlookVersion.Major >= (int) OfficeVersions.Office2007)
{ {
contentId = Guid.NewGuid().ToString(); contentId = Guid.NewGuid().ToString();
} }
@ -283,7 +298,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
var selection = document2.selection; var selection = document2.selection;
if (selection != null) if (selection != null)
{ {
var range = (IHTMLTxtRange)selection.createRange(); var range = (IHTMLTxtRange) selection.createRange();
if (range != null) if (range != null)
{ {
// First paste, than attach (otherwise the range is wrong!) // First paste, than attach (otherwise the range is wrong!)
@ -315,7 +330,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
// Create the attachment (if inlined the attachment isn't visible as attachment!) // Create the attachment (if inlined the attachment isn't visible as attachment!)
using var attachments = DisposableCom.Create(mailItem.Attachments); using var attachments = DisposableCom.Create(mailItem.Attachments);
using var attachment = DisposableCom.Create(attachments.ComObject.Add(tmpFile, OlAttachmentType.olByValue, inlinePossible ? 0 : 1, attachmentName)); using var attachment = DisposableCom.Create(attachments.ComObject.Add(tmpFile, OlAttachmentType.olByValue, inlinePossible ? 0 : 1, attachmentName));
if (_outlookVersion.Major >= (int)OfficeVersions.Office2007) if (_outlookVersion.Major >= (int) OfficeVersions.Office2007)
{ {
// Add the content id to the attachment, this only works for Outlook >= 2007 // Add the content id to the attachment, this only works for Outlook >= 2007
try try
@ -341,9 +356,11 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
caption = explorer.ComObject.Caption; caption = explorer.ComObject.Caption;
} }
LOG.Warn($"Problem while trying to add attachment to Item '{caption}'", ex); LOG.Warn($"Problem while trying to add attachment to Item '{caption}'", ex);
return false; return false;
} }
try try
{ {
if (inspector != null) if (inspector != null)
@ -360,6 +377,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
LOG.Warn("Problem activating inspector/explorer: ", ex); LOG.Warn("Problem activating inspector/explorer: ", ex);
return false; return false;
} }
LOG.Debug("Finished!"); LOG.Debug("Finished!");
return true; return true;
} }
@ -376,27 +394,32 @@ namespace Greenshot.Plugin.Office.OfficeExport
/// <param name="cc"></param> /// <param name="cc"></param>
/// <param name="bcc"></param> /// <param name="bcc"></param>
/// <param name="url"></param> /// <param name="url"></param>
private void ExportToNewEmail(IDisposableCom<Application> outlookApplication, EmailFormat format, string tmpFile, string subject, string attachmentName, string to, string cc, string bcc, string url) private void ExportToNewEmail(IDisposableCom<Application> outlookApplication, EmailFormat format, string tmpFile, string subject, string attachmentName, string to,
string cc, string bcc, string url)
{ {
using var newItem = DisposableCom.Create((MailItem)outlookApplication.ComObject.CreateItem(OlItemType.olMailItem)); using var newItem = DisposableCom.Create((MailItem) outlookApplication.ComObject.CreateItem(OlItemType.olMailItem));
if (newItem == null) if (newItem == null)
{ {
return; return;
} }
var newMail = newItem.ComObject; var newMail = newItem.ComObject;
newMail.Subject = subject; newMail.Subject = subject;
if (!string.IsNullOrEmpty(to)) if (!string.IsNullOrEmpty(to))
{ {
newMail.To = to; newMail.To = to;
} }
if (!string.IsNullOrEmpty(cc)) if (!string.IsNullOrEmpty(cc))
{ {
newMail.CC = cc; newMail.CC = cc;
} }
if (!string.IsNullOrEmpty(bcc)) if (!string.IsNullOrEmpty(bcc))
{ {
newMail.BCC = bcc; newMail.BCC = bcc;
} }
newMail.BodyFormat = OlBodyFormat.olFormatHTML; newMail.BodyFormat = OlBodyFormat.olFormatHTML;
string bodyString = null; string bodyString = null;
// Read the default signature, if nothing found use empty email // Read the default signature, if nothing found use empty email
@ -408,6 +431,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
LOG.Error("Problem reading signature!", e); LOG.Error("Problem reading signature!", e);
} }
switch (format) switch (format)
{ {
case EmailFormat.Text: case EmailFormat.Text:
@ -421,9 +445,11 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
bodyString = ""; bodyString = "";
} }
newMail.Body = bodyString; newMail.Body = bodyString;
} }
} }
break; break;
default: default:
string contentId = Path.GetFileName(tmpFile); string contentId = Path.GetFileName(tmpFile);
@ -432,7 +458,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
using var attachment = DisposableCom.Create(attachments.ComObject.Add(tmpFile, OlAttachmentType.olByValue, 0, attachmentName)); using var attachment = DisposableCom.Create(attachments.ComObject.Add(tmpFile, OlAttachmentType.olByValue, 0, attachmentName));
// add content ID to the attachment // add content ID to the attachment
if (_outlookVersion.Major >= (int)OfficeVersions.Office2007) if (_outlookVersion.Major >= (int) OfficeVersions.Office2007)
{ {
try try
{ {
@ -456,6 +482,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
href = $"<A HREF=\"{url}\">"; href = $"<A HREF=\"{url}\">";
hrefEnd = "</A>"; hrefEnd = "</A>";
} }
string htmlImgEmbedded = $"<BR/>{href}<IMG border=0 hspace=0 alt=\"{attachmentName}\" align=baseline src=\"cid:{contentId}\">{hrefEnd}<BR/>"; string htmlImgEmbedded = $"<BR/>{href}<IMG border=0 hspace=0 alt=\"{attachmentName}\" align=baseline src=\"cid:{contentId}\">{hrefEnd}<BR/>";
string fallbackBody = $"<HTML><BODY>{htmlImgEmbedded}</BODY></HTML>"; string fallbackBody = $"<HTML><BODY>{htmlImgEmbedded}</BODY></HTML>";
if (bodyString == null) if (bodyString == null)
@ -482,13 +509,15 @@ namespace Greenshot.Plugin.Office.OfficeExport
bodyString = fallbackBody; bodyString = fallbackBody;
} }
} }
newMail.HTMLBody = bodyString; newMail.HTMLBody = bodyString;
break; break;
} }
// So not save, otherwise the email is always stored in Draft folder.. (newMail.Save();) // So not save, otherwise the email is always stored in Draft folder.. (newMail.Save();)
newMail.Display(false); newMail.Display(false);
using var inspector = DisposableCom.Create((_Inspector)newMail.GetInspector); using var inspector = DisposableCom.Create((_Inspector) newMail.GetInspector);
if (inspector != null) if (inspector != null)
{ {
try try
@ -528,12 +557,14 @@ namespace Greenshot.Plugin.Office.OfficeExport
exported = true; exported = true;
} }
} }
return exported; return exported;
} }
catch (Exception e) catch (Exception e)
{ {
LOG.Error("Error while creating an outlook mail item: ", e); LOG.Error("Error while creating an outlook mail item: ", e);
} }
return exported; return exported;
} }
@ -548,6 +579,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
outlookApplication = DisposableCom.Create(new Application()); outlookApplication = DisposableCom.Create(new Application());
} }
InitializeVariables(outlookApplication); InitializeVariables(outlookApplication);
return outlookApplication; return outlookApplication;
} }
@ -568,10 +600,12 @@ namespace Greenshot.Plugin.Office.OfficeExport
// Ignore, probably no outlook running // Ignore, probably no outlook running
return null; return null;
} }
if ((outlookApplication != null) && (outlookApplication.ComObject != null)) if ((outlookApplication != null) && (outlookApplication.ComObject != null))
{ {
InitializeVariables(outlookApplication); InitializeVariables(outlookApplication);
} }
return outlookApplication; return outlookApplication;
} }
@ -587,7 +621,8 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
return null; return null;
} }
string defaultProfile = (string)profilesKey.GetValue(DefaultProfileValue);
string defaultProfile = (string) profilesKey.GetValue(DefaultProfileValue);
LOG.DebugFormat("defaultProfile={0}", defaultProfile); LOG.DebugFormat("defaultProfile={0}", defaultProfile);
using var profileKey = profilesKey.OpenSubKey(defaultProfile + @"\" + AccountKey, false); using var profileKey = profilesKey.OpenSubKey(defaultProfile + @"\" + AccountKey, false);
if (profileKey != null) if (profileKey != null)
@ -599,19 +634,21 @@ namespace Greenshot.Plugin.Office.OfficeExport
using var numberKey = profileKey.OpenSubKey(number, false); using var numberKey = profileKey.OpenSubKey(number, false);
if (numberKey != null) if (numberKey != null)
{ {
byte[] val = (byte[])numberKey.GetValue(NewSignatureValue); byte[] val = (byte[]) numberKey.GetValue(NewSignatureValue);
if (val == null) if (val == null)
{ {
continue; continue;
} }
string signatureName = ""; string signatureName = "";
foreach (byte b in val) foreach (byte b in val)
{ {
if (b != 0) if (b != 0)
{ {
signatureName += (char)b; signatureName += (char) b;
} }
} }
LOG.DebugFormat("Found email signature: {0}", signatureName); LOG.DebugFormat("Found email signature: {0}", signatureName);
var extension = format switch var extension = format switch
{ {
@ -628,6 +665,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
} }
} }
} }
return null; return null;
} }
@ -642,13 +680,15 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
return; return;
} }
if (!Version.TryParse(outlookApplication.ComObject.Version, out _outlookVersion)) if (!Version.TryParse(outlookApplication.ComObject.Version, out _outlookVersion))
{ {
LOG.Warn("Assuming outlook version 1997."); LOG.Warn("Assuming outlook version 1997.");
_outlookVersion = new Version((int)OfficeVersions.Office97, 0, 0, 0); _outlookVersion = new Version((int) OfficeVersions.Office97, 0, 0, 0);
} }
// Preventing retrieval of currentUser if Outlook is older than 2007 // Preventing retrieval of currentUser if Outlook is older than 2007
if (_outlookVersion.Major >= (int)OfficeVersions.Office2007) if (_outlookVersion.Major >= (int) OfficeVersions.Office2007)
{ {
try try
{ {
@ -657,6 +697,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
using var currentUser = DisposableCom.Create(mapiNamespace.ComObject.CurrentUser); using var currentUser = DisposableCom.Create(mapiNamespace.ComObject.CurrentUser);
_currentUser = currentUser.ComObject.Name; _currentUser = currentUser.ComObject.Name;
} }
LOG.InfoFormat("Current user: {0}", _currentUser); LOG.InfoFormat("Current user: {0}", _currentUser);
} }
catch (Exception exNs) catch (Exception exNs)
@ -682,7 +723,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
} }
// The activeexplorer inline response only works with >= 2013, Microsoft Outlook 15.0 Object Library // The activeexplorer inline response only works with >= 2013, Microsoft Outlook 15.0 Object Library
if (_outlookVersion.Major >= (int)OfficeVersions.Office2013) if (_outlookVersion.Major >= (int) OfficeVersions.Office2013)
{ {
// Check inline "panel" for Outlook 2013 // Check inline "panel" for Outlook 2013
using var activeExplorer = DisposableCom.Create(outlookApplication.ComObject.ActiveExplorer()); using var activeExplorer = DisposableCom.Create(outlookApplication.ComObject.ActiveExplorer());
@ -701,15 +742,17 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
inspectorCaptions.Add(caption, mailItem.Class); inspectorCaptions.Add(caption, mailItem.Class);
} }
break; break;
case AppointmentItem appointmentItem: case AppointmentItem appointmentItem:
if ((_outlookVersion.Major >= (int)OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings) if ((_outlookVersion.Major >= (int) OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
{ {
if (!string.IsNullOrEmpty(appointmentItem.Organizer) && appointmentItem.Organizer.Equals(_currentUser)) if (!string.IsNullOrEmpty(appointmentItem.Organizer) && appointmentItem.Organizer.Equals(_currentUser))
{ {
inspectorCaptions.Add(caption, appointmentItem.Class); inspectorCaptions.Add(caption, appointmentItem.Class);
} }
} }
break; break;
} }
} }
@ -740,10 +783,11 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
continue; continue;
} }
inspectorCaptions.Add(caption, mailItem.Class); inspectorCaptions.Add(caption, mailItem.Class);
break; break;
case AppointmentItem appointmentItem: case AppointmentItem appointmentItem:
if ((_outlookVersion.Major >= (int)OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings) if ((_outlookVersion.Major >= (int) OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
{ {
if (!string.IsNullOrEmpty(appointmentItem.Organizer) && !appointmentItem.Organizer.Equals(_currentUser)) if (!string.IsNullOrEmpty(appointmentItem.Organizer) && !appointmentItem.Organizer.Equals(_currentUser))
{ {
@ -756,6 +800,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
// skip, can't export to olAppointment // skip, can't export to olAppointment
continue; continue;
} }
inspectorCaptions.Add(caption, appointmentItem.Class); inspectorCaptions.Add(caption, appointmentItem.Class);
break; break;
default: default:
@ -769,6 +814,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
LOG.Warn("Problem retrieving word destinations, ignoring: ", ex); LOG.Warn("Problem retrieving word destinations, ignoring: ", ex);
} }
return inspectorCaptions; return inspectorCaptions;
} }
} }

View file

@ -60,6 +60,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
left = pageSetup.ComObject.SlideWidth / 2 - imageSize.Width / 2f; left = pageSetup.ComObject.SlideWidth / 2 - imageSize.Width / 2f;
top = pageSetup.ComObject.SlideHeight / 2 - imageSize.Height / 2f; top = pageSetup.ComObject.SlideHeight / 2 - imageSize.Height / 2f;
} }
float width = imageSize.Width; float width = imageSize.Width;
float height = imageSize.Height; float height = imageSize.Height;
IDisposableCom<Shape> shapeForCaption = null; IDisposableCom<Shape> shapeForCaption = null;
@ -86,6 +87,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
shapeForLocation.ComObject.Left = left; shapeForLocation.ComObject.Left = left;
} }
shapeForLocation.ComObject.Width = imageSize.Width; shapeForLocation.ComObject.Width = imageSize.Width;
if (height > shapeForLocation.ComObject.Height) if (height > shapeForLocation.ComObject.Height)
@ -98,6 +100,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
top = shapeForLocation.ComObject.Top + shapeForLocation.ComObject.Height / 2 - imageSize.Height / 2f; top = shapeForLocation.ComObject.Top + shapeForLocation.ComObject.Height / 2 - imageSize.Height / 2f;
} }
shapeForLocation.ComObject.Height = imageSize.Height; shapeForLocation.ComObject.Height = imageSize.Height;
} }
catch (Exception e) catch (Exception e)
@ -106,6 +109,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
using var slides = DisposableCom.Create(presentation.ComObject.Slides); using var slides = DisposableCom.Create(presentation.ComObject.Slides);
slide = DisposableCom.Create(slides.ComObject.Add(slides.ComObject.Count + 1, PpSlideLayout.ppLayoutBlank)); slide = DisposableCom.Create(slides.ComObject.Add(slides.ComObject.Count + 1, PpSlideLayout.ppLayoutBlank));
} }
using (var shapes = DisposableCom.Create(slide.ComObject.Shapes)) using (var shapes = DisposableCom.Create(slide.ComObject.Shapes))
{ {
using var shape = DisposableCom.Create(shapes.ComObject.AddPicture(tmpFile, MsoTriState.msoFalse, MsoTriState.msoTrue, 0, 0, width, height)); using var shape = DisposableCom.Create(shapes.ComObject.AddPicture(tmpFile, MsoTriState.msoFalse, MsoTriState.msoTrue, 0, 0, width, height));
@ -117,20 +121,24 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
shape.ComObject.LockAspectRatio = MsoTriState.msoFalse; shape.ComObject.LockAspectRatio = MsoTriState.msoFalse;
} }
shape.ComObject.ScaleHeight(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromMiddle); shape.ComObject.ScaleHeight(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromMiddle);
shape.ComObject.ScaleWidth(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromMiddle); shape.ComObject.ScaleWidth(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromMiddle);
if (hasScaledWidth) if (hasScaledWidth)
{ {
shape.ComObject.Width = width; shape.ComObject.Width = width;
} }
if (hasScaledHeight) if (hasScaledHeight)
{ {
shape.ComObject.Height = height; shape.ComObject.Height = height;
} }
shape.ComObject.Left = left; shape.ComObject.Left = left;
shape.ComObject.Top = top; shape.ComObject.Top = top;
shape.ComObject.AlternativeText = title; shape.ComObject.AlternativeText = title;
} }
if (shapeForCaption != null) if (shapeForCaption != null)
{ {
try try
@ -148,6 +156,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
LOG.Warn("Problem setting the title to a text-range", ex); LOG.Warn("Problem setting the title to a text-range", ex);
} }
} }
// Activate/Goto the slide // Activate/Goto the slide
try try
{ {
@ -194,10 +203,12 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
continue; continue;
} }
if (!presentation.ComObject.Name.StartsWith(presentationName)) if (!presentation.ComObject.Name.StartsWith(presentationName))
{ {
continue; continue;
} }
try try
{ {
AddPictureToPresentation(presentation, tmpFile, imageSize, title); AddPictureToPresentation(presentation, tmpFile, imageSize, title);
@ -209,6 +220,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
} }
} }
} }
return false; return false;
} }
@ -223,6 +235,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
powerPointApplication = DisposableCom.Create(new Application()); powerPointApplication = DisposableCom.Create(new Application());
} }
InitializeVariables(powerPointApplication); InitializeVariables(powerPointApplication);
return powerPointApplication; return powerPointApplication;
} }
@ -243,10 +256,12 @@ namespace Greenshot.Plugin.Office.OfficeExport
// Ignore, probably no PowerPoint running // Ignore, probably no PowerPoint running
return null; return null;
} }
if (powerPointApplication?.ComObject != null) if (powerPointApplication?.ComObject != null)
{ {
InitializeVariables(powerPointApplication); InitializeVariables(powerPointApplication);
} }
return powerPointApplication; return powerPointApplication;
} }
@ -271,10 +286,12 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
continue; continue;
} }
if (presentation.ComObject.ReadOnly == MsoTriState.msoTrue) if (presentation.ComObject.ReadOnly == MsoTriState.msoTrue)
{ {
continue; continue;
} }
if (IsAfter2003()) if (IsAfter2003())
{ {
if (presentation.ComObject.Final) if (presentation.ComObject.Final)
@ -282,6 +299,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
continue; continue;
} }
} }
yield return presentation.ComObject.Name; yield return presentation.ComObject.Name;
} }
} }
@ -296,10 +314,11 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
return; return;
} }
if (!Version.TryParse(powerpointApplication.ComObject.Version, out _powerpointVersion)) if (!Version.TryParse(powerpointApplication.ComObject.Version, out _powerpointVersion))
{ {
LOG.Warn("Assuming Powerpoint version 1997."); LOG.Warn("Assuming Powerpoint version 1997.");
_powerpointVersion = new Version((int)OfficeVersions.Office97, 0, 0, 0); _powerpointVersion = new Version((int) OfficeVersions.Office97, 0, 0, 0);
} }
} }
@ -332,13 +351,13 @@ namespace Greenshot.Plugin.Office.OfficeExport
} }
} }
} }
return isPictureAdded; return isPictureAdded;
} }
private bool IsAfter2003() private bool IsAfter2003()
{ {
return _powerpointVersion.Major > (int)OfficeVersions.Office2003; return _powerpointVersion.Major > (int) OfficeVersions.Office2003;
} }
} }
} }

View file

@ -53,6 +53,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
shape.ComObject.LockAspectRatio = MsoTriState.msoTrue; shape.ComObject.LockAspectRatio = MsoTriState.msoTrue;
} }
selection.ComObject.InsertAfter("\r\n"); selection.ComObject.InsertAfter("\r\n");
selection.ComObject.MoveDown(WdUnits.wdLine, 1, Type.Missing); selection.ComObject.MoveDown(WdUnits.wdLine, 1, Type.Missing);
return shape; return shape;
@ -69,6 +70,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
wordApplication = DisposableCom.Create(new Application()); wordApplication = DisposableCom.Create(new Application());
} }
InitializeVariables(wordApplication); InitializeVariables(wordApplication);
return wordApplication; return wordApplication;
} }
@ -89,10 +91,12 @@ namespace Greenshot.Plugin.Office.OfficeExport
// Ignore, probably no word running // Ignore, probably no word running
return null; return null;
} }
if ((wordApplication != null) && (wordApplication.ComObject != null)) if ((wordApplication != null) && (wordApplication.ComObject != null))
{ {
InitializeVariables(wordApplication); InitializeVariables(wordApplication);
} }
return wordApplication; return wordApplication;
} }
@ -116,6 +120,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
continue; continue;
} }
if (IsAfter2003()) if (IsAfter2003())
{ {
if (document.ComObject.Final) if (document.ComObject.Final)
@ -139,10 +144,11 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
return; return;
} }
if (!Version.TryParse(wordApplication.ComObject.Version, out _wordVersion)) if (!Version.TryParse(wordApplication.ComObject.Version, out _wordVersion))
{ {
LOG.Warn("Assuming Word version 1997."); LOG.Warn("Assuming Word version 1997.");
_wordVersion = new Version((int)OfficeVersions.Office97, 0, 0, 0); _wordVersion = new Version((int) OfficeVersions.Office97, 0, 0, 0);
} }
} }
@ -164,7 +170,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
using var documents = DisposableCom.Create(wordApplication.ComObject.Documents); using var documents = DisposableCom.Create(wordApplication.ComObject.Documents);
for (int i = 1; i <= documents.ComObject.Count; i++) for (int i = 1; i <= documents.ComObject.Count; i++)
{ {
using var wordDocument = DisposableCom.Create((_Document)documents.ComObject[i]); using var wordDocument = DisposableCom.Create((_Document) documents.ComObject[i]);
using var activeWindow = DisposableCom.Create(wordDocument.ComObject.ActiveWindow); using var activeWindow = DisposableCom.Create(wordDocument.ComObject.ActiveWindow);
if (activeWindow.ComObject.Caption.StartsWith(wordCaption)) if (activeWindow.ComObject.Caption.StartsWith(wordCaption))
{ {
@ -172,6 +178,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
} }
} }
} }
return false; return false;
} }
@ -184,7 +191,8 @@ namespace Greenshot.Plugin.Office.OfficeExport
/// <param name="address">string</param> /// <param name="address">string</param>
/// <param name="tooltip">string with the tooltip of the image</param> /// <param name="tooltip">string with the tooltip of the image</param>
/// <returns>bool</returns> /// <returns>bool</returns>
internal bool InsertIntoExistingDocument(IDisposableCom<Application> wordApplication, IDisposableCom<_Document> wordDocument, string tmpFile, string address, string tooltip) internal bool InsertIntoExistingDocument(IDisposableCom<Application> wordApplication, IDisposableCom<_Document> wordDocument, string tmpFile, string address,
string tooltip)
{ {
// Bug #1517: image will be inserted into that document, where the focus was last. It will not inserted into the chosen one. // Bug #1517: image will be inserted into that document, where the focus was last. It will not inserted into the chosen one.
// Solution: Make sure the selected document is active, otherwise the insert will be made in a different document! // Solution: Make sure the selected document is active, otherwise the insert will be made in a different document!
@ -204,6 +212,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
LOG.InfoFormat("No selection to insert {0} into found.", tmpFile); LOG.InfoFormat("No selection to insert {0} into found.", tmpFile);
return false; return false;
} }
// Add Picture // Add Picture
using (var shape = AddPictureToSelection(selection, tmpFile)) using (var shape = AddPictureToSelection(selection, tmpFile))
{ {
@ -214,6 +223,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
screentip = tooltip; screentip = tooltip;
} }
try try
{ {
using var hyperlinks = DisposableCom.Create(wordDocument.ComObject.Hyperlinks); using var hyperlinks = DisposableCom.Create(wordDocument.ComObject.Hyperlinks);
@ -225,6 +235,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
} }
} }
} }
try try
{ {
// When called for Outlook, the follow error is created: This object model command is not available in e-mail // When called for Outlook, the follow error is created: This object model command is not available in e-mail
@ -245,6 +256,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
LOG.WarnFormat("Couldn't set zoom to 100, error: {0}", e.Message); LOG.WarnFormat("Couldn't set zoom to 100, error: {0}", e.Message);
} }
} }
try try
{ {
wordApplication.ComObject.Activate(); wordApplication.ComObject.Activate();
@ -254,6 +266,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
LOG.Warn("Error activating word application", ex); LOG.Warn("Error activating word application", ex);
} }
try try
{ {
wordDocument.ComObject.Activate(); wordDocument.ComObject.Activate();
@ -263,6 +276,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
LOG.Warn("Error activating word document", ex); LOG.Warn("Error activating word document", ex);
} }
return true; return true;
} }
@ -279,6 +293,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
return; return;
} }
wordApplication.ComObject.Visible = true; wordApplication.ComObject.Visible = true;
wordApplication.ComObject.Activate(); wordApplication.ComObject.Activate();
// Create new Document // Create new Document
@ -299,6 +314,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
screentip = tooltip; screentip = tooltip;
} }
try try
{ {
using var hyperlinks = DisposableCom.Create(wordDocument.ComObject.Hyperlinks); using var hyperlinks = DisposableCom.Create(wordDocument.ComObject.Hyperlinks);
@ -313,6 +329,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
} }
} }
} }
try try
{ {
wordDocument.ComObject.Activate(); wordDocument.ComObject.Activate();
@ -322,6 +339,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{ {
LOG.Warn("Error activating word document", ex); LOG.Warn("Error activating word document", ex);
} }
try try
{ {
using var activeWindow = DisposableCom.Create(wordDocument.ComObject.ActiveWindow); using var activeWindow = DisposableCom.Create(wordDocument.ComObject.ActiveWindow);
@ -340,7 +358,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
/// <returns></returns> /// <returns></returns>
private bool IsAfter2003() private bool IsAfter2003()
{ {
return _wordVersion.Major > (int)OfficeVersions.Office2003; return _wordVersion.Major > (int) OfficeVersions.Office2003;
} }
} }
} }

View file

@ -28,6 +28,7 @@ namespace Greenshot.Plugin.Office.OfficeInterop
/// Use the plain text format /// Use the plain text format
/// </summary> /// </summary>
Text, Text,
/// <summary> /// <summary>
/// Use HTML format /// Use HTML format
/// </summary> /// </summary>

View file

@ -28,26 +28,32 @@ namespace Greenshot.Plugin.Office.OfficeInterop
/// Office 97 /// Office 97
/// </summary> /// </summary>
Office97 = 8, Office97 = 8,
/// <summary> /// <summary>
/// Office 2003 /// Office 2003
/// </summary> /// </summary>
Office2003 = 11, Office2003 = 11,
/// <summary> /// <summary>
/// Office 2007 /// Office 2007
/// </summary> /// </summary>
Office2007 = 12, Office2007 = 12,
/// <summary> /// <summary>
/// Office 2010 /// Office 2010
/// </summary> /// </summary>
Office2010 = 14, Office2010 = 14,
/// <summary> /// <summary>
/// Office 2013 /// Office 2013
/// </summary> /// </summary>
Office2013 = 15, Office2013 = 15,
/// <summary> /// <summary>
/// Office 2016 /// Office 2016
/// </summary> /// </summary>
Office2016 = 16, Office2016 = 16,
/// <summary> /// <summary>
/// Office 2019 /// Office 2019
/// </summary> /// </summary>

View file

@ -26,7 +26,8 @@ using GreenshotPlugin.Core;
using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin; using GreenshotPlugin.Interfaces.Plugin;
namespace Greenshot.Plugin.Office { namespace Greenshot.Plugin.Office
{
/// <summary> /// <summary>
/// This is the OfficePlugin base code /// This is the OfficePlugin base code
/// </summary> /// </summary>
@ -35,59 +36,87 @@ namespace Greenshot.Plugin.Office {
{ {
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OfficePlugin)); private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OfficePlugin));
public void Dispose() { public void Dispose()
{
Dispose(true); Dispose(true);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
protected void Dispose(bool disposing) { protected void Dispose(bool disposing)
{
// Do nothing // Do nothing
} }
private IEnumerable<IDestination> Destinations() { private IEnumerable<IDestination> Destinations()
{
IDestination destination; IDestination destination;
try { try
{
destination = new ExcelDestination(); destination = new ExcelDestination();
} catch { }
catch
{
destination = null; destination = null;
} }
if (destination != null) {
if (destination != null)
{
yield return destination; yield return destination;
} }
try { try
{
destination = new PowerpointDestination(); destination = new PowerpointDestination();
} catch { }
catch
{
destination = null; destination = null;
} }
if (destination != null) {
if (destination != null)
{
yield return destination; yield return destination;
} }
try { try
{
destination = new WordDestination(); destination = new WordDestination();
} catch { }
catch
{
destination = null; destination = null;
} }
if (destination != null) {
if (destination != null)
{
yield return destination; yield return destination;
} }
try { try
{
destination = new OutlookDestination(); destination = new OutlookDestination();
} catch { }
catch
{
destination = null; destination = null;
} }
if (destination != null) {
if (destination != null)
{
yield return destination; yield return destination;
} }
try { try
{
destination = new OneNoteDestination(); destination = new OneNoteDestination();
} catch { }
catch
{
destination = null; destination = null;
} }
if (destination != null) {
if (destination != null)
{
yield return destination; yield return destination;
} }
} }
@ -97,19 +126,22 @@ namespace Greenshot.Plugin.Office {
/// Implementation of the IGreenshotPlugin.Initialize /// Implementation of the IGreenshotPlugin.Initialize
/// </summary> /// </summary>
/// <returns>true if plugin is initialized, false if not (doesn't show)</returns> /// <returns>true if plugin is initialized, false if not (doesn't show)</returns>
public bool Initialize() { public bool Initialize()
{
SimpleServiceProvider.Current.AddService(Destinations()); SimpleServiceProvider.Current.AddService(Destinations());
return true; return true;
} }
public void Shutdown() { public void Shutdown()
{
LOG.Debug("Office Plugin shutdown."); LOG.Debug("Office Plugin shutdown.");
} }
/// <summary> /// <summary>
/// Implementation of the IPlugin.Configure /// Implementation of the IPlugin.Configure
/// </summary> /// </summary>
public void Configure() { public void Configure()
{
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }

View file

@ -19,10 +19,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Greenshot.Plugin.Photobucket.Forms { namespace Greenshot.Plugin.Photobucket.Forms
{
/// <summary> /// <summary>
/// This class is needed for design-time resolving of the language files /// This class is needed for design-time resolving of the language files
/// </summary> /// </summary>
public class PhotobucketForm : GreenshotPlugin.Controls.GreenshotForm { public class PhotobucketForm : GreenshotPlugin.Controls.GreenshotForm
{
} }
} }

View file

@ -19,11 +19,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Greenshot.Plugin.Photobucket.Forms { namespace Greenshot.Plugin.Photobucket.Forms
{
/// <summary> /// <summary>
/// Description of PasswordRequestForm. /// Description of PasswordRequestForm.
/// </summary> /// </summary>
public partial class SettingsForm : PhotobucketForm { public partial class SettingsForm : PhotobucketForm
{
public SettingsForm() public SettingsForm()
{ {
// //

View file

@ -19,8 +19,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Greenshot.Plugin.Photobucket { namespace Greenshot.Plugin.Photobucket
public enum LangKey { {
public enum LangKey
{
upload_menu_item, upload_menu_item,
upload_failure, upload_failure,
communication_wait, communication_wait,

View file

@ -25,26 +25,35 @@ using GreenshotPlugin.Controls;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.IniFile; using GreenshotPlugin.IniFile;
namespace Greenshot.Plugin.Photobucket { namespace Greenshot.Plugin.Photobucket
{
/// <summary> /// <summary>
/// Description of PhotobucketConfiguration. /// Description of PhotobucketConfiguration.
/// </summary> /// </summary>
[IniSection("Photobucket", Description="Greenshot Photobucket Plugin configuration")] [IniSection("Photobucket", Description = "Greenshot Photobucket Plugin configuration")]
public class PhotobucketConfiguration : IniSection { public class PhotobucketConfiguration : IniSection
[IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")] {
[IniProperty("UploadFormat", Description = "What file type to use for uploading", DefaultValue = "png")]
public OutputFormat UploadFormat { get; set; } public OutputFormat UploadFormat { get; set; }
[IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
[IniProperty("UploadJpegQuality", Description = "JPEG file save quality in %.", DefaultValue = "80")]
public int UploadJpegQuality { get; set; } public int UploadJpegQuality { get; set; }
[IniProperty("UploadReduceColors", Description="Reduce color amount of the uploaded image to 256", DefaultValue="False")]
[IniProperty("UploadReduceColors", Description = "Reduce color amount of the uploaded image to 256", DefaultValue = "False")]
public bool UploadReduceColors { get; set; } public bool UploadReduceColors { get; set; }
[IniProperty("UsePageLink", Description = "Use pagelink instead of direct link on the clipboard", DefaultValue = "False")] [IniProperty("UsePageLink", Description = "Use pagelink instead of direct link on the clipboard", DefaultValue = "False")]
public bool UsePageLink { get; set; } public bool UsePageLink { get; set; }
[IniProperty("Token", Description = "The Photobucket token", Encrypted=true, ExcludeIfNull=true)]
[IniProperty("Token", Description = "The Photobucket token", Encrypted = true, ExcludeIfNull = true)]
public string Token { get; set; } public string Token { get; set; }
[IniProperty("TokenSecret", Description = "The Photobucket token secret", Encrypted=true, ExcludeIfNull=true)]
[IniProperty("TokenSecret", Description = "The Photobucket token secret", Encrypted = true, ExcludeIfNull = true)]
public string TokenSecret { get; set; } public string TokenSecret { get; set; }
[IniProperty("SubDomain", Description = "The Photobucket api subdomain", Encrypted = true, ExcludeIfNull = true)] [IniProperty("SubDomain", Description = "The Photobucket api subdomain", Encrypted = true, ExcludeIfNull = true)]
public string SubDomain { get; set; } public string SubDomain { get; set; }
[IniProperty("Username", Description = "The Photobucket api username", ExcludeIfNull = true)] [IniProperty("Username", Description = "The Photobucket api username", ExcludeIfNull = true)]
public string Username { get; set; } public string Username { get; set; }
@ -52,18 +61,19 @@ namespace Greenshot.Plugin.Photobucket {
/// A form for username/password /// A form for username/password
/// </summary> /// </summary>
/// <returns>bool true if OK was pressed, false if cancel</returns> /// <returns>bool true if OK was pressed, false if cancel</returns>
public bool ShowConfigDialog() { public bool ShowConfigDialog()
{
SettingsForm settingsForm = null; SettingsForm settingsForm = null;
new PleaseWaitForm().ShowAndWait("Photobucket", Language.GetString("photobucket", LangKey.communication_wait), new PleaseWaitForm().ShowAndWait("Photobucket", Language.GetString("photobucket", LangKey.communication_wait),
delegate { delegate { settingsForm = new SettingsForm(); }
settingsForm = new SettingsForm();
}
); );
DialogResult result = settingsForm.ShowDialog(); DialogResult result = settingsForm.ShowDialog();
if (result == DialogResult.OK) { if (result == DialogResult.OK)
{
return true; return true;
} }
return false; return false;
} }
} }

Some files were not shown because too many files have changed in this diff Show more