mirror of
https://github.com/greenshot/greenshot
synced 2025-07-15 01:23:47 -07:00
Code formatting (indents etc.) to get it consistent, simplify it for contributors.
This commit is contained in:
parent
726644de99
commit
e8c0b307ee
435 changed files with 46647 additions and 39014 deletions
|
@ -25,12 +25,14 @@ using Greenshot.Plugin.Box.Forms;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.IniFile;
|
||||
|
||||
namespace Greenshot.Plugin.Box {
|
||||
namespace Greenshot.Plugin.Box
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of ImgurConfiguration.
|
||||
/// </summary>
|
||||
[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")]
|
||||
public OutputFormat UploadFormat { get; set; }
|
||||
|
||||
|
@ -42,6 +44,7 @@ namespace Greenshot.Plugin.Box {
|
|||
|
||||
[IniProperty("UseSharedLink", Description = "Use the shared link, instead of the private, on the clipboard", DefaultValue = "True")]
|
||||
public bool UseSharedLink { get; set; }
|
||||
|
||||
[IniProperty("FolderId", Description = "Folder ID to upload to, only change if you know what you are doing!", DefaultValue = "0")]
|
||||
public string FolderId { get; set; }
|
||||
|
||||
|
@ -51,30 +54,26 @@ namespace Greenshot.Plugin.Box {
|
|||
/// <summary>
|
||||
/// Not stored
|
||||
/// </summary>
|
||||
public string AccessToken {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string AccessToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Not stored
|
||||
/// </summary>
|
||||
public DateTimeOffset AccessTokenExpires {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public DateTimeOffset AccessTokenExpires { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A form for token
|
||||
/// </summary>
|
||||
/// <returns>bool true if OK was pressed, false if cancel</returns>
|
||||
public bool ShowConfigDialog() {
|
||||
public bool ShowConfigDialog()
|
||||
{
|
||||
DialogResult result = new SettingsForm().ShowDialog();
|
||||
if (result == DialogResult.OK) {
|
||||
if (result == DialogResult.OK)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -24,10 +24,14 @@ using System.Drawing;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.Interfaces;
|
||||
|
||||
namespace Greenshot.Plugin.Box {
|
||||
public class BoxDestination : AbstractDestination {
|
||||
namespace Greenshot.Plugin.Box
|
||||
{
|
||||
public class BoxDestination : AbstractDestination
|
||||
{
|
||||
private readonly BoxPlugin _plugin;
|
||||
public BoxDestination(BoxPlugin plugin) {
|
||||
|
||||
public BoxDestination(BoxPlugin plugin)
|
||||
{
|
||||
_plugin = plugin;
|
||||
}
|
||||
|
||||
|
@ -35,20 +39,25 @@ namespace Greenshot.Plugin.Box {
|
|||
|
||||
public override string Description => Language.GetString("box", LangKey.upload_menu_item);
|
||||
|
||||
public override Image DisplayIcon {
|
||||
get {
|
||||
public override Image DisplayIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
ComponentResourceManager resources = new ComponentResourceManager(typeof(BoxPlugin));
|
||||
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);
|
||||
string uploadUrl = _plugin.Upload(captureDetails, surface);
|
||||
if (uploadUrl != null) {
|
||||
if (uploadUrl != null)
|
||||
{
|
||||
exportInformation.ExportMade = true;
|
||||
exportInformation.Uri = uploadUrl;
|
||||
}
|
||||
|
||||
ProcessExport(exportInformation, surface);
|
||||
return exportInformation;
|
||||
}
|
||||
|
|
|
@ -22,39 +22,35 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Greenshot.Plugin.Box {
|
||||
namespace Greenshot.Plugin.Box
|
||||
{
|
||||
[DataContract]
|
||||
public class Authorization {
|
||||
[DataMember(Name = "access_token")]
|
||||
public string AccessToken { get; set; }
|
||||
[DataMember(Name = "expires_in")]
|
||||
public int ExpiresIn { get; set; }
|
||||
[DataMember(Name = "refresh_token")]
|
||||
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; }
|
||||
public class Authorization
|
||||
{
|
||||
[DataMember(Name = "access_token")] public string AccessToken { get; set; }
|
||||
[DataMember(Name = "expires_in")] public int ExpiresIn { get; set; }
|
||||
[DataMember(Name = "refresh_token")] public string RefreshToken { get; set; }
|
||||
[DataMember(Name = "token_type")] public string TokenType { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class FileEntry {
|
||||
[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; }
|
||||
public class SharedLink
|
||||
{
|
||||
[DataMember(Name = "url")] public string Url { get; set; }
|
||||
[DataMember(Name = "download_url")] public string DownloadUrl { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class Upload {
|
||||
[DataMember(Name = "entries")]
|
||||
public List<FileEntry> Entries { get; set; }
|
||||
public class FileEntry
|
||||
{
|
||||
[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; }
|
||||
}
|
||||
}
|
|
@ -30,18 +30,21 @@ using GreenshotPlugin.IniFile;
|
|||
using GreenshotPlugin.Interfaces;
|
||||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
|
||||
namespace Greenshot.Plugin.Box {
|
||||
namespace Greenshot.Plugin.Box
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the Box base code
|
||||
/// </summary>
|
||||
[Plugin("Box", true)]
|
||||
public class BoxPlugin : IGreenshotPlugin {
|
||||
public class BoxPlugin : IGreenshotPlugin
|
||||
{
|
||||
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(BoxPlugin));
|
||||
private static BoxConfiguration _config;
|
||||
private ComponentResourceManager _resources;
|
||||
private ToolStripMenuItem _itemPlugInConfig;
|
||||
|
||||
public void Dispose() {
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
@ -59,13 +62,14 @@ namespace Greenshot.Plugin.Box {
|
|||
/// <summary>
|
||||
/// Implementation of the IGreenshotPlugin.Initialize
|
||||
/// </summary>
|
||||
public bool Initialize() {
|
||||
|
||||
public bool Initialize()
|
||||
{
|
||||
// Register configuration (don't need the configuration itself)
|
||||
_config = IniConfig.GetIniSection<BoxConfiguration>();
|
||||
_resources = new ComponentResourceManager(typeof(BoxPlugin));
|
||||
SimpleServiceProvider.Current.AddService<IDestination>(new BoxDestination(this));
|
||||
_itemPlugInConfig = new ToolStripMenuItem {
|
||||
_itemPlugInConfig = new ToolStripMenuItem
|
||||
{
|
||||
Image = (Image) _resources.GetObject("Box"),
|
||||
Text = Language.GetString("box", LangKey.Configure)
|
||||
};
|
||||
|
@ -76,49 +80,57 @@ namespace Greenshot.Plugin.Box {
|
|||
return true;
|
||||
}
|
||||
|
||||
public void OnLanguageChanged(object sender, EventArgs e) {
|
||||
if (_itemPlugInConfig != null) {
|
||||
public void OnLanguageChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (_itemPlugInConfig != null)
|
||||
{
|
||||
_itemPlugInConfig.Text = Language.GetString("box", LangKey.Configure);
|
||||
}
|
||||
}
|
||||
|
||||
public void Shutdown() {
|
||||
public void Shutdown()
|
||||
{
|
||||
LOG.Debug("Box Plugin shutdown.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of the IPlugin.Configure
|
||||
/// </summary>
|
||||
public void Configure() {
|
||||
public void Configure()
|
||||
{
|
||||
_config.ShowConfigDialog();
|
||||
}
|
||||
|
||||
public void ConfigMenuClick(object sender, EventArgs eventArgs) {
|
||||
public void ConfigMenuClick(object sender, EventArgs eventArgs)
|
||||
{
|
||||
_config.ShowConfigDialog();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will be called when the menu item in the Editor is clicked
|
||||
/// </summary>
|
||||
public string Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload) {
|
||||
public string Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload)
|
||||
{
|
||||
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, false);
|
||||
try {
|
||||
try
|
||||
{
|
||||
string url = null;
|
||||
string filename = Path.GetFileName(FilenameHelper.GetFilename(_config.UploadFormat, captureDetails));
|
||||
SurfaceContainer imageToUpload = new SurfaceContainer(surfaceToUpload, outputSettings, filename);
|
||||
|
||||
new PleaseWaitForm().ShowAndWait("Box", Language.GetString("box", LangKey.communication_wait),
|
||||
delegate {
|
||||
url = BoxUtils.UploadToBox(imageToUpload, captureDetails.Title, filename);
|
||||
}
|
||||
delegate { url = BoxUtils.UploadToBox(imageToUpload, captureDetails.Title, filename); }
|
||||
);
|
||||
|
||||
if (url != null && _config.AfterUploadLinkToClipBoard) {
|
||||
if (url != null && _config.AfterUploadLinkToClipBoard)
|
||||
{
|
||||
ClipboardHelper.SetClipboardData(url);
|
||||
}
|
||||
|
||||
return url;
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.Error("Error uploading.", ex);
|
||||
MessageBox.Show(Language.GetString("box", LangKey.upload_failure) + " " + ex.Message);
|
||||
return null;
|
||||
|
|
|
@ -27,12 +27,13 @@ using GreenshotPlugin.Core;
|
|||
using GreenshotPlugin.Core.OAuth;
|
||||
using GreenshotPlugin.IniFile;
|
||||
|
||||
namespace Greenshot.Plugin.Box {
|
||||
|
||||
namespace Greenshot.Plugin.Box
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of BoxUtils.
|
||||
/// </summary>
|
||||
public static class BoxUtils {
|
||||
public static class BoxUtils
|
||||
{
|
||||
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(BoxUtils));
|
||||
private static readonly BoxConfiguration Config = IniConfig.GetIniSection<BoxConfiguration>();
|
||||
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="settings">OAuth2Settings</param>
|
||||
/// <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);
|
||||
|
||||
byte[] data = Encoding.UTF8.GetBytes(content);
|
||||
using (var requestStream = webRequest.GetRequestStream()) {
|
||||
using (var requestStream = webRequest.GetRequestStream())
|
||||
{
|
||||
requestStream.Write(data, 0, data.Length);
|
||||
}
|
||||
|
||||
return NetworkHelper.GetResponseAsString(webRequest);
|
||||
}
|
||||
|
||||
|
@ -63,8 +67,8 @@ namespace Greenshot.Plugin.Box {
|
|||
/// <param name="title">Title of box upload</param>
|
||||
/// <param name="filename">Filename of box upload</param>
|
||||
/// <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
|
||||
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
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, UploadFileUri, settings);
|
||||
IDictionary<string, object> parameters = new Dictionary<string, object>
|
||||
{
|
||||
{ "file", image },
|
||||
{ "parent_id", Config.FolderId }
|
||||
{
|
||||
"file", image
|
||||
},
|
||||
{
|
||||
"parent_id", Config.FolderId
|
||||
}
|
||||
};
|
||||
|
||||
NetworkHelper.WriteMultipartFormData(webRequest, parameters);
|
||||
|
@ -100,13 +109,17 @@ namespace Greenshot.Plugin.Box {
|
|||
var upload = JsonSerializer.Deserialize<Upload>(response);
|
||||
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);
|
||||
var file = JsonSerializer.Deserialize<FileEntry>(filesResponse);
|
||||
return file.SharedLink.Url;
|
||||
}
|
||||
|
||||
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.
|
||||
Config.RefreshToken = settings.RefreshToken;
|
||||
Config.AccessToken = settings.AccessToken;
|
||||
|
@ -116,17 +129,20 @@ namespace Greenshot.Plugin.Box {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A simple helper class for the DataContractJsonSerializer
|
||||
/// </summary>
|
||||
internal static class JsonSerializer {
|
||||
internal static class JsonSerializer
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper method to parse JSON to object
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="jsonString"></param>
|
||||
/// <returns></returns>
|
||||
public static T Deserialize<T>(string jsonString) {
|
||||
public static T Deserialize<T>(string jsonString)
|
||||
{
|
||||
var deserializer = new DataContractJsonSerializer(typeof(T));
|
||||
using var stream = new MemoryStream();
|
||||
byte[] content = Encoding.UTF8.GetBytes(jsonString);
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
|
||||
using GreenshotPlugin.Controls;
|
||||
|
||||
namespace Greenshot.Plugin.Box.Forms {
|
||||
public class BoxForm : GreenshotForm {
|
||||
namespace Greenshot.Plugin.Box.Forms
|
||||
{
|
||||
public class BoxForm : GreenshotForm
|
||||
{
|
||||
}
|
||||
}
|
|
@ -19,12 +19,15 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Greenshot.Plugin.Box.Forms {
|
||||
namespace Greenshot.Plugin.Box.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of PasswordRequestForm.
|
||||
/// </summary>
|
||||
public partial class SettingsForm : BoxForm {
|
||||
public SettingsForm() {
|
||||
public partial class SettingsForm : BoxForm
|
||||
{
|
||||
public SettingsForm()
|
||||
{
|
||||
//
|
||||
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||
//
|
||||
|
|
|
@ -18,8 +18,11 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* 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_failure,
|
||||
communication_wait,
|
||||
|
|
|
@ -26,16 +26,21 @@ using GreenshotConfluencePlugin.confluence;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.IniFile;
|
||||
|
||||
namespace Greenshot.Plugin.Confluence {
|
||||
public class Page {
|
||||
public Page(RemotePage page) {
|
||||
namespace Greenshot.Plugin.Confluence
|
||||
{
|
||||
public class Page
|
||||
{
|
||||
public Page(RemotePage page)
|
||||
{
|
||||
Id = page.id;
|
||||
Title = page.title;
|
||||
SpaceKey = page.space;
|
||||
Url = page.url;
|
||||
Content = page.content;
|
||||
}
|
||||
public Page(RemoteSearchResult searchResult, string space) {
|
||||
|
||||
public Page(RemoteSearchResult searchResult, string space)
|
||||
{
|
||||
Id = searchResult.id;
|
||||
Title = searchResult.title;
|
||||
SpaceKey = space;
|
||||
|
@ -43,53 +48,39 @@ namespace Greenshot.Plugin.Confluence {
|
|||
Content = searchResult.excerpt;
|
||||
}
|
||||
|
||||
public Page(RemotePageSummary pageSummary) {
|
||||
public Page(RemotePageSummary pageSummary)
|
||||
{
|
||||
Id = pageSummary.id;
|
||||
Title = pageSummary.title;
|
||||
SpaceKey = pageSummary.space;
|
||||
Url = pageSummary.url;
|
||||
}
|
||||
public long Id {
|
||||
get;
|
||||
set;
|
||||
|
||||
public long Id { get; 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;
|
||||
set;
|
||||
}
|
||||
public string Url {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string Content {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string SpaceKey {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
public class Space {
|
||||
public Space(RemoteSpaceSummary space) {
|
||||
|
||||
public class Space
|
||||
{
|
||||
public Space(RemoteSpaceSummary space)
|
||||
{
|
||||
Key = space.key;
|
||||
Name = space.name;
|
||||
}
|
||||
public string Key {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string Name {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string Key { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For details see the Confluence API site
|
||||
/// See: http://confluence.atlassian.com/display/CONFDEV/Remote+API+Specification
|
||||
/// </summary>
|
||||
public class ConfluenceConnector : IDisposable {
|
||||
public class ConfluenceConnector : IDisposable
|
||||
{
|
||||
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ConfluenceConnector));
|
||||
private const string AuthFailedExceptionName = "com.atlassian.confluence.rpc.AuthenticationFailedException";
|
||||
private const string V2Failed = "AXIS";
|
||||
|
@ -102,29 +93,37 @@ namespace Greenshot.Plugin.Confluence {
|
|||
private string _url;
|
||||
private readonly Cache<string, RemotePage> _pageCache = new Cache<string, RemotePage>(60 * Config.Timeout);
|
||||
|
||||
public void Dispose() {
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected void Dispose(bool disposing) {
|
||||
if (_confluence != null) {
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if (_confluence != null)
|
||||
{
|
||||
Logout();
|
||||
}
|
||||
if (disposing) {
|
||||
if (_confluence != null) {
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (_confluence != null)
|
||||
{
|
||||
_confluence.Dispose();
|
||||
_confluence = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ConfluenceConnector(string url, int timeout) {
|
||||
public ConfluenceConnector(string url, int timeout)
|
||||
{
|
||||
_timeout = timeout;
|
||||
Init(url);
|
||||
}
|
||||
|
||||
private void Init(string url) {
|
||||
private void Init(string url)
|
||||
{
|
||||
_url = url;
|
||||
_confluence = new ConfluenceSoapServiceService
|
||||
{
|
||||
|
@ -133,7 +132,8 @@ namespace Greenshot.Plugin.Confluence {
|
|||
};
|
||||
}
|
||||
|
||||
~ConfluenceConnector() {
|
||||
~ConfluenceConnector()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
|
@ -141,21 +141,29 @@ namespace Greenshot.Plugin.Confluence {
|
|||
/// Internal login which catches the exceptions
|
||||
/// </summary>
|
||||
/// <returns>true if login was done sucessfully</returns>
|
||||
private bool DoLogin(string user, string password) {
|
||||
try {
|
||||
private bool DoLogin(string user, string password)
|
||||
{
|
||||
try
|
||||
{
|
||||
_credentials = _confluence.login(user, password);
|
||||
_loggedInTime = DateTime.Now;
|
||||
_loggedIn = true;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// 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"));
|
||||
return DoLogin(user, password);
|
||||
}
|
||||
|
||||
// check if auth failed
|
||||
if (e.Message.Contains(AuthFailedExceptionName)) {
|
||||
if (e.Message.Contains(AuthFailedExceptionName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Not an authentication issue
|
||||
_loggedIn = false;
|
||||
_credentials = null;
|
||||
|
@ -163,12 +171,15 @@ namespace Greenshot.Plugin.Confluence {
|
|||
e.Data.Add("url", _url);
|
||||
throw;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Login() {
|
||||
public void Login()
|
||||
{
|
||||
Logout();
|
||||
try {
|
||||
try
|
||||
{
|
||||
// Get the system name, so the user knows where to login to
|
||||
string systemName = _url.Replace(ConfluenceConfiguration.DEFAULT_POSTFIX1, "");
|
||||
systemName = systemName.Replace(ConfluenceConfiguration.DEFAULT_POSTFIX2, "");
|
||||
|
@ -176,53 +187,73 @@ namespace Greenshot.Plugin.Confluence {
|
|||
{
|
||||
Name = null
|
||||
};
|
||||
while (dialog.Show(dialog.Name) == DialogResult.OK) {
|
||||
if (DoLogin(dialog.Name, dialog.Password)) {
|
||||
if (dialog.SaveChecked) {
|
||||
while (dialog.Show(dialog.Name) == DialogResult.OK)
|
||||
{
|
||||
if (DoLogin(dialog.Name, dialog.Password))
|
||||
{
|
||||
if (dialog.SaveChecked)
|
||||
{
|
||||
dialog.Confirm(true);
|
||||
}
|
||||
|
||||
return;
|
||||
} else {
|
||||
try {
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
dialog.Confirm(false);
|
||||
} catch (ApplicationException e) {
|
||||
}
|
||||
catch (ApplicationException e)
|
||||
{
|
||||
// exception handling ...
|
||||
Log.Error("Problem using the credentials dialog", e);
|
||||
}
|
||||
|
||||
// For every windows version after XP show an incorrect password baloon
|
||||
dialog.IncorrectPassword = true;
|
||||
// Make sure the dialog is display, the password was false!
|
||||
dialog.AlwaysDisplay = true;
|
||||
}
|
||||
}
|
||||
} catch (ApplicationException e) {
|
||||
}
|
||||
catch (ApplicationException e)
|
||||
{
|
||||
// exception handling ...
|
||||
Log.Error("Problem using the credentials dialog", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void Logout() {
|
||||
if (_credentials != null) {
|
||||
public void Logout()
|
||||
{
|
||||
if (_credentials != null)
|
||||
{
|
||||
_confluence.logout(_credentials);
|
||||
_credentials = null;
|
||||
_loggedIn = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckCredentials() {
|
||||
if (_loggedIn) {
|
||||
if (_loggedInTime.AddMinutes(_timeout-1).CompareTo(DateTime.Now) < 0) {
|
||||
private void CheckCredentials()
|
||||
{
|
||||
if (_loggedIn)
|
||||
{
|
||||
if (_loggedInTime.AddMinutes(_timeout - 1).CompareTo(DateTime.Now) < 0)
|
||||
{
|
||||
Logout();
|
||||
Login();
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Login();
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
// Comment is ignored, see: http://jira.atlassian.com/browse/CONF-9395
|
||||
var attachment = new RemoteAttachment
|
||||
|
@ -234,69 +265,88 @@ namespace Greenshot.Plugin.Confluence {
|
|||
_confluence.addAttachment(_credentials, pageId, attachment, image.ToByteArray());
|
||||
}
|
||||
|
||||
public Page GetPage(string spaceKey, string pageTitle) {
|
||||
public Page GetPage(string spaceKey, string pageTitle)
|
||||
{
|
||||
RemotePage page = null;
|
||||
string cacheKey = spaceKey + pageTitle;
|
||||
if (_pageCache.Contains(cacheKey)) {
|
||||
if (_pageCache.Contains(cacheKey))
|
||||
{
|
||||
page = _pageCache[cacheKey];
|
||||
}
|
||||
if (page == null) {
|
||||
|
||||
if (page == null)
|
||||
{
|
||||
CheckCredentials();
|
||||
page = _confluence.getPage(_credentials, spaceKey, pageTitle);
|
||||
_pageCache.Add(cacheKey, page);
|
||||
}
|
||||
|
||||
return new Page(page);
|
||||
}
|
||||
|
||||
public Page GetPage(long pageId) {
|
||||
public Page GetPage(long pageId)
|
||||
{
|
||||
RemotePage page = null;
|
||||
string cacheKey = pageId.ToString();
|
||||
|
||||
if (_pageCache.Contains(cacheKey)) {
|
||||
if (_pageCache.Contains(cacheKey))
|
||||
{
|
||||
page = _pageCache[cacheKey];
|
||||
}
|
||||
if (page == null) {
|
||||
|
||||
if (page == null)
|
||||
{
|
||||
CheckCredentials();
|
||||
page = _confluence.getPage(_credentials, pageId);
|
||||
_pageCache.Add(cacheKey, page);
|
||||
}
|
||||
|
||||
return new Page(page);
|
||||
}
|
||||
|
||||
public Page GetSpaceHomepage(Space spaceSummary) {
|
||||
public Page GetSpaceHomepage(Space spaceSummary)
|
||||
{
|
||||
CheckCredentials();
|
||||
RemoteSpace spaceDetail = _confluence.getSpace(_credentials, spaceSummary.Key);
|
||||
RemotePage page = _confluence.getPage(_credentials, spaceDetail.homePage);
|
||||
return new Page(page);
|
||||
}
|
||||
|
||||
public IEnumerable<Space> GetSpaceSummaries() {
|
||||
public IEnumerable<Space> GetSpaceSummaries()
|
||||
{
|
||||
CheckCredentials();
|
||||
RemoteSpaceSummary[] spaces = _confluence.getSpaces(_credentials);
|
||||
foreach(RemoteSpaceSummary space in spaces) {
|
||||
foreach (RemoteSpaceSummary space in spaces)
|
||||
{
|
||||
yield return new Space(space);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Page> GetPageChildren(Page parentPage) {
|
||||
public IEnumerable<Page> GetPageChildren(Page parentPage)
|
||||
{
|
||||
CheckCredentials();
|
||||
RemotePageSummary[] pages = _confluence.getChildren(_credentials, parentPage.Id);
|
||||
foreach(RemotePageSummary page in pages) {
|
||||
foreach (RemotePageSummary page in pages)
|
||||
{
|
||||
yield return new Page(page);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Page> GetPageSummaries(Space space) {
|
||||
public IEnumerable<Page> GetPageSummaries(Space space)
|
||||
{
|
||||
CheckCredentials();
|
||||
RemotePageSummary[] pages = _confluence.getPages(_credentials, space.Key);
|
||||
foreach(RemotePageSummary page in pages) {
|
||||
foreach (RemotePageSummary page in pages)
|
||||
{
|
||||
yield return new Page(page);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Page> SearchPages(string query, string space) {
|
||||
public IEnumerable<Page> SearchPages(string query, string space)
|
||||
{
|
||||
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);
|
||||
if ("page".Equals(searchResult.type))
|
||||
{
|
||||
|
|
|
@ -23,63 +23,45 @@ using System;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.IniFile;
|
||||
|
||||
namespace Greenshot.Plugin.Confluence {
|
||||
namespace Greenshot.Plugin.Confluence
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of ConfluenceConfiguration.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[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_POSTFIX2 = "/rpc/soap-axis/confluenceservice-v2?wsdl";
|
||||
public const string DEFAULT_PREFIX = "http://";
|
||||
private const string DEFAULT_URL = DEFAULT_PREFIX + "confluence";
|
||||
|
||||
[IniProperty("Url", Description = "Url to Confluence system, including wsdl.", DefaultValue = DEFAULT_URL)]
|
||||
public string Url {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string Url { get; set; }
|
||||
|
||||
[IniProperty("Timeout", Description = "Session timeout in minutes", DefaultValue = "30")]
|
||||
public int Timeout {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public int Timeout { get; set; }
|
||||
|
||||
[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")]
|
||||
public int UploadJpegQuality {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public int UploadJpegQuality { get; set; }
|
||||
|
||||
[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("OpenPageAfterUpload", Description = "Open the page where the picture is uploaded after upload", DefaultValue = "True")]
|
||||
public bool OpenPageAfterUpload {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
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;
|
||||
}
|
||||
public bool CopyWikiMarkupForImageToClipboard { get; set; }
|
||||
|
||||
[IniProperty("SearchSpaceKey", Description = "Key of last space that was searched for")]
|
||||
public string SearchSpaceKey {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string SearchSpaceKey { get; set; }
|
||||
|
||||
[IniProperty("IncludePersonSpaces", Description = "Include personal spaces in the search & browse spaces list", DefaultValue = "False")]
|
||||
public bool IncludePersonSpaces {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public bool IncludePersonSpaces { get; set; }
|
||||
}
|
||||
}
|
|
@ -32,121 +32,145 @@ using GreenshotPlugin.IniFile;
|
|||
using GreenshotPlugin.Interfaces;
|
||||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
|
||||
namespace Greenshot.Plugin.Confluence {
|
||||
namespace Greenshot.Plugin.Confluence
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of ConfluenceDestination.
|
||||
/// </summary>
|
||||
public class ConfluenceDestination : AbstractDestination {
|
||||
public class ConfluenceDestination : AbstractDestination
|
||||
{
|
||||
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ConfluenceDestination));
|
||||
private static readonly ConfluenceConfiguration ConfluenceConfig = IniConfig.GetIniSection<ConfluenceConfiguration>();
|
||||
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
|
||||
private static readonly Image ConfluenceIcon;
|
||||
private readonly Page _page;
|
||||
|
||||
static ConfluenceDestination() {
|
||||
static ConfluenceDestination()
|
||||
{
|
||||
IsInitialized = false;
|
||||
try {
|
||||
try
|
||||
{
|
||||
Uri confluenceIconUri = new Uri("/GreenshotConfluencePlugin;component/Images/Confluence.ico", UriKind.Relative);
|
||||
using (Stream iconStream = Application.GetResourceStream(confluenceIconUri)?.Stream)
|
||||
{
|
||||
// TODO: Check what to do with the IImage
|
||||
ConfluenceIcon = ImageHelper.FromStream(iconStream);
|
||||
}
|
||||
|
||||
IsInitialized = true;
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
public override string Designation {
|
||||
get {
|
||||
return "Confluence";
|
||||
}
|
||||
public override string Designation
|
||||
{
|
||||
get { return "Confluence"; }
|
||||
}
|
||||
|
||||
public override string Description {
|
||||
get {
|
||||
if (_page == null) {
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_page == null)
|
||||
{
|
||||
return Language.GetString("confluence", LangKey.upload_menu_item);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return Language.GetString("confluence", LangKey.upload_menu_item) + ": \"" + _page.Title + "\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsDynamic {
|
||||
get {
|
||||
return true;
|
||||
}
|
||||
public override bool IsDynamic
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override bool IsActive {
|
||||
get {
|
||||
return base.IsActive && !string.IsNullOrEmpty(ConfluenceConfig.Url);
|
||||
}
|
||||
public override bool IsActive
|
||||
{
|
||||
get { return base.IsActive && !string.IsNullOrEmpty(ConfluenceConfig.Url); }
|
||||
}
|
||||
|
||||
public override Image DisplayIcon {
|
||||
get {
|
||||
return ConfluenceIcon;
|
||||
}
|
||||
public override Image DisplayIcon
|
||||
{
|
||||
get { return ConfluenceIcon; }
|
||||
}
|
||||
|
||||
public override IEnumerable<IDestination> DynamicDestinations() {
|
||||
if (ConfluencePlugin.ConfluenceConnectorNoLogin == null || !ConfluencePlugin.ConfluenceConnectorNoLogin.IsLoggedIn) {
|
||||
public override IEnumerable<IDestination> DynamicDestinations()
|
||||
{
|
||||
if (ConfluencePlugin.ConfluenceConnectorNoLogin == null || !ConfluencePlugin.ConfluenceConnectorNoLogin.IsLoggedIn)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
List<Page> currentPages = ConfluenceUtils.GetCurrentPages();
|
||||
if (currentPages == null || currentPages.Count == 0) {
|
||||
if (currentPages == null || currentPages.Count == 0)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
foreach(Page currentPage in currentPages) {
|
||||
|
||||
foreach (Page currentPage in currentPages)
|
||||
{
|
||||
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);
|
||||
// force password check to take place before the pages load
|
||||
if (!ConfluencePlugin.ConfluenceConnector.IsLoggedIn) {
|
||||
if (!ConfluencePlugin.ConfluenceConnector.IsLoggedIn)
|
||||
{
|
||||
return exportInformation;
|
||||
}
|
||||
|
||||
Page selectedPage = _page;
|
||||
bool openPage = (_page == null) && ConfluenceConfig.OpenPageAfterUpload;
|
||||
string filename = FilenameHelper.GetFilenameWithoutExtensionFromPattern(CoreConfig.OutputFileFilenamePattern, captureDetails);
|
||||
if (selectedPage == null) {
|
||||
if (selectedPage == null)
|
||||
{
|
||||
Forms.ConfluenceUpload confluenceUpload = new Forms.ConfluenceUpload(filename);
|
||||
bool? dialogResult = confluenceUpload.ShowDialog();
|
||||
if (dialogResult.HasValue && dialogResult.Value) {
|
||||
if (dialogResult.HasValue && dialogResult.Value)
|
||||
{
|
||||
selectedPage = confluenceUpload.SelectedPage;
|
||||
if (confluenceUpload.IsOpenPageSelected) {
|
||||
if (confluenceUpload.IsOpenPageSelected)
|
||||
{
|
||||
openPage = false;
|
||||
}
|
||||
|
||||
filename = confluenceUpload.Filename;
|
||||
}
|
||||
}
|
||||
|
||||
string extension = "." + ConfluenceConfig.UploadFormat;
|
||||
if (!filename.ToLower().EndsWith(extension)) {
|
||||
if (!filename.ToLower().EndsWith(extension))
|
||||
{
|
||||
filename += extension;
|
||||
}
|
||||
if (selectedPage != null) {
|
||||
|
||||
if (selectedPage != null)
|
||||
{
|
||||
bool uploaded = Upload(surface, selectedPage, filename, out var errorMessage);
|
||||
if (uploaded) {
|
||||
if (openPage) {
|
||||
if (uploaded)
|
||||
{
|
||||
if (openPage)
|
||||
{
|
||||
try
|
||||
{
|
||||
Process.Start(selectedPage.Url);
|
||||
|
@ -156,23 +180,32 @@ namespace Greenshot.Plugin.Confluence {
|
|||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
exportInformation.ExportMade = true;
|
||||
exportInformation.Uri = selectedPage.Url;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
exportInformation.ErrorMessage = errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessExport(exportInformation, surface);
|
||||
return exportInformation;
|
||||
}
|
||||
|
||||
private bool Upload(ISurface surfaceToUpload, Page page, string filename, out string errorMessage) {
|
||||
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(ConfluenceConfig.UploadFormat, ConfluenceConfig.UploadJpegQuality, ConfluenceConfig.UploadReduceColors);
|
||||
private bool Upload(ISurface surfaceToUpload, Page page, string filename, out string errorMessage)
|
||||
{
|
||||
SurfaceOutputSettings outputSettings =
|
||||
new SurfaceOutputSettings(ConfluenceConfig.UploadFormat, ConfluenceConfig.UploadJpegQuality, ConfluenceConfig.UploadReduceColors);
|
||||
errorMessage = null;
|
||||
try {
|
||||
try
|
||||
{
|
||||
new PleaseWaitForm().ShowAndWait(Description, Language.GetString("confluence", LangKey.communication_wait),
|
||||
delegate {
|
||||
ConfluencePlugin.ConfluenceConnector.AddAttachment(page.Id, "image/" + ConfluenceConfig.UploadFormat.ToString().ToLower(), null, filename, new SurfaceContainer(surfaceToUpload, outputSettings, filename));
|
||||
delegate
|
||||
{
|
||||
ConfluencePlugin.ConfluenceConnector.AddAttachment(page.Id, "image/" + ConfluenceConfig.UploadFormat.ToString().ToLower(), null, filename,
|
||||
new SurfaceContainer(surfaceToUpload, outputSettings, filename));
|
||||
}
|
||||
);
|
||||
Log.Debug("Uploaded to Confluence.");
|
||||
|
@ -180,25 +213,39 @@ namespace Greenshot.Plugin.Confluence {
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int retryCount = 2;
|
||||
while (retryCount >= 0) {
|
||||
try {
|
||||
while (retryCount >= 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
Clipboard.SetText("!" + filename + "!");
|
||||
break;
|
||||
} catch (Exception ee) {
|
||||
if (retryCount == 0) {
|
||||
}
|
||||
catch (Exception ee)
|
||||
{
|
||||
if (retryCount == 0)
|
||||
{
|
||||
Log.Error(ee);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
} finally {
|
||||
}
|
||||
finally
|
||||
{
|
||||
--retryCount;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch(Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
errorMessage = e.Message;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,53 +28,70 @@ using GreenshotPlugin.IniFile;
|
|||
using GreenshotPlugin.Interfaces;
|
||||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
|
||||
namespace Greenshot.Plugin.Confluence {
|
||||
namespace Greenshot.Plugin.Confluence
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the ConfluencePlugin base code
|
||||
/// </summary>
|
||||
[Plugin("Confluence", true)]
|
||||
public class ConfluencePlugin : IGreenshotPlugin {
|
||||
public class ConfluencePlugin : IGreenshotPlugin
|
||||
{
|
||||
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ConfluencePlugin));
|
||||
private static ConfluenceConnector _confluenceConnector;
|
||||
private static ConfluenceConfiguration _config;
|
||||
|
||||
public void Dispose() {
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected void Dispose(bool disposing) {
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
//if (disposing) {}
|
||||
}
|
||||
|
||||
private static void CreateConfluenceConnector() {
|
||||
if (_confluenceConnector == null) {
|
||||
if (_config.Url.Contains("soap-axis")) {
|
||||
private static void CreateConfluenceConnector()
|
||||
{
|
||||
if (_confluenceConnector == null)
|
||||
{
|
||||
if (_config.Url.Contains("soap-axis"))
|
||||
{
|
||||
_confluenceConnector = new ConfluenceConnector(_config.Url, _config.Timeout);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
_confluenceConnector = new ConfluenceConnector(_config.Url + ConfluenceConfiguration.DEFAULT_POSTFIX2, _config.Timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static ConfluenceConnector ConfluenceConnectorNoLogin {
|
||||
get {
|
||||
return _confluenceConnector;
|
||||
}
|
||||
public static ConfluenceConnector ConfluenceConnectorNoLogin
|
||||
{
|
||||
get { return _confluenceConnector; }
|
||||
}
|
||||
|
||||
public static ConfluenceConnector ConfluenceConnector {
|
||||
get {
|
||||
if (_confluenceConnector == null) {
|
||||
public static ConfluenceConnector ConfluenceConnector
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_confluenceConnector == null)
|
||||
{
|
||||
CreateConfluenceConnector();
|
||||
}
|
||||
try {
|
||||
if (_confluenceConnector != null && !_confluenceConnector.IsLoggedIn) {
|
||||
|
||||
try
|
||||
{
|
||||
if (_confluenceConnector != null && !_confluenceConnector.IsLoggedIn)
|
||||
{
|
||||
_confluenceConnector.Login();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessageBox.Show(Language.GetFormattedString("confluence", LangKey.login_error, e.Message));
|
||||
}
|
||||
|
||||
return _confluenceConnector;
|
||||
}
|
||||
}
|
||||
|
@ -82,29 +99,39 @@ namespace Greenshot.Plugin.Confluence {
|
|||
/// <summary>
|
||||
/// Implementation of the IGreenshotPlugin.Initialize
|
||||
/// </summary>
|
||||
public bool Initialize() {
|
||||
public bool Initialize()
|
||||
{
|
||||
// Register configuration (don't need the configuration itself)
|
||||
_config = IniConfig.GetIniSection<ConfluenceConfiguration>();
|
||||
if(_config.IsDirty) {
|
||||
if (_config.IsDirty)
|
||||
{
|
||||
IniConfig.Save();
|
||||
}
|
||||
try {
|
||||
|
||||
try
|
||||
{
|
||||
TranslationManager.Instance.TranslationProvider = new LanguageXMLTranslationProvider();
|
||||
//resources = new ComponentResourceManager(typeof(ConfluencePlugin));
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.ErrorFormat("Problem in ConfluencePlugin.Initialize: {0}", ex.Message);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ConfluenceDestination.IsInitialized)
|
||||
{
|
||||
SimpleServiceProvider.Current.AddService<IDestination>(new ConfluenceDestination());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Shutdown() {
|
||||
public void Shutdown()
|
||||
{
|
||||
LOG.Debug("Confluence Plugin shutdown.");
|
||||
if (_confluenceConnector != null) {
|
||||
if (_confluenceConnector != null)
|
||||
{
|
||||
_confluenceConnector.Logout();
|
||||
_confluenceConnector = null;
|
||||
}
|
||||
|
@ -113,20 +140,26 @@ namespace Greenshot.Plugin.Confluence {
|
|||
/// <summary>
|
||||
/// Implementation of the IPlugin.Configure
|
||||
/// </summary>
|
||||
public void Configure() {
|
||||
public void Configure()
|
||||
{
|
||||
ConfluenceConfiguration clonedConfig = _config.Clone();
|
||||
ConfluenceConfigurationForm configForm = new ConfluenceConfigurationForm(clonedConfig);
|
||||
string url = _config.Url;
|
||||
bool? dialogResult = configForm.ShowDialog();
|
||||
if (dialogResult.HasValue && dialogResult.Value) {
|
||||
if (dialogResult.HasValue && dialogResult.Value)
|
||||
{
|
||||
// copy the new object to the old...
|
||||
clonedConfig.CloneTo(_config);
|
||||
IniConfig.Save();
|
||||
if (_confluenceConnector != null) {
|
||||
if (!url.Equals(_config.Url)) {
|
||||
if (_confluenceConnector.IsLoggedIn) {
|
||||
if (_confluenceConnector != null)
|
||||
{
|
||||
if (!url.Equals(_config.Url))
|
||||
{
|
||||
if (_confluenceConnector.IsLoggedIn)
|
||||
{
|
||||
_confluenceConnector.Logout();
|
||||
}
|
||||
|
||||
_confluenceConnector = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,76 +26,106 @@ using System.Text.RegularExpressions;
|
|||
using System.Windows.Automation;
|
||||
using GreenshotPlugin.Core;
|
||||
|
||||
namespace Greenshot.Plugin.Confluence {
|
||||
namespace Greenshot.Plugin.Confluence
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of ConfluenceUtils.
|
||||
/// </summary>
|
||||
public class ConfluenceUtils {
|
||||
public class 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>();
|
||||
Regex pageIdRegex = new Regex(@"pageId=(\d+)");
|
||||
Regex spacePageRegex = new Regex(@"\/display\/([^\/]+)\/([^#]+)");
|
||||
foreach(string browserurl in GetBrowserUrls()) {
|
||||
foreach (string browserurl in GetBrowserUrls())
|
||||
{
|
||||
string url;
|
||||
try {
|
||||
try
|
||||
{
|
||||
url = Uri.UnescapeDataString(browserurl).Replace("+", " ");
|
||||
} catch {
|
||||
}
|
||||
catch
|
||||
{
|
||||
LOG.WarnFormat("Error processing URL: {0}", browserurl);
|
||||
continue;
|
||||
}
|
||||
|
||||
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);
|
||||
try {
|
||||
try
|
||||
{
|
||||
bool pageDouble = false;
|
||||
foreach(Page page in pages) {
|
||||
if (page.Id == pageId) {
|
||||
foreach (Page page in pages)
|
||||
{
|
||||
if (page.Id == pageId)
|
||||
{
|
||||
pageDouble = true;
|
||||
LOG.DebugFormat("Skipping double page with ID {0}", pageId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!pageDouble) {
|
||||
|
||||
if (!pageDouble)
|
||||
{
|
||||
Page page = ConfluencePlugin.ConfluenceConnector.GetPage(pageId);
|
||||
LOG.DebugFormat("Adding page {0}", page.Title);
|
||||
pages.Add(page);
|
||||
}
|
||||
|
||||
continue;
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Preventing security problems
|
||||
LOG.DebugFormat("Couldn't get page details for PageID {0}", pageId);
|
||||
LOG.Warn(ex);
|
||||
}
|
||||
}
|
||||
|
||||
MatchCollection spacePageMatch = spacePageRegex.Matches(url);
|
||||
if (spacePageMatch != null && spacePageMatch.Count > 0) {
|
||||
if (spacePageMatch[0].Groups.Count >= 2) {
|
||||
if (spacePageMatch != null && spacePageMatch.Count > 0)
|
||||
{
|
||||
if (spacePageMatch[0].Groups.Count >= 2)
|
||||
{
|
||||
string space = spacePageMatch[0].Groups[1].Value;
|
||||
string title = spacePageMatch[0].Groups[2].Value;
|
||||
if (string.IsNullOrEmpty(title) || string.IsNullOrEmpty(space)) {
|
||||
if (string.IsNullOrEmpty(title) || string.IsNullOrEmpty(space))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (title.EndsWith("#")) {
|
||||
|
||||
if (title.EndsWith("#"))
|
||||
{
|
||||
title = title.Substring(0, title.Length - 1);
|
||||
}
|
||||
try {
|
||||
|
||||
try
|
||||
{
|
||||
bool pageDouble = false;
|
||||
foreach(Page page in pages) {
|
||||
if (page.Title.Equals(title)) {
|
||||
foreach (Page page in pages)
|
||||
{
|
||||
if (page.Title.Equals(title))
|
||||
{
|
||||
LOG.DebugFormat("Skipping double page with title {0}", title);
|
||||
pageDouble = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!pageDouble) {
|
||||
|
||||
if (!pageDouble)
|
||||
{
|
||||
Page page = ConfluencePlugin.ConfluenceConnector.GetPage(space, title);
|
||||
LOG.DebugFormat("Adding page {0}", page.Title);
|
||||
pages.Add(page);
|
||||
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Preventing security problems
|
||||
LOG.DebugFormat("Couldn't get page details for space {0} / title {1}", space, title);
|
||||
LOG.Warn(ex);
|
||||
|
@ -103,49 +133,65 @@ namespace Greenshot.Plugin.Confluence {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pages;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> GetBrowserUrls() {
|
||||
private static IEnumerable<string> GetBrowserUrls()
|
||||
{
|
||||
HashSet<string> urls = new HashSet<string>();
|
||||
|
||||
// FireFox
|
||||
foreach (WindowDetails window in WindowDetails.GetAllWindows("MozillaWindowClass")) {
|
||||
if (window.Text.Length == 0) {
|
||||
continue;
|
||||
}
|
||||
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) {
|
||||
foreach (WindowDetails window in WindowDetails.GetAllWindows("MozillaWindowClass"))
|
||||
{
|
||||
if (window.Text.Length == 0)
|
||||
{
|
||||
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);
|
||||
if (docElement == null) {
|
||||
if (docElement == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
foreach (AutomationPattern pattern in docElement.GetSupportedPatterns()) {
|
||||
if (pattern.ProgrammaticName != "ValuePatternIdentifiers.Pattern") {
|
||||
|
||||
foreach (AutomationPattern pattern in docElement.GetSupportedPatterns())
|
||||
{
|
||||
if (pattern.ProgrammaticName != "ValuePatternIdentifiers.Pattern")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string url = (docElement.GetCurrentPattern(pattern) as ValuePattern).Current.Value;
|
||||
if (!string.IsNullOrEmpty(url)) {
|
||||
if (!string.IsNullOrEmpty(url))
|
||||
{
|
||||
urls.Add(url);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach(string url in IEHelper.GetIEUrls().Distinct()) {
|
||||
foreach (string url in IEHelper.GetIEUrls().Distinct())
|
||||
{
|
||||
urls.Add(url);
|
||||
}
|
||||
|
||||
return urls;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -28,24 +28,32 @@ using System.Reflection;
|
|||
using System.Windows.Data;
|
||||
using GreenshotPlugin.Core;
|
||||
|
||||
namespace Greenshot.Plugin.Confluence {
|
||||
public class EnumDisplayer : IValueConverter {
|
||||
namespace Greenshot.Plugin.Confluence
|
||||
{
|
||||
public class EnumDisplayer : IValueConverter
|
||||
{
|
||||
private Type _type;
|
||||
private IDictionary _displayValues;
|
||||
private IDictionary _reverseValues;
|
||||
|
||||
public Type Type {
|
||||
public Type Type
|
||||
{
|
||||
get { return _type; }
|
||||
set {
|
||||
if (!value.IsEnum) {
|
||||
set
|
||||
{
|
||||
if (!value.IsEnum)
|
||||
{
|
||||
throw new ArgumentException("parameter is not an Enumerated type", nameof(value));
|
||||
}
|
||||
|
||||
_type = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ReadOnlyCollection<string> DisplayNames {
|
||||
get {
|
||||
public ReadOnlyCollection<string> DisplayNames
|
||||
{
|
||||
get
|
||||
{
|
||||
var genericTypeDefinition = typeof(Dictionary<,>).GetGenericTypeDefinition();
|
||||
if (genericTypeDefinition != null)
|
||||
{
|
||||
|
@ -59,38 +67,47 @@ namespace Greenshot.Plugin.Confluence {
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
string displayKey = GetDisplayKeyValue(a);
|
||||
object enumValue = field.GetValue(null);
|
||||
|
||||
string displayString;
|
||||
if (displayKey != null && Language.HasKey(displayKey)) {
|
||||
if (displayKey != null && Language.HasKey(displayKey))
|
||||
{
|
||||
displayString = Language.GetString(displayKey);
|
||||
}
|
||||
|
||||
displayString = displayKey ?? enumValue.ToString();
|
||||
|
||||
_displayValues.Add(enumValue, displayString);
|
||||
_reverseValues.Add(displayString, enumValue);
|
||||
}
|
||||
|
||||
return new List<string>((IEnumerable<string>) _displayValues.Values).AsReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetDisplayKeyValue(DisplayKeyAttribute[] a) {
|
||||
if (a == null || a.Length == 0) {
|
||||
private static string GetDisplayKeyValue(DisplayKeyAttribute[] a)
|
||||
{
|
||||
if (a == null || a.Length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
DisplayKeyAttribute dka = a[0];
|
||||
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];
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,20 +21,24 @@
|
|||
|
||||
using System.Windows;
|
||||
|
||||
namespace Greenshot.Plugin.Confluence.Forms {
|
||||
namespace Greenshot.Plugin.Confluence.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ConfluenceConfigurationForm.xaml
|
||||
/// </summary>
|
||||
public partial class ConfluenceConfigurationForm : Window {
|
||||
public partial class ConfluenceConfigurationForm : Window
|
||||
{
|
||||
public ConfluenceConfiguration Config { get; }
|
||||
|
||||
public ConfluenceConfigurationForm(ConfluenceConfiguration config) {
|
||||
public ConfluenceConfigurationForm(ConfluenceConfiguration config)
|
||||
{
|
||||
DataContext = config;
|
||||
Config = config;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Button_OK_Click(object sender, RoutedEventArgs e) {
|
||||
private void Button_OK_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DialogResult = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Greenshot.Plugin.Confluence.Forms {
|
||||
namespace Greenshot.Plugin.Confluence.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ConfluencePagePicker.xaml
|
||||
/// </summary>
|
||||
|
@ -29,27 +30,34 @@ namespace Greenshot.Plugin.Confluence.Forms {
|
|||
{
|
||||
private readonly ConfluenceUpload _confluenceUpload;
|
||||
|
||||
public ConfluencePagePicker(ConfluenceUpload confluenceUpload, List<Page> pagesToPick) {
|
||||
public ConfluencePagePicker(ConfluenceUpload confluenceUpload, List<Page> pagesToPick)
|
||||
{
|
||||
_confluenceUpload = confluenceUpload;
|
||||
DataContext = pagesToPick;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void PageListView_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) {
|
||||
private void PageListView_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
|
||||
{
|
||||
SelectionChanged();
|
||||
}
|
||||
|
||||
private void SelectionChanged() {
|
||||
if (PageListView.HasItems && PageListView.SelectedItems.Count > 0) {
|
||||
private void SelectionChanged()
|
||||
{
|
||||
if (PageListView.HasItems && PageListView.SelectedItems.Count > 0)
|
||||
{
|
||||
_confluenceUpload.SelectedPage = (Page) PageListView.SelectedItem;
|
||||
// Make sure the uploader knows we selected an already opened page
|
||||
_confluenceUpload.IsOpenPageSelected = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
_confluenceUpload.SelectedPage = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void Page_Loaded(object sender, System.Windows.RoutedEventArgs e) {
|
||||
private void Page_Loaded(object sender, System.Windows.RoutedEventArgs e)
|
||||
{
|
||||
SelectionChanged();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,8 @@ using System.Linq;
|
|||
using System.Windows;
|
||||
using GreenshotPlugin.IniFile;
|
||||
|
||||
namespace Greenshot.Plugin.Confluence.Forms {
|
||||
namespace Greenshot.Plugin.Confluence.Forms
|
||||
{
|
||||
public partial class ConfluenceSearch
|
||||
{
|
||||
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 ConfluenceSearch(ConfluenceUpload confluenceUpload) {
|
||||
public ConfluenceSearch(ConfluenceUpload confluenceUpload)
|
||||
{
|
||||
_confluenceUpload = confluenceUpload;
|
||||
DataContext = this;
|
||||
InitializeComponent();
|
||||
if (ConfluenceConfig.SearchSpaceKey == null) {
|
||||
if (ConfluenceConfig.SearchSpaceKey == null)
|
||||
{
|
||||
SpaceComboBox.SelectedItem = Spaces.FirstOrDefault();
|
||||
} else {
|
||||
foreach(var space in Spaces) {
|
||||
if (space.Key.Equals(ConfluenceConfig.SearchSpaceKey)) {
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var space in Spaces)
|
||||
{
|
||||
if (space.Key.Equals(ConfluenceConfig.SearchSpaceKey))
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
private void SelectionChanged() {
|
||||
if (PageListView.HasItems && PageListView.SelectedItems.Count > 0) {
|
||||
private void SelectionChanged()
|
||||
{
|
||||
if (PageListView.HasItems && PageListView.SelectedItems.Count > 0)
|
||||
{
|
||||
_confluenceUpload.SelectedPage = (Page) PageListView.SelectedItem;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
_confluenceUpload.SelectedPage = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void Search_Click(object sender, RoutedEventArgs e) {
|
||||
private void Search_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DoSearch();
|
||||
}
|
||||
|
||||
private void DoSearch() {
|
||||
private void DoSearch()
|
||||
{
|
||||
string spaceKey = (string) SpaceComboBox.SelectedValue;
|
||||
ConfluenceConfig.SearchSpaceKey = spaceKey;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private void SearchText_KeyDown(object sender, System.Windows.Input.KeyEventArgs e) {
|
||||
if (e.Key == System.Windows.Input.Key.Return && Search.IsEnabled) {
|
||||
private void SearchText_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == System.Windows.Input.Key.Return && Search.IsEnabled)
|
||||
{
|
||||
DoSearch();
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void Page_Loaded(object sender, RoutedEventArgs e) {
|
||||
private void Page_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,8 @@ using System.Windows.Controls;
|
|||
using System.Windows.Input;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace Greenshot.Plugin.Confluence.Forms {
|
||||
namespace Greenshot.Plugin.Confluence.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ConfluenceTreePicker.xaml
|
||||
/// </summary>
|
||||
|
@ -38,28 +39,36 @@ namespace Greenshot.Plugin.Confluence.Forms {
|
|||
private readonly ConfluenceUpload _confluenceUpload;
|
||||
private bool _isInitDone;
|
||||
|
||||
public ConfluenceTreePicker(ConfluenceUpload confluenceUpload) {
|
||||
public ConfluenceTreePicker(ConfluenceUpload confluenceUpload)
|
||||
{
|
||||
_confluenceConnector = ConfluencePlugin.ConfluenceConnector;
|
||||
_confluenceUpload = confluenceUpload;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void PageTreeViewItem_DoubleClick(object sender, MouseButtonEventArgs eventArgs) {
|
||||
private void PageTreeViewItem_DoubleClick(object sender, MouseButtonEventArgs eventArgs)
|
||||
{
|
||||
Log.Debug("spaceTreeViewItem_MouseLeftButtonDown is called!");
|
||||
TreeViewItem clickedItem = eventArgs.Source as TreeViewItem;
|
||||
if (clickedItem?.Tag is not Page page) {
|
||||
if (clickedItem?.Tag is not Page page)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (clickedItem.HasItems)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Debug("Loading pages for page: " + page.Title);
|
||||
new Thread(() => {
|
||||
new Thread(() =>
|
||||
{
|
||||
Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart) (() => { ShowBusy.Visibility = Visibility.Visible; }));
|
||||
var pages = _confluenceConnector.GetPageChildren(page).OrderBy(p => p.Title);
|
||||
Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)(() => {
|
||||
foreach(var childPage in pages) {
|
||||
Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart) (() =>
|
||||
{
|
||||
foreach (var childPage in pages)
|
||||
{
|
||||
Log.Debug("Adding page: " + childPage.Title);
|
||||
var pageTreeViewItem = new TreeViewItem
|
||||
{
|
||||
|
@ -70,32 +79,46 @@ namespace Greenshot.Plugin.Confluence.Forms {
|
|||
pageTreeViewItem.PreviewMouseDoubleClick += PageTreeViewItem_DoubleClick;
|
||||
pageTreeViewItem.PreviewMouseLeftButtonDown += PageTreeViewItem_Click;
|
||||
}
|
||||
|
||||
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!");
|
||||
if (eventArgs.Source is not TreeViewItem clickedItem) {
|
||||
if (eventArgs.Source is not TreeViewItem clickedItem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Page page = clickedItem.Tag as Page;
|
||||
_confluenceUpload.SelectedPage = page;
|
||||
if (page != null) {
|
||||
if (page != null)
|
||||
{
|
||||
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;
|
||||
if (_isInitDone) {
|
||||
if (_isInitDone)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ShowBusy.Visibility = Visibility.Visible;
|
||||
new Thread(() => {
|
||||
Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)(() => {
|
||||
foreach (Space space in _confluenceUpload.Spaces) {
|
||||
new Thread(() =>
|
||||
{
|
||||
Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart) (() =>
|
||||
{
|
||||
foreach (Space space in _confluenceUpload.Spaces)
|
||||
{
|
||||
TreeViewItem spaceTreeViewItem = new TreeViewItem
|
||||
{
|
||||
Header = space.Name,
|
||||
|
@ -103,7 +126,8 @@ namespace Greenshot.Plugin.Confluence.Forms {
|
|||
};
|
||||
|
||||
// Get homepage
|
||||
try {
|
||||
try
|
||||
{
|
||||
Page page = _confluenceConnector.GetSpaceHomepage(space);
|
||||
TreeViewItem pageTreeViewItem = new TreeViewItem
|
||||
{
|
||||
|
@ -114,14 +138,20 @@ namespace Greenshot.Plugin.Confluence.Forms {
|
|||
pageTreeViewItem.PreviewMouseLeftButtonDown += PageTreeViewItem_Click;
|
||||
spaceTreeViewItem.Items.Add(pageTreeViewItem);
|
||||
ConfluenceTreeView.Items.Add(spaceTreeViewItem);
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Can't get homepage for space : " + space.Name + " (" + ex.Message + ")");
|
||||
}
|
||||
}
|
||||
|
||||
ShowBusy.Visibility = Visibility.Collapsed;
|
||||
_isInitDone = true;
|
||||
}));
|
||||
}) { Name = "Loading spaces for confluence"}.Start();
|
||||
})
|
||||
{
|
||||
Name = "Loading spaces for confluence"
|
||||
}.Start();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,91 +25,116 @@ using System.Linq;
|
|||
using System.Threading;
|
||||
using System.Windows;
|
||||
|
||||
namespace Greenshot.Plugin.Confluence.Forms {
|
||||
namespace Greenshot.Plugin.Confluence.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ConfluenceUpload.xaml
|
||||
/// </summary>
|
||||
public partial class ConfluenceUpload : Window {
|
||||
public partial class ConfluenceUpload : Window
|
||||
{
|
||||
private System.Windows.Controls.Page _pickerPage;
|
||||
public System.Windows.Controls.Page PickerPage {
|
||||
get {
|
||||
if (_pickerPage == null) {
|
||||
|
||||
public System.Windows.Controls.Page PickerPage
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_pickerPage == null)
|
||||
{
|
||||
List<Page> pages = ConfluenceUtils.GetCurrentPages();
|
||||
if (pages != null && pages.Count > 0) {
|
||||
if (pages != null && pages.Count > 0)
|
||||
{
|
||||
_pickerPage = new ConfluencePagePicker(this, pages);
|
||||
}
|
||||
}
|
||||
|
||||
return _pickerPage;
|
||||
}
|
||||
}
|
||||
|
||||
private System.Windows.Controls.Page _searchPage;
|
||||
public System.Windows.Controls.Page SearchPage {
|
||||
|
||||
public System.Windows.Controls.Page SearchPage
|
||||
{
|
||||
get { return _searchPage ??= new ConfluenceSearch(this); }
|
||||
}
|
||||
|
||||
private System.Windows.Controls.Page _browsePage;
|
||||
public System.Windows.Controls.Page BrowsePage {
|
||||
|
||||
public System.Windows.Controls.Page BrowsePage
|
||||
{
|
||||
get { return _browsePage ??= new ConfluenceTreePicker(this); }
|
||||
}
|
||||
|
||||
private Page _selectedPage;
|
||||
public Page SelectedPage {
|
||||
|
||||
public Page SelectedPage
|
||||
{
|
||||
get => _selectedPage;
|
||||
set {
|
||||
set
|
||||
{
|
||||
_selectedPage = value;
|
||||
Upload.IsEnabled = _selectedPage != null;
|
||||
IsOpenPageSelected = false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsOpenPageSelected {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string Filename {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public bool IsOpenPageSelected { get; set; }
|
||||
public string Filename { get; set; }
|
||||
|
||||
private static DateTime _lastLoad = DateTime.Now;
|
||||
private static IList<Space> _spaces;
|
||||
public IList<Space> Spaces {
|
||||
get {
|
||||
|
||||
public IList<Space> Spaces
|
||||
{
|
||||
get
|
||||
{
|
||||
UpdateSpaces();
|
||||
while (_spaces == null) {
|
||||
while (_spaces == null)
|
||||
{
|
||||
Thread.Sleep(300);
|
||||
}
|
||||
|
||||
return _spaces;
|
||||
}
|
||||
}
|
||||
|
||||
public ConfluenceUpload(string filename) {
|
||||
public ConfluenceUpload(string filename)
|
||||
{
|
||||
Filename = filename;
|
||||
InitializeComponent();
|
||||
DataContext = this;
|
||||
UpdateSpaces();
|
||||
if (PickerPage == null) {
|
||||
if (PickerPage == null)
|
||||
{
|
||||
PickerTab.Visibility = Visibility.Collapsed;
|
||||
SearchTab.IsSelected = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSpaces() {
|
||||
if (_spaces != null && DateTime.Now.AddMinutes(-60).CompareTo(_lastLoad) > 0) {
|
||||
private void UpdateSpaces()
|
||||
{
|
||||
if (_spaces != null && DateTime.Now.AddMinutes(-60).CompareTo(_lastLoad) > 0)
|
||||
{
|
||||
// Reset
|
||||
_spaces = null;
|
||||
}
|
||||
|
||||
// Check if load is needed
|
||||
if (_spaces == null) {
|
||||
(new Thread(() => {
|
||||
if (_spaces == null)
|
||||
{
|
||||
(new Thread(() =>
|
||||
{
|
||||
_spaces = ConfluencePlugin.ConfluenceConnector.GetSpaceSummaries().OrderBy(s => s.Name).ToList();
|
||||
_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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,10 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Greenshot.Plugin.Confluence {
|
||||
public enum LangKey {
|
||||
namespace Greenshot.Plugin.Confluence
|
||||
{
|
||||
public enum LangKey
|
||||
{
|
||||
login_error,
|
||||
upload_menu_item,
|
||||
communication_wait
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
namespace Greenshot.Plugin.Confluence.Support {
|
||||
public interface ITranslationProvider {
|
||||
namespace Greenshot.Plugin.Confluence.Support
|
||||
{
|
||||
public interface ITranslationProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Translates the specified key.
|
||||
/// </summary>
|
||||
|
|
|
@ -43,9 +43,9 @@ namespace Greenshot.Plugin.Confluence.Support
|
|||
manager = new LanguageChangedEventManager();
|
||||
SetCurrentManager(managerType, manager);
|
||||
}
|
||||
|
||||
return manager;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,17 +1,22 @@
|
|||
using GreenshotPlugin.Core;
|
||||
|
||||
namespace Greenshot.Plugin.Confluence.Support {
|
||||
namespace Greenshot.Plugin.Confluence.Support
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class LanguageXMLTranslationProvider : ITranslationProvider {
|
||||
public class LanguageXMLTranslationProvider : ITranslationProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// See <see cref="ITranslationProvider.Translate" />
|
||||
/// </summary>
|
||||
public object Translate(string key) {
|
||||
if (Language.HasKey("confluence", key)) {
|
||||
public object Translate(string key)
|
||||
{
|
||||
if (Language.HasKey("confluence", key))
|
||||
{
|
||||
return Language.GetString("confluence", key);
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,18 @@
|
|||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
|
||||
namespace Greenshot.Plugin.Confluence.Support {
|
||||
public class TranslationData : IWeakEventListener, INotifyPropertyChanged {
|
||||
namespace Greenshot.Plugin.Confluence.Support
|
||||
{
|
||||
public class TranslationData : IWeakEventListener, INotifyPropertyChanged
|
||||
{
|
||||
private readonly string _key;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TranslationData"/> class.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
public TranslationData( string key) {
|
||||
public TranslationData(string key)
|
||||
{
|
||||
_key = key;
|
||||
LanguageChangedEventManager.AddListener(TranslationManager.Instance, this);
|
||||
}
|
||||
|
@ -19,7 +22,8 @@ namespace Greenshot.Plugin.Confluence.Support {
|
|||
/// Releases unmanaged resources and performs other cleanup operations before the
|
||||
/// <see cref="TranslationData"/> is reclaimed by garbage collection.
|
||||
/// </summary>
|
||||
~TranslationData() {
|
||||
~TranslationData()
|
||||
{
|
||||
LanguageChangedEventManager.RemoveListener(TranslationManager.Instance, this);
|
||||
}
|
||||
|
||||
|
@ -32,6 +36,7 @@ namespace Greenshot.Plugin.Confluence.Support {
|
|||
OnLanguageChanged(sender, e);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
using System;
|
||||
|
||||
namespace Greenshot.Plugin.Confluence.Support {
|
||||
public class TranslationManager {
|
||||
namespace Greenshot.Plugin.Confluence.Support
|
||||
{
|
||||
public class TranslationManager
|
||||
{
|
||||
private static TranslationManager _translationManager;
|
||||
|
||||
public event EventHandler LanguageChanged;
|
||||
|
@ -29,11 +31,14 @@ namespace Greenshot.Plugin.Confluence.Support {
|
|||
|
||||
public ITranslationProvider TranslationProvider { get; set; }
|
||||
|
||||
public object Translate(string key) {
|
||||
public object Translate(string key)
|
||||
{
|
||||
object translatedValue = TranslationProvider?.Translate(key);
|
||||
if( translatedValue != null) {
|
||||
if (translatedValue != null)
|
||||
{
|
||||
return translatedValue;
|
||||
}
|
||||
|
||||
return $"!{key}!";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,12 +25,16 @@ using GreenshotPlugin.Core;
|
|||
using GreenshotPlugin.IniFile;
|
||||
using GreenshotPlugin.Interfaces;
|
||||
|
||||
namespace Greenshot.Plugin.Dropbox {
|
||||
internal class DropboxDestination : AbstractDestination {
|
||||
namespace Greenshot.Plugin.Dropbox
|
||||
{
|
||||
internal class DropboxDestination : AbstractDestination
|
||||
{
|
||||
private static readonly DropboxPluginConfiguration DropboxConfig = IniConfig.GetIniSection<DropboxPluginConfiguration>();
|
||||
|
||||
private readonly DropboxPlugin _plugin;
|
||||
public DropboxDestination(DropboxPlugin plugin) {
|
||||
|
||||
public DropboxDestination(DropboxPlugin plugin)
|
||||
{
|
||||
_plugin = plugin;
|
||||
}
|
||||
|
||||
|
@ -38,23 +42,29 @@ namespace Greenshot.Plugin.Dropbox {
|
|||
|
||||
public override string Description => Language.GetString("dropbox", LangKey.upload_menu_item);
|
||||
|
||||
public override Image DisplayIcon {
|
||||
get {
|
||||
public override Image DisplayIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
ComponentResourceManager resources = new ComponentResourceManager(typeof(DropboxPlugin));
|
||||
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);
|
||||
bool uploaded = _plugin.Upload(captureDetails, surface, out var uploadUrl);
|
||||
if (uploaded) {
|
||||
if (uploaded)
|
||||
{
|
||||
exportInformation.Uri = uploadUrl;
|
||||
exportInformation.ExportMade = true;
|
||||
if (DropboxConfig.AfterUploadLinkToClipBoard) {
|
||||
if (DropboxConfig.AfterUploadLinkToClipBoard)
|
||||
{
|
||||
ClipboardHelper.SetClipboardData(uploadUrl);
|
||||
}
|
||||
}
|
||||
|
||||
ProcessExport(exportInformation, surface);
|
||||
return exportInformation;
|
||||
}
|
||||
|
|
|
@ -29,18 +29,21 @@ using GreenshotPlugin.IniFile;
|
|||
using GreenshotPlugin.Interfaces;
|
||||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
|
||||
namespace Greenshot.Plugin.Dropbox {
|
||||
namespace Greenshot.Plugin.Dropbox
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the Dropbox base code
|
||||
/// </summary>
|
||||
[Plugin("Dropbox", true)]
|
||||
public class DropboxPlugin : IGreenshotPlugin {
|
||||
public class DropboxPlugin : IGreenshotPlugin
|
||||
{
|
||||
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(DropboxPlugin));
|
||||
private static DropboxPluginConfiguration _config;
|
||||
private ComponentResourceManager _resources;
|
||||
private ToolStripMenuItem _itemPlugInConfig;
|
||||
|
||||
public void Dispose() {
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
@ -56,8 +59,8 @@ namespace Greenshot.Plugin.Dropbox {
|
|||
/// <summary>
|
||||
/// Implementation of the IGreenshotPlugin.Initialize
|
||||
/// </summary>
|
||||
public bool Initialize() {
|
||||
|
||||
public bool Initialize()
|
||||
{
|
||||
// Register configuration (don't need the configuration itself)
|
||||
_config = IniConfig.GetIniSection<DropboxPluginConfiguration>();
|
||||
_resources = new ComponentResourceManager(typeof(DropboxPlugin));
|
||||
|
@ -74,44 +77,49 @@ namespace Greenshot.Plugin.Dropbox {
|
|||
return true;
|
||||
}
|
||||
|
||||
public void OnLanguageChanged(object sender, EventArgs e) {
|
||||
if (_itemPlugInConfig != null) {
|
||||
public void OnLanguageChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (_itemPlugInConfig != null)
|
||||
{
|
||||
_itemPlugInConfig.Text = Language.GetString("dropbox", LangKey.Configure);
|
||||
}
|
||||
}
|
||||
|
||||
public void Shutdown() {
|
||||
public void Shutdown()
|
||||
{
|
||||
Log.Debug("Dropbox Plugin shutdown.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of the IPlugin.Configure
|
||||
/// </summary>
|
||||
public void Configure() {
|
||||
public void Configure()
|
||||
{
|
||||
_config.ShowConfigDialog();
|
||||
}
|
||||
|
||||
public void ConfigMenuClick(object sender, EventArgs eventArgs) {
|
||||
public void ConfigMenuClick(object sender, EventArgs eventArgs)
|
||||
{
|
||||
_config.ShowConfigDialog();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will be called when the menu item in the Editor is clicked
|
||||
/// </summary>
|
||||
public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, out string uploadUrl) {
|
||||
public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, out string uploadUrl)
|
||||
{
|
||||
uploadUrl = null;
|
||||
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, false);
|
||||
try
|
||||
{
|
||||
bool result = false;
|
||||
new PleaseWaitForm().ShowAndWait("Dropbox", Language.GetString("dropbox", LangKey.communication_wait),
|
||||
delegate
|
||||
{
|
||||
result = DropboxUtils.UploadToDropbox(surfaceToUpload, outputSettings, captureDetails);
|
||||
}
|
||||
delegate { result = DropboxUtils.UploadToDropbox(surfaceToUpload, outputSettings, captureDetails); }
|
||||
);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
MessageBox.Show(Language.GetString("dropbox", LangKey.upload_failure) + " " + e.Message);
|
||||
return false;
|
||||
|
|
|
@ -25,12 +25,14 @@ using Greenshot.Plugin.Dropbox.Forms;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.IniFile;
|
||||
|
||||
namespace Greenshot.Plugin.Dropbox {
|
||||
namespace Greenshot.Plugin.Dropbox
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of ImgurConfiguration.
|
||||
/// </summary>
|
||||
[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")]
|
||||
public OutputFormat UploadFormat { get; set; }
|
||||
|
||||
|
@ -57,11 +59,14 @@ namespace Greenshot.Plugin.Dropbox {
|
|||
/// A form for token
|
||||
/// </summary>
|
||||
/// <returns>bool true if OK was pressed, false if cancel</returns>
|
||||
public bool ShowConfigDialog() {
|
||||
public bool ShowConfigDialog()
|
||||
{
|
||||
DialogResult result = new SettingsForm().ShowDialog();
|
||||
if (result == DialogResult.OK) {
|
||||
if (result == DialogResult.OK)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,15 +29,18 @@ using GreenshotPlugin.Interfaces;
|
|||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Greenshot.Plugin.Dropbox {
|
||||
namespace Greenshot.Plugin.Dropbox
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of DropboxUtils.
|
||||
/// </summary>
|
||||
public class DropboxUtils {
|
||||
public class DropboxUtils
|
||||
{
|
||||
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(DropboxUtils));
|
||||
private static readonly DropboxPluginConfiguration DropboxConfig = IniConfig.GetIniSection<DropboxPluginConfiguration>();
|
||||
|
||||
private DropboxUtils() {
|
||||
private DropboxUtils()
|
||||
{
|
||||
}
|
||||
|
||||
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>
|
||||
{
|
||||
{ "autorename", true },
|
||||
{ "mute", true },
|
||||
{ "path", "/" + filename.Replace(Path.DirectorySeparatorChar, '\\')}
|
||||
{
|
||||
"autorename", true
|
||||
},
|
||||
{
|
||||
"mute", true
|
||||
},
|
||||
{
|
||||
"path", "/" + filename.Replace(Path.DirectorySeparatorChar, '\\')
|
||||
}
|
||||
};
|
||||
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);
|
||||
|
||||
|
@ -78,10 +89,13 @@ namespace Greenshot.Plugin.Dropbox {
|
|||
var response = JsonConvert.DeserializeObject<IDictionary<string, string>>(responseString);
|
||||
return response.ContainsKey("id");
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Upload error: ", ex);
|
||||
throw;
|
||||
} finally {
|
||||
}
|
||||
finally
|
||||
{
|
||||
DropboxConfig.RefreshToken = oauth2Settings.RefreshToken;
|
||||
DropboxConfig.AccessToken = oauth2Settings.AccessToken;
|
||||
DropboxConfig.AccessTokenExpires = oauth2Settings.AccessTokenExpires;
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
|
||||
using GreenshotPlugin.Controls;
|
||||
|
||||
namespace Greenshot.Plugin.Dropbox.Forms {
|
||||
public class DropboxForm : GreenshotForm {
|
||||
namespace Greenshot.Plugin.Dropbox.Forms
|
||||
{
|
||||
public class DropboxForm : GreenshotForm
|
||||
{
|
||||
}
|
||||
}
|
|
@ -19,12 +19,15 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Greenshot.Plugin.Dropbox.Forms {
|
||||
namespace Greenshot.Plugin.Dropbox.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of PasswordRequestForm.
|
||||
/// </summary>
|
||||
public partial class SettingsForm : DropboxForm {
|
||||
public SettingsForm() {
|
||||
public partial class SettingsForm : DropboxForm
|
||||
{
|
||||
public SettingsForm()
|
||||
{
|
||||
//
|
||||
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||
//
|
||||
|
@ -32,6 +35,5 @@ namespace Greenshot.Plugin.Dropbox.Forms {
|
|||
AcceptButton = buttonOK;
|
||||
CancelButton = buttonCancel;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -18,8 +18,11 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* 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_failure,
|
||||
communication_wait,
|
||||
|
|
|
@ -25,31 +25,42 @@ using System.IO;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.IniFile;
|
||||
|
||||
namespace Greenshot.Plugin.ExternalCommand {
|
||||
namespace Greenshot.Plugin.ExternalCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of FlickrConfiguration.
|
||||
/// </summary>
|
||||
[IniSection("ExternalCommand", Description = "Greenshot ExternalCommand Plugin configuration")]
|
||||
public class ExternalCommandConfiguration : IniSection {
|
||||
public class ExternalCommandConfiguration : IniSection
|
||||
{
|
||||
[IniProperty("Commands", Description = "The commands that are available.")]
|
||||
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; }
|
||||
|
||||
[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; }
|
||||
|
||||
[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; }
|
||||
|
||||
[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; }
|
||||
|
||||
[IniProperty("OutputToClipboard", Description = "Depends on 'RedirectStandardOutput': Place the standard output on the clipboard.", DefaultValue = "false")]
|
||||
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; }
|
||||
|
||||
[IniProperty("Commandline", Description = "The commandline for the output command.")]
|
||||
|
@ -71,13 +82,19 @@ namespace Greenshot.Plugin.ExternalCommand {
|
|||
private const string PaintDotNet = "Paint.NET";
|
||||
private static readonly string PaintDotNetPath;
|
||||
private static readonly bool HasPaintDotNet;
|
||||
static ExternalCommandConfiguration() {
|
||||
try {
|
||||
|
||||
static ExternalCommandConfiguration()
|
||||
{
|
||||
try
|
||||
{
|
||||
PaintPath = PluginUtils.GetExePath("pbrush.exe");
|
||||
HasPaint = !string.IsNullOrEmpty(PaintPath) && File.Exists(PaintPath);
|
||||
} catch {
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
PaintDotNetPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Paint.NET\PaintDotNet.exe");
|
||||
|
@ -99,6 +116,7 @@ namespace Greenshot.Plugin.ExternalCommand {
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Commands.Remove(command);
|
||||
Commandline.Remove(command);
|
||||
Argument.Remove(command);
|
||||
|
|
|
@ -31,17 +31,24 @@ using GreenshotPlugin.IniFile;
|
|||
using GreenshotPlugin.Interfaces;
|
||||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
|
||||
namespace Greenshot.Plugin.ExternalCommand {
|
||||
namespace Greenshot.Plugin.ExternalCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of OCRDestination.
|
||||
/// </summary>
|
||||
public class ExternalCommandDestination : AbstractDestination {
|
||||
public class ExternalCommandDestination : AbstractDestination
|
||||
{
|
||||
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 readonly string _presetCommand;
|
||||
|
||||
public ExternalCommandDestination(string commando) {
|
||||
public ExternalCommandDestination(string commando)
|
||||
{
|
||||
_presetCommand = commando;
|
||||
}
|
||||
|
||||
|
@ -49,27 +56,33 @@ namespace Greenshot.Plugin.ExternalCommand {
|
|||
|
||||
public override string Description => _presetCommand;
|
||||
|
||||
public override IEnumerable<IDestination> DynamicDestinations() {
|
||||
public override IEnumerable<IDestination> DynamicDestinations()
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
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);
|
||||
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings();
|
||||
outputSettings.PreventGreenshotFormat();
|
||||
|
||||
if (_presetCommand != null) {
|
||||
if (!config.RunInbackground.ContainsKey(_presetCommand)) {
|
||||
if (_presetCommand != null)
|
||||
{
|
||||
if (!config.RunInbackground.ContainsKey(_presetCommand))
|
||||
{
|
||||
config.RunInbackground.Add(_presetCommand, true);
|
||||
}
|
||||
|
||||
bool runInBackground = config.RunInbackground[_presetCommand];
|
||||
string fullPath = captureDetails.Filename ?? ImageOutput.SaveNamedTmpFile(surface, captureDetails, outputSettings);
|
||||
|
||||
string output;
|
||||
string error;
|
||||
if (runInBackground) {
|
||||
if (runInBackground)
|
||||
{
|
||||
Thread commandThread = new Thread(delegate()
|
||||
{
|
||||
CallExternalCommand(exportInformation, fullPath, out output, out error);
|
||||
|
@ -82,11 +95,14 @@ namespace Greenshot.Plugin.ExternalCommand {
|
|||
commandThread.SetApartmentState(ApartmentState.STA);
|
||||
commandThread.Start();
|
||||
exportInformation.ExportMade = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
CallExternalCommand(exportInformation, fullPath, out output, out error);
|
||||
ProcessExport(exportInformation, surface);
|
||||
}
|
||||
}
|
||||
|
||||
return exportInformation;
|
||||
}
|
||||
|
||||
|
@ -98,32 +114,44 @@ namespace Greenshot.Plugin.ExternalCommand {
|
|||
/// <param name="fullPath"></param>
|
||||
/// <param name="output"></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;
|
||||
error = null;
|
||||
try {
|
||||
if (CallExternalCommand(_presetCommand, fullPath, out output, out error) == 0) {
|
||||
try
|
||||
{
|
||||
if (CallExternalCommand(_presetCommand, fullPath, out output, out error) == 0)
|
||||
{
|
||||
exportInformation.ExportMade = true;
|
||||
if (!string.IsNullOrEmpty(output)) {
|
||||
if (!string.IsNullOrEmpty(output))
|
||||
{
|
||||
MatchCollection uriMatches = URI_REGEXP.Matches(output);
|
||||
// Place output on the clipboard before the URI, so if one is found this overwrites
|
||||
if (config.OutputToClipboard) {
|
||||
if (config.OutputToClipboard)
|
||||
{
|
||||
ClipboardHelper.SetClipboardData(output);
|
||||
}
|
||||
if (uriMatches.Count > 0) {
|
||||
|
||||
if (uriMatches.Count > 0)
|
||||
{
|
||||
exportInformation.Uri = uriMatches[0].Groups[1].Value;
|
||||
LOG.InfoFormat("Got URI : {0} ", exportInformation.Uri);
|
||||
if (config.UriToClipboard) {
|
||||
if (config.UriToClipboard)
|
||||
{
|
||||
ClipboardHelper.SetClipboardData(exportInformation.Uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.WarnFormat("Error calling external command: {0} ", output);
|
||||
exportInformation.ExportMade = false;
|
||||
exportInformation.ErrorMessage = error;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exportInformation.ExportMade = false;
|
||||
exportInformation.ErrorMessage = ex.Message;
|
||||
LOG.WarnFormat("Error calling external command: {0} ", exportInformation.ErrorMessage);
|
||||
|
@ -138,18 +166,27 @@ namespace Greenshot.Plugin.ExternalCommand {
|
|||
/// <param name="output"></param>
|
||||
/// <param name="error"></param>
|
||||
/// <returns></returns>
|
||||
private int CallExternalCommand(string commando, string fullPath, out string output, out string error) {
|
||||
try {
|
||||
private int CallExternalCommand(string commando, string fullPath, out string output, out string error)
|
||||
{
|
||||
try
|
||||
{
|
||||
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);
|
||||
} catch {
|
||||
}
|
||||
catch
|
||||
{
|
||||
w32Ex.Data.Add("commandline", config.Commandline[_presetCommand]);
|
||||
w32Ex.Data.Add("arguments", config.Argument[_presetCommand]);
|
||||
throw;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.Data.Add("commandline", config.Commandline[_presetCommand]);
|
||||
ex.Data.Add("arguments", config.Argument[_presetCommand]);
|
||||
throw;
|
||||
|
@ -165,7 +202,8 @@ namespace Greenshot.Plugin.ExternalCommand {
|
|||
/// <param name="output"></param>
|
||||
/// <param name="error"></param>
|
||||
/// <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 arguments = config.Argument[commando];
|
||||
output = null;
|
||||
|
@ -183,33 +221,46 @@ namespace Greenshot.Plugin.ExternalCommand {
|
|||
process.StartInfo.FileName = FilenameHelper.FillCmdVariables(commandline, true);
|
||||
process.StartInfo.Arguments = FormatArguments(arguments, fullPath);
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
if (config.RedirectStandardOutput) {
|
||||
if (config.RedirectStandardOutput)
|
||||
{
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
}
|
||||
if (config.RedirectStandardError) {
|
||||
|
||||
if (config.RedirectStandardError)
|
||||
{
|
||||
process.StartInfo.RedirectStandardError = true;
|
||||
}
|
||||
if (verb != null) {
|
||||
|
||||
if (verb != null)
|
||||
{
|
||||
process.StartInfo.Verb = verb;
|
||||
}
|
||||
|
||||
LOG.InfoFormat("Starting : {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
||||
process.Start();
|
||||
process.WaitForExit();
|
||||
if (config.RedirectStandardOutput) {
|
||||
if (config.RedirectStandardOutput)
|
||||
{
|
||||
output = process.StandardOutput.ReadToEnd();
|
||||
if (config.ShowStandardOutputInLog && output.Trim().Length > 0) {
|
||||
if (config.ShowStandardOutputInLog && output.Trim().Length > 0)
|
||||
{
|
||||
LOG.InfoFormat("Output:\n{0}", output);
|
||||
}
|
||||
}
|
||||
if (config.RedirectStandardError) {
|
||||
|
||||
if (config.RedirectStandardError)
|
||||
{
|
||||
error = process.StandardError.ReadToEnd();
|
||||
if (error.Trim().Length > 0) {
|
||||
if (error.Trim().Length > 0)
|
||||
{
|
||||
LOG.WarnFormat("Error:\n{0}", error);
|
||||
}
|
||||
}
|
||||
|
||||
LOG.InfoFormat("Finished : {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
||||
return process.ExitCode;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,10 +21,12 @@
|
|||
|
||||
using GreenshotPlugin.Controls;
|
||||
|
||||
namespace Greenshot.Plugin.ExternalCommand {
|
||||
namespace Greenshot.Plugin.ExternalCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is needed for design-time resolving of the language files
|
||||
/// </summary>
|
||||
public class ExternalCommandForm : GreenshotForm {
|
||||
public class ExternalCommandForm : GreenshotForm
|
||||
{
|
||||
}
|
||||
}
|
|
@ -55,6 +55,7 @@ namespace Greenshot.Plugin.ExternalCommand
|
|||
_itemPlugInRoot.Dispose();
|
||||
_itemPlugInRoot = null;
|
||||
}
|
||||
|
||||
private IEnumerable<IDestination> Destinations()
|
||||
{
|
||||
foreach (string command in ExternalCommandConfig.Commands)
|
||||
|
@ -77,17 +78,20 @@ namespace Greenshot.Plugin.ExternalCommand
|
|||
// Fix it
|
||||
ExternalCommandConfig.RunInbackground.Add(command, true);
|
||||
}
|
||||
|
||||
if (!ExternalCommandConfig.Argument.ContainsKey(command))
|
||||
{
|
||||
Log.WarnFormat("Found missing argument for {0}", command);
|
||||
// Fix it
|
||||
ExternalCommandConfig.Argument.Add(command, "{0}");
|
||||
}
|
||||
|
||||
if (!ExternalCommandConfig.Commandline.ContainsKey(command))
|
||||
{
|
||||
Log.WarnFormat("Found missing commandline for {0}", command);
|
||||
return false;
|
||||
}
|
||||
|
||||
string commandline = FilenameHelper.FillVariables(ExternalCommandConfig.Commandline[command], 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);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of the IGreenshotPlugin.Initialize
|
||||
/// </summary>
|
||||
|
@ -114,11 +120,13 @@ namespace Greenshot.Plugin.ExternalCommand
|
|||
commandsToDelete.Add(command);
|
||||
}
|
||||
}
|
||||
|
||||
// cleanup
|
||||
foreach (string command in commandsToDelete)
|
||||
{
|
||||
ExternalCommandConfig.Delete(command);
|
||||
}
|
||||
|
||||
SimpleServiceProvider.Current.AddService(Destinations());
|
||||
|
||||
_itemPlugInRoot = new ToolStripMenuItem();
|
||||
|
|
|
@ -25,22 +25,31 @@ using System.IO;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.IniFile;
|
||||
|
||||
namespace Greenshot.Plugin.ExternalCommand {
|
||||
public static class IconCache {
|
||||
namespace Greenshot.Plugin.ExternalCommand
|
||||
{
|
||||
public static class IconCache
|
||||
{
|
||||
private static readonly ExternalCommandConfiguration config = IniConfig.GetIniSection<ExternalCommandConfiguration>();
|
||||
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;
|
||||
if (commandName != null) {
|
||||
if (config.Commandline.ContainsKey(commandName) && File.Exists(config.Commandline[commandName])) {
|
||||
try {
|
||||
if (commandName != null)
|
||||
{
|
||||
if (config.Commandline.ContainsKey(commandName) && File.Exists(config.Commandline[commandName]))
|
||||
{
|
||||
try
|
||||
{
|
||||
icon = PluginUtils.GetCachedExeIcon(config.Commandline[commandName], 0);
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.Warn("Problem loading icon for " + config.Commandline[commandName], ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,14 +24,17 @@ using System.Drawing;
|
|||
using System.Windows.Forms;
|
||||
using GreenshotPlugin.IniFile;
|
||||
|
||||
namespace Greenshot.Plugin.ExternalCommand {
|
||||
namespace Greenshot.Plugin.ExternalCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of SettingsForm.
|
||||
/// </summary>
|
||||
public partial class SettingsForm : ExternalCommandForm {
|
||||
public partial class SettingsForm : ExternalCommandForm
|
||||
{
|
||||
private static readonly ExternalCommandConfiguration ExternalCommandConfig = IniConfig.GetIniSection<ExternalCommandConfiguration>();
|
||||
|
||||
public SettingsForm() {
|
||||
public SettingsForm()
|
||||
{
|
||||
//
|
||||
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||
//
|
||||
|
@ -41,65 +44,83 @@ namespace Greenshot.Plugin.ExternalCommand {
|
|||
UpdateView();
|
||||
}
|
||||
|
||||
private void ButtonOkClick(object sender, EventArgs e) {
|
||||
private void ButtonOkClick(object sender, EventArgs e)
|
||||
{
|
||||
IniConfig.Save();
|
||||
}
|
||||
|
||||
private void ButtonAddClick(object sender, EventArgs e) {
|
||||
private void ButtonAddClick(object sender, EventArgs e)
|
||||
{
|
||||
var form = new SettingsFormDetail(null);
|
||||
form.ShowDialog();
|
||||
|
||||
UpdateView();
|
||||
}
|
||||
|
||||
private void ButtonDeleteClick(object sender, EventArgs e) {
|
||||
foreach(ListViewItem item in listView1.SelectedItems) {
|
||||
private void ButtonDeleteClick(object sender, EventArgs e)
|
||||
{
|
||||
foreach (ListViewItem item in listView1.SelectedItems)
|
||||
{
|
||||
string commando = item.Tag as string;
|
||||
|
||||
ExternalCommandConfig.Delete(commando);
|
||||
}
|
||||
|
||||
UpdateView();
|
||||
}
|
||||
|
||||
private void UpdateView() {
|
||||
private void UpdateView()
|
||||
{
|
||||
listView1.Items.Clear();
|
||||
if(ExternalCommandConfig.Commands != null) {
|
||||
if (ExternalCommandConfig.Commands != null)
|
||||
{
|
||||
listView1.ListViewItemSorter = new ListviewComparer();
|
||||
ImageList imageList = new ImageList();
|
||||
listView1.SmallImageList = imageList;
|
||||
int imageNr = 0;
|
||||
foreach(string commando in ExternalCommandConfig.Commands) {
|
||||
foreach (string commando in ExternalCommandConfig.Commands)
|
||||
{
|
||||
ListViewItem item;
|
||||
Image iconForExe = IconCache.IconForCommand(commando);
|
||||
if(iconForExe != null) {
|
||||
if (iconForExe != null)
|
||||
{
|
||||
imageList.Images.Add(iconForExe);
|
||||
item = new ListViewItem(commando, imageNr++);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
item = new ListViewItem(commando);
|
||||
}
|
||||
|
||||
item.Tag = commando;
|
||||
listView1.Items.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
private void ListView1ItemSelectionChanged(object sender, EventArgs e) {
|
||||
private void ListView1ItemSelectionChanged(object sender, EventArgs e)
|
||||
{
|
||||
button_edit.Enabled = listView1.SelectedItems.Count > 0;
|
||||
}
|
||||
|
||||
private void ButtonEditClick(object sender, EventArgs e) {
|
||||
private void ButtonEditClick(object sender, EventArgs e)
|
||||
{
|
||||
ListView1DoubleClick(sender, e);
|
||||
}
|
||||
|
||||
private void ListView1DoubleClick(object sender, EventArgs e) {
|
||||
private void ListView1DoubleClick(object sender, EventArgs e)
|
||||
{
|
||||
// Safety check for bug #1484
|
||||
bool selectionActive = listView1.SelectedItems.Count > 0;
|
||||
if(!selectionActive) {
|
||||
if (!selectionActive)
|
||||
{
|
||||
button_edit.Enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
string commando = listView1.SelectedItems[0].Tag as string;
|
||||
|
||||
var form = new SettingsFormDetail(commando);
|
||||
|
@ -109,12 +130,17 @@ namespace Greenshot.Plugin.ExternalCommand {
|
|||
}
|
||||
}
|
||||
|
||||
public class ListviewComparer : System.Collections.IComparer {
|
||||
public int Compare(object x, object y) {
|
||||
if(!(x is ListViewItem)) {
|
||||
public class ListviewComparer : System.Collections.IComparer
|
||||
{
|
||||
public int Compare(object x, object y)
|
||||
{
|
||||
if (!(x is ListViewItem))
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
if(!(y is ListViewItem)) {
|
||||
|
||||
if (!(y is ListViewItem))
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,52 +26,64 @@ using System.Windows.Forms;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.IniFile;
|
||||
|
||||
namespace Greenshot.Plugin.ExternalCommand {
|
||||
namespace Greenshot.Plugin.ExternalCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of SettingsFormDetail.
|
||||
/// </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 ExternalCommandConfiguration ExternalCommandConfig = IniConfig.GetIniSection<ExternalCommandConfiguration>();
|
||||
|
||||
private readonly string _commando;
|
||||
private readonly int _commandIndex;
|
||||
|
||||
public SettingsFormDetail(string commando) {
|
||||
public SettingsFormDetail(string commando)
|
||||
{
|
||||
InitializeComponent();
|
||||
AcceptButton = buttonOk;
|
||||
CancelButton = buttonCancel;
|
||||
_commando = commando;
|
||||
|
||||
if(commando != null) {
|
||||
if (commando != null)
|
||||
{
|
||||
textBox_name.Text = commando;
|
||||
textBox_commandline.Text = ExternalCommandConfig.Commandline[commando];
|
||||
textBox_arguments.Text = ExternalCommandConfig.Argument[commando];
|
||||
_commandIndex = ExternalCommandConfig.Commands.FindIndex(s => s == commando);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
textBox_arguments.Text = "\"{0}\"";
|
||||
}
|
||||
|
||||
OkButtonState();
|
||||
}
|
||||
|
||||
private void ButtonOkClick(object sender, EventArgs e) {
|
||||
private void ButtonOkClick(object sender, EventArgs e)
|
||||
{
|
||||
string commandName = textBox_name.Text;
|
||||
string commandLine = textBox_commandline.Text;
|
||||
string arguments = textBox_arguments.Text;
|
||||
if(_commando != null) {
|
||||
if (_commando != null)
|
||||
{
|
||||
ExternalCommandConfig.Commands[_commandIndex] = commandName;
|
||||
ExternalCommandConfig.Commandline.Remove(_commando);
|
||||
ExternalCommandConfig.Commandline.Add(commandName, commandLine);
|
||||
ExternalCommandConfig.Argument.Remove(_commando);
|
||||
ExternalCommandConfig.Argument.Add(commandName, arguments);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ExternalCommandConfig.Commands.Add(commandName);
|
||||
ExternalCommandConfig.Commandline.Add(commandName, commandLine);
|
||||
ExternalCommandConfig.Argument.Add(commandName, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
private void Button3Click(object sender, EventArgs e) {
|
||||
private void Button3Click(object sender, EventArgs e)
|
||||
{
|
||||
var openFileDialog = new OpenFileDialog
|
||||
{
|
||||
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.Warn("Exception: ", ex);
|
||||
}
|
||||
if(initialPath != null && Directory.Exists(initialPath)) {
|
||||
|
||||
if (initialPath != null && Directory.Exists(initialPath))
|
||||
{
|
||||
openFileDialog.InitialDirectory = initialPath;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
initialPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
|
||||
openFileDialog.InitialDirectory = initialPath;
|
||||
}
|
||||
|
||||
Log.DebugFormat("Starting OpenFileDialog at {0}", initialPath);
|
||||
if(openFileDialog.ShowDialog() == DialogResult.OK) {
|
||||
if (openFileDialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
textBox_commandline.Text = openFileDialog.FileName;
|
||||
}
|
||||
}
|
||||
|
||||
private void OkButtonState() {
|
||||
private void OkButtonState()
|
||||
{
|
||||
// Assume OK
|
||||
buttonOk.Enabled = true;
|
||||
textBox_name.BackColor = Color.White;
|
||||
textBox_commandline.BackColor = Color.White;
|
||||
textBox_arguments.BackColor = Color.White;
|
||||
// Is there a text in the name field
|
||||
if(string.IsNullOrEmpty(textBox_name.Text)) {
|
||||
if (string.IsNullOrEmpty(textBox_name.Text))
|
||||
{
|
||||
buttonOk.Enabled = false;
|
||||
}
|
||||
|
||||
// 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;
|
||||
textBox_name.BackColor = Color.Red;
|
||||
}
|
||||
|
||||
// Is there a text in the commandline field
|
||||
if(string.IsNullOrEmpty(textBox_commandline.Text)) {
|
||||
if (string.IsNullOrEmpty(textBox_commandline.Text))
|
||||
{
|
||||
buttonOk.Enabled = false;
|
||||
}
|
||||
|
||||
|
@ -134,6 +158,7 @@ namespace Greenshot.Plugin.ExternalCommand {
|
|||
textBox_commandline.BackColor = Color.Red;
|
||||
}
|
||||
}
|
||||
|
||||
// Are the arguments in a valid format?
|
||||
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();
|
||||
}
|
||||
|
||||
private void textBox_commandline_TextChanged(object sender, EventArgs e) {
|
||||
private void textBox_commandline_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
OkButtonState();
|
||||
}
|
||||
|
||||
|
@ -161,6 +188,5 @@ namespace Greenshot.Plugin.ExternalCommand {
|
|||
{
|
||||
OkButtonState();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -24,17 +24,21 @@ using Greenshot.Plugin.Flickr.Forms;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.IniFile;
|
||||
|
||||
namespace Greenshot.Plugin.Flickr {
|
||||
public enum SafetyLevel {
|
||||
namespace Greenshot.Plugin.Flickr
|
||||
{
|
||||
public enum SafetyLevel
|
||||
{
|
||||
Safe = 1,
|
||||
Moderate = 2,
|
||||
Restricted = 3
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Description of FlickrConfiguration.
|
||||
/// </summary>
|
||||
[IniSection("Flickr", Description = "Greenshot Flickr Plugin configuration")]
|
||||
public class FlickrConfiguration : IniSection {
|
||||
public class FlickrConfiguration : IniSection
|
||||
{
|
||||
[IniProperty("flickrIsPublic", Description = "IsPublic.", DefaultValue = "true")]
|
||||
public bool IsPublic { get; set; }
|
||||
|
||||
|
@ -64,6 +68,7 @@ namespace Greenshot.Plugin.Flickr {
|
|||
|
||||
[IniProperty("FlickrToken", Description = "The Flickr token", Encrypted = true, ExcludeIfNull = true)]
|
||||
public string FlickrToken { get; set; }
|
||||
|
||||
[IniProperty("FlickrTokenSecret", Description = "The Flickr token secret", Encrypted = true, ExcludeIfNull = true)]
|
||||
public string FlickrTokenSecret { get; set; }
|
||||
|
||||
|
@ -71,11 +76,14 @@ namespace Greenshot.Plugin.Flickr {
|
|||
/// A form for token
|
||||
/// </summary>
|
||||
/// <returns>bool true if OK was pressed, false if cancel</returns>
|
||||
public bool ShowConfigDialog() {
|
||||
public bool ShowConfigDialog()
|
||||
{
|
||||
DialogResult result = new SettingsForm().ShowDialog();
|
||||
if (result == DialogResult.OK) {
|
||||
if (result == DialogResult.OK)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,10 +24,14 @@ using System.Drawing;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.Interfaces;
|
||||
|
||||
namespace Greenshot.Plugin.Flickr {
|
||||
public class FlickrDestination : AbstractDestination {
|
||||
namespace Greenshot.Plugin.Flickr
|
||||
{
|
||||
public class FlickrDestination : AbstractDestination
|
||||
{
|
||||
private readonly FlickrPlugin _plugin;
|
||||
public FlickrDestination(FlickrPlugin plugin) {
|
||||
|
||||
public FlickrDestination(FlickrPlugin plugin)
|
||||
{
|
||||
_plugin = plugin;
|
||||
}
|
||||
|
||||
|
@ -35,20 +39,25 @@ namespace Greenshot.Plugin.Flickr {
|
|||
|
||||
public override string Description => Language.GetString("flickr", LangKey.upload_menu_item);
|
||||
|
||||
public override Image DisplayIcon {
|
||||
get {
|
||||
public override Image DisplayIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
ComponentResourceManager resources = new ComponentResourceManager(typeof(FlickrPlugin));
|
||||
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);
|
||||
bool uploaded = _plugin.Upload(captureDetails, surface, out var uploadUrl);
|
||||
if (uploaded) {
|
||||
if (uploaded)
|
||||
{
|
||||
exportInformation.ExportMade = true;
|
||||
exportInformation.Uri = uploadUrl;
|
||||
}
|
||||
|
||||
ProcessExport(exportInformation, surface);
|
||||
return exportInformation;
|
||||
}
|
||||
|
|
|
@ -37,24 +37,31 @@ namespace Greenshot.Plugin.Flickr
|
|||
/// This is the Flickr base code
|
||||
/// </summary>
|
||||
[Plugin("Flickr", true)]
|
||||
public class FlickrPlugin : IGreenshotPlugin {
|
||||
public class FlickrPlugin : IGreenshotPlugin
|
||||
{
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(FlickrPlugin));
|
||||
private static FlickrConfiguration _config;
|
||||
private ComponentResourceManager _resources;
|
||||
private ToolStripMenuItem _itemPlugInConfig;
|
||||
|
||||
public void Dispose() {
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected void Dispose(bool disposing) {
|
||||
if (!disposing) {
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (_itemPlugInConfig == null) {
|
||||
|
||||
if (_itemPlugInConfig == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_itemPlugInConfig.Dispose();
|
||||
_itemPlugInConfig = null;
|
||||
}
|
||||
|
@ -62,7 +69,8 @@ namespace Greenshot.Plugin.Flickr
|
|||
/// <summary>
|
||||
/// Implementation of the IGreenshotPlugin.Initialize
|
||||
/// </summary>
|
||||
public bool Initialize() {
|
||||
public bool Initialize()
|
||||
{
|
||||
// Register configuration (don't need the configuration itself)
|
||||
_config = IniConfig.GetIniSection<FlickrConfiguration>();
|
||||
_resources = new ComponentResourceManager(typeof(FlickrPlugin));
|
||||
|
@ -79,52 +87,67 @@ namespace Greenshot.Plugin.Flickr
|
|||
return true;
|
||||
}
|
||||
|
||||
public void OnLanguageChanged(object sender, EventArgs e) {
|
||||
if (_itemPlugInConfig != null) {
|
||||
public void OnLanguageChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (_itemPlugInConfig != null)
|
||||
{
|
||||
_itemPlugInConfig.Text = Language.GetString("flickr", LangKey.Configure);
|
||||
}
|
||||
}
|
||||
|
||||
public void Shutdown() {
|
||||
public void Shutdown()
|
||||
{
|
||||
Log.Debug("Flickr Plugin shutdown.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of the IPlugin.Configure
|
||||
/// </summary>
|
||||
public void Configure() {
|
||||
public void Configure()
|
||||
{
|
||||
_config.ShowConfigDialog();
|
||||
}
|
||||
|
||||
public void ConfigMenuClick(object sender, EventArgs eventArgs) {
|
||||
public void ConfigMenuClick(object sender, EventArgs eventArgs)
|
||||
{
|
||||
_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);
|
||||
uploadUrl = null;
|
||||
try {
|
||||
try
|
||||
{
|
||||
string flickrUrl = null;
|
||||
new PleaseWaitForm().ShowAndWait("Flickr", Language.GetString("flickr", LangKey.communication_wait),
|
||||
delegate {
|
||||
delegate
|
||||
{
|
||||
string filename = Path.GetFileName(FilenameHelper.GetFilename(_config.UploadFormat, captureDetails));
|
||||
flickrUrl = FlickrUtils.UploadToFlickr(surface, outputSettings, captureDetails.Title, filename);
|
||||
}
|
||||
);
|
||||
|
||||
if (flickrUrl == null) {
|
||||
if (flickrUrl == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uploadUrl = flickrUrl;
|
||||
|
||||
if (_config.AfterUploadLinkToClipBoard) {
|
||||
if (_config.AfterUploadLinkToClipBoard)
|
||||
{
|
||||
ClipboardHelper.SetClipboardData(flickrUrl);
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error("Error uploading.", e);
|
||||
MessageBox.Show(Language.GetString("flickr", LangKey.upload_failure) + " " + e.Message);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,21 +30,27 @@ using GreenshotPlugin.Interfaces;
|
|||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
using log4net;
|
||||
|
||||
namespace Greenshot.Plugin.Flickr {
|
||||
namespace Greenshot.Plugin.Flickr
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of FlickrUtils.
|
||||
/// </summary>
|
||||
public static class FlickrUtils {
|
||||
public static class FlickrUtils
|
||||
{
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(FlickrUtils));
|
||||
private static readonly FlickrConfiguration config = IniConfig.GetIniSection<FlickrConfiguration>();
|
||||
private const string FLICKR_API_BASE_URL = "https://api.flickr.com/services/";
|
||||
|
||||
private const string FLICKR_UPLOAD_URL = FLICKR_API_BASE_URL + "upload/";
|
||||
|
||||
// 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_AUTHORIZE_URL = FLICKR_OAUTH_BASE_URL + "authorize";
|
||||
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}";
|
||||
|
||||
// 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";
|
||||
|
@ -58,7 +64,8 @@ namespace Greenshot.Plugin.Flickr {
|
|||
/// <param name="title"></param>
|
||||
/// <param name="filename"></param>
|
||||
/// <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)
|
||||
{
|
||||
BrowserSize = new Size(520, 800),
|
||||
|
@ -70,70 +77,116 @@ namespace Greenshot.Plugin.Flickr {
|
|||
Token = config.FlickrToken,
|
||||
TokenSecret = config.FlickrTokenSecret
|
||||
};
|
||||
if (string.IsNullOrEmpty(oAuth.Token)) {
|
||||
if (!oAuth.Authorize()) {
|
||||
if (string.IsNullOrEmpty(oAuth.Token))
|
||||
{
|
||||
if (!oAuth.Authorize())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(oAuth.Token)) {
|
||||
|
||||
if (!string.IsNullOrEmpty(oAuth.Token))
|
||||
{
|
||||
config.FlickrToken = oAuth.Token;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(oAuth.TokenSecret)) {
|
||||
|
||||
if (!string.IsNullOrEmpty(oAuth.TokenSecret))
|
||||
{
|
||||
config.FlickrTokenSecret = oAuth.TokenSecret;
|
||||
}
|
||||
|
||||
IniConfig.Save();
|
||||
}
|
||||
try {
|
||||
|
||||
try
|
||||
{
|
||||
IDictionary<string, object> signedParameters = new Dictionary<string, object>
|
||||
{
|
||||
{ "content_type", "2" }, // Screenshot
|
||||
{ "tags", "Greenshot" },
|
||||
{ "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" }
|
||||
{
|
||||
"content_type", "2"
|
||||
}, // Screenshot
|
||||
{
|
||||
"tags", "Greenshot"
|
||||
},
|
||||
{
|
||||
"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>
|
||||
{
|
||||
{ "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 photoId = GetPhotoId(response);
|
||||
|
||||
// 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);
|
||||
return GetUrl(photoInfo);
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.Error("Upload error: ", ex);
|
||||
throw;
|
||||
} finally {
|
||||
if (!string.IsNullOrEmpty(oAuth.Token)) {
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!string.IsNullOrEmpty(oAuth.Token))
|
||||
{
|
||||
config.FlickrToken = oAuth.Token;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(oAuth.TokenSecret)) {
|
||||
|
||||
if (!string.IsNullOrEmpty(oAuth.TokenSecret))
|
||||
{
|
||||
config.FlickrTokenSecret = oAuth.TokenSecret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetUrl(string response) {
|
||||
try {
|
||||
private static string GetUrl(string response)
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(response);
|
||||
if (config.UsePageLink) {
|
||||
if (config.UsePageLink)
|
||||
{
|
||||
XmlNodeList nodes = doc.GetElementsByTagName("url");
|
||||
if (nodes.Count > 0) {
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
var xmlNode = nodes.Item(0);
|
||||
if (xmlNode != null) {
|
||||
if (xmlNode != null)
|
||||
{
|
||||
return xmlNode.InnerText;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
XmlNodeList nodes = doc.GetElementsByTagName("photo");
|
||||
if (nodes.Count > 0) {
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
var item = nodes.Item(0);
|
||||
if (item?.Attributes != null) {
|
||||
if (item?.Attributes != null)
|
||||
{
|
||||
string farmId = item.Attributes["farm"].Value;
|
||||
string serverId = item.Attributes["server"].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);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetPhotoId(string response) {
|
||||
try {
|
||||
private static string GetPhotoId(string response)
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(response);
|
||||
XmlNodeList nodes = doc.GetElementsByTagName("photoid");
|
||||
if (nodes.Count > 0) {
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
var xmlNode = nodes.Item(0);
|
||||
if (xmlNode != null) {
|
||||
if (xmlNode != null)
|
||||
{
|
||||
return xmlNode.InnerText;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.Error("Error parsing Flickr Response.", ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
|
||||
using GreenshotPlugin.Controls;
|
||||
|
||||
namespace Greenshot.Plugin.Flickr.Forms {
|
||||
public class FlickrForm : GreenshotForm {
|
||||
namespace Greenshot.Plugin.Flickr.Forms
|
||||
{
|
||||
public class FlickrForm : GreenshotForm
|
||||
{
|
||||
}
|
||||
}
|
|
@ -19,12 +19,15 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Greenshot.Plugin.Flickr.Forms {
|
||||
namespace Greenshot.Plugin.Flickr.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of PasswordRequestForm.
|
||||
/// </summary>
|
||||
public partial class SettingsForm : FlickrForm {
|
||||
public SettingsForm() {
|
||||
public partial class SettingsForm : FlickrForm
|
||||
{
|
||||
public SettingsForm()
|
||||
{
|
||||
//
|
||||
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||
//
|
||||
|
@ -32,6 +35,5 @@ namespace Greenshot.Plugin.Flickr.Forms {
|
|||
CancelButton = buttonCancel;
|
||||
AcceptButton = buttonOK;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -18,8 +18,11 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* 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_failure,
|
||||
communication_wait,
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
using GreenshotPlugin.Controls;
|
||||
|
||||
namespace Greenshot.Plugin.GooglePhotos.Forms {
|
||||
public class GooglePhotosForm : GreenshotForm {
|
||||
namespace Greenshot.Plugin.GooglePhotos.Forms
|
||||
{
|
||||
public class GooglePhotosForm : GreenshotForm
|
||||
{
|
||||
}
|
||||
}
|
|
@ -18,12 +18,13 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Greenshot.Plugin.GooglePhotos.Forms {
|
||||
namespace Greenshot.Plugin.GooglePhotos.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of PasswordRequestForm.
|
||||
/// </summary>
|
||||
public partial class SettingsForm : GooglePhotosForm {
|
||||
|
||||
public partial class SettingsForm : GooglePhotosForm
|
||||
{
|
||||
public SettingsForm()
|
||||
{
|
||||
//
|
||||
|
@ -33,6 +34,5 @@ namespace Greenshot.Plugin.GooglePhotos.Forms {
|
|||
CancelButton = buttonCancel;
|
||||
AcceptButton = buttonOK;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -24,12 +24,14 @@ using Greenshot.Plugin.GooglePhotos.Forms;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.IniFile;
|
||||
|
||||
namespace Greenshot.Plugin.GooglePhotos {
|
||||
namespace Greenshot.Plugin.GooglePhotos
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of GooglePhotosConfiguration.
|
||||
/// </summary>
|
||||
[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")]
|
||||
public OutputFormat UploadFormat { get; set; }
|
||||
|
||||
|
@ -38,57 +40,42 @@ namespace Greenshot.Plugin.GooglePhotos {
|
|||
|
||||
[IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send GooglePhotos link to clipboard.", DefaultValue = "true")]
|
||||
public bool AfterUploadLinkToClipBoard { get; set; }
|
||||
|
||||
[IniProperty("AddFilename", Description = "Is the filename passed on to GooglePhotos", DefaultValue = "False")]
|
||||
public bool AddFilename {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public bool AddFilename { get; set; }
|
||||
|
||||
[IniProperty("UploadUser", Description = "The GooglePhotos user to upload to", DefaultValue = "default")]
|
||||
public string UploadUser {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string UploadUser { get; set; }
|
||||
|
||||
[IniProperty("UploadAlbum", Description = "The GooglePhotos album to upload to", DefaultValue = "default")]
|
||||
public string UploadAlbum {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string UploadAlbum { get; set; }
|
||||
|
||||
[IniProperty("RefreshToken", Description = "GooglePhotos authorization refresh Token", Encrypted = true)]
|
||||
public string RefreshToken {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string RefreshToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Not stored
|
||||
/// </summary>
|
||||
public string AccessToken {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string AccessToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Not stored
|
||||
/// </summary>
|
||||
public DateTimeOffset AccessTokenExpires {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public DateTimeOffset AccessTokenExpires { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A form for token
|
||||
/// </summary>
|
||||
/// <returns>bool true if OK was pressed, false if cancel</returns>
|
||||
public bool ShowConfigDialog() {
|
||||
public bool ShowConfigDialog()
|
||||
{
|
||||
DialogResult result = new SettingsForm().ShowDialog();
|
||||
if (result == DialogResult.OK) {
|
||||
if (result == DialogResult.OK)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -23,10 +23,14 @@ using System.Drawing;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.Interfaces;
|
||||
|
||||
namespace Greenshot.Plugin.GooglePhotos {
|
||||
public class GooglePhotosDestination : AbstractDestination {
|
||||
namespace Greenshot.Plugin.GooglePhotos
|
||||
{
|
||||
public class GooglePhotosDestination : AbstractDestination
|
||||
{
|
||||
private readonly GooglePhotosPlugin _plugin;
|
||||
public GooglePhotosDestination(GooglePhotosPlugin plugin) {
|
||||
|
||||
public GooglePhotosDestination(GooglePhotosPlugin plugin)
|
||||
{
|
||||
_plugin = plugin;
|
||||
}
|
||||
|
||||
|
@ -34,20 +38,25 @@ namespace Greenshot.Plugin.GooglePhotos {
|
|||
|
||||
public override string Description => Language.GetString("googlephotos", LangKey.upload_menu_item);
|
||||
|
||||
public override Image DisplayIcon {
|
||||
get {
|
||||
public override Image DisplayIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
ComponentResourceManager resources = new ComponentResourceManager(typeof(GooglePhotosPlugin));
|
||||
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);
|
||||
bool uploaded = _plugin.Upload(captureDetails, surface, out var uploadUrl);
|
||||
if (uploaded) {
|
||||
if (uploaded)
|
||||
{
|
||||
exportInformation.ExportMade = true;
|
||||
exportInformation.Uri = uploadUrl;
|
||||
}
|
||||
|
||||
ProcessExport(exportInformation, surface);
|
||||
return exportInformation;
|
||||
}
|
||||
|
|
|
@ -29,18 +29,21 @@ using GreenshotPlugin.IniFile;
|
|||
using GreenshotPlugin.Interfaces;
|
||||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
|
||||
namespace Greenshot.Plugin.GooglePhotos {
|
||||
namespace Greenshot.Plugin.GooglePhotos
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the GooglePhotos base code
|
||||
/// </summary>
|
||||
[Plugin("GooglePhotos", true)]
|
||||
public class GooglePhotosPlugin : IGreenshotPlugin {
|
||||
public class GooglePhotosPlugin : IGreenshotPlugin
|
||||
{
|
||||
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(GooglePhotosPlugin));
|
||||
private static GooglePhotosConfiguration _config;
|
||||
private ComponentResourceManager _resources;
|
||||
private ToolStripMenuItem _itemPlugInRoot;
|
||||
|
||||
public void Dispose() {
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
@ -56,7 +59,8 @@ namespace Greenshot.Plugin.GooglePhotos {
|
|||
/// <summary>
|
||||
/// Implementation of the IGreenshotPlugin.Initialize
|
||||
/// </summary>
|
||||
public bool Initialize() {
|
||||
public bool Initialize()
|
||||
{
|
||||
SimpleServiceProvider.Current.AddService<IDestination>(new GooglePhotosDestination(this));
|
||||
|
||||
// Get configuration
|
||||
|
@ -74,13 +78,16 @@ namespace Greenshot.Plugin.GooglePhotos {
|
|||
return true;
|
||||
}
|
||||
|
||||
public void OnLanguageChanged(object sender, EventArgs e) {
|
||||
if (_itemPlugInRoot != null) {
|
||||
public void OnLanguageChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (_itemPlugInRoot != null)
|
||||
{
|
||||
_itemPlugInRoot.Text = Language.GetString("googlephotos", LangKey.Configure);
|
||||
}
|
||||
}
|
||||
|
||||
public void Shutdown() {
|
||||
public void Shutdown()
|
||||
{
|
||||
Log.Debug("GooglePhotos Plugin shutdown.");
|
||||
Language.LanguageChanged -= OnLanguageChanged;
|
||||
//host.OnImageEditorOpen -= new OnImageEditorOpenHandler(ImageEditorOpened);
|
||||
|
@ -89,17 +96,21 @@ namespace Greenshot.Plugin.GooglePhotos {
|
|||
/// <summary>
|
||||
/// Implementation of the IPlugin.Configure
|
||||
/// </summary>
|
||||
public void Configure() {
|
||||
public void Configure()
|
||||
{
|
||||
_config.ShowConfigDialog();
|
||||
}
|
||||
|
||||
public void ConfigMenuClick(object sender, EventArgs eventArgs) {
|
||||
public void ConfigMenuClick(object sender, EventArgs eventArgs)
|
||||
{
|
||||
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);
|
||||
try {
|
||||
try
|
||||
{
|
||||
string url = null;
|
||||
new PleaseWaitForm().ShowAndWait("GooglePhotos", Language.GetString("googlephotos", LangKey.communication_wait),
|
||||
delegate
|
||||
|
@ -110,14 +121,19 @@ namespace Greenshot.Plugin.GooglePhotos {
|
|||
);
|
||||
uploadUrl = url;
|
||||
|
||||
if (uploadUrl != null && _config.AfterUploadLinkToClipBoard) {
|
||||
if (uploadUrl != null && _config.AfterUploadLinkToClipBoard)
|
||||
{
|
||||
ClipboardHelper.SetClipboardData(uploadUrl);
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error("Error uploading.", e);
|
||||
MessageBox.Show(Language.GetString("googlephotos", LangKey.upload_failure) + " " + e.Message);
|
||||
}
|
||||
|
||||
uploadUrl = null;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -26,15 +26,20 @@ using GreenshotPlugin.IniFile;
|
|||
using GreenshotPlugin.Interfaces;
|
||||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
|
||||
namespace Greenshot.Plugin.GooglePhotos {
|
||||
namespace Greenshot.Plugin.GooglePhotos
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of GooglePhotosUtils.
|
||||
/// </summary>
|
||||
public static class GooglePhotosUtils {
|
||||
public static class GooglePhotosUtils
|
||||
{
|
||||
private const string GooglePhotosScope = "https://picasaweb.google.com/data/";
|
||||
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(GooglePhotosUtils));
|
||||
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 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="filename">string</param>
|
||||
/// <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
|
||||
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
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
SurfaceContainer container = new SurfaceContainer(surfaceToUpload, outputSettings, filename);
|
||||
container.Upload(webRequest);
|
||||
|
||||
string response = NetworkHelper.GetResponseAsString(webRequest);
|
||||
|
||||
return ParseResponse(response);
|
||||
} finally {
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Copy the settings back to the config, so they are stored.
|
||||
Config.RefreshToken = settings.RefreshToken;
|
||||
Config.AccessToken = settings.AccessToken;
|
||||
|
@ -89,31 +100,43 @@ namespace Greenshot.Plugin.GooglePhotos {
|
|||
/// </summary>
|
||||
/// <param name="response"></param>
|
||||
/// <returns></returns>
|
||||
public static string ParseResponse(string response) {
|
||||
if (response == null) {
|
||||
public static string ParseResponse(string response)
|
||||
{
|
||||
if (response == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
|
||||
try
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(response);
|
||||
XmlNodeList nodes = doc.GetElementsByTagName("link", "*");
|
||||
if(nodes.Count > 0) {
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
string url = null;
|
||||
foreach(XmlNode node in nodes) {
|
||||
if (node.Attributes != null) {
|
||||
foreach (XmlNode node in nodes)
|
||||
{
|
||||
if (node.Attributes != null)
|
||||
{
|
||||
url = node.Attributes["href"].Value;
|
||||
string rel = node.Attributes["rel"].Value;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Greenshot.Plugin.GooglePhotos {
|
||||
namespace Greenshot.Plugin.GooglePhotos
|
||||
{
|
||||
public enum LangKey
|
||||
{
|
||||
upload_menu_item,
|
||||
|
|
|
@ -21,10 +21,12 @@
|
|||
|
||||
using GreenshotPlugin.Controls;
|
||||
|
||||
namespace Greenshot.Plugin.Imgur.Forms {
|
||||
namespace Greenshot.Plugin.Imgur.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is needed for design-time resolving of the language files
|
||||
/// </summary>
|
||||
public class ImgurForm : GreenshotForm {
|
||||
public class ImgurForm : GreenshotForm
|
||||
{
|
||||
}
|
||||
}
|
|
@ -27,18 +27,21 @@ using GreenshotPlugin.Controls;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.IniFile;
|
||||
|
||||
namespace Greenshot.Plugin.Imgur.Forms {
|
||||
namespace Greenshot.Plugin.Imgur.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// Imgur history form
|
||||
/// </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 readonly GreenshotColumnSorter _columnSorter;
|
||||
private static readonly object Lock = new object();
|
||||
private static readonly ImgurConfiguration Config = IniConfig.GetIniSection<ImgurConfiguration>();
|
||||
private static ImgurHistory _instance;
|
||||
|
||||
public static void ShowHistory() {
|
||||
public static void ShowHistory()
|
||||
{
|
||||
lock (Lock)
|
||||
{
|
||||
if (ImgurUtils.IsHistoryLoadingNeeded())
|
||||
|
@ -54,15 +57,18 @@ namespace Greenshot.Plugin.Imgur.Forms {
|
|||
{
|
||||
_instance = new ImgurHistory();
|
||||
}
|
||||
|
||||
if (!_instance.Visible)
|
||||
{
|
||||
_instance.Show();
|
||||
}
|
||||
|
||||
_instance.Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
private ImgurHistory() {
|
||||
private ImgurHistory()
|
||||
{
|
||||
ManualLanguageApply = true;
|
||||
//
|
||||
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||
|
@ -76,26 +82,36 @@ namespace Greenshot.Plugin.Imgur.Forms {
|
|||
_columnSorter.SortColumn = 3;
|
||||
_columnSorter.Order = SortOrder.Descending;
|
||||
Redraw();
|
||||
if (listview_imgur_uploads.Items.Count > 0) {
|
||||
if (listview_imgur_uploads.Items.Count > 0)
|
||||
{
|
||||
listview_imgur_uploads.Items[0].Selected = true;
|
||||
}
|
||||
|
||||
ApplyLanguage();
|
||||
if (Config.Credits > 0) {
|
||||
if (Config.Credits > 0)
|
||||
{
|
||||
Text = Text + " (" + Config.Credits + " credits)";
|
||||
}
|
||||
}
|
||||
|
||||
private void Redraw() {
|
||||
private void Redraw()
|
||||
{
|
||||
// Should fix Bug #3378699
|
||||
pictureBox1.Image = pictureBox1.ErrorImage;
|
||||
listview_imgur_uploads.BeginUpdate();
|
||||
listview_imgur_uploads.Items.Clear();
|
||||
listview_imgur_uploads.Columns.Clear();
|
||||
string[] columns = { "hash", "title", "deleteHash", "Date"};
|
||||
foreach (string column in columns) {
|
||||
string[] columns =
|
||||
{
|
||||
"hash", "title", "deleteHash", "Date"
|
||||
};
|
||||
foreach (string column in columns)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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));
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -116,17 +134,22 @@ namespace Greenshot.Plugin.Imgur.Forms {
|
|||
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;
|
||||
if (listview_imgur_uploads.SelectedItems.Count > 0) {
|
||||
if (listview_imgur_uploads.SelectedItems.Count > 0)
|
||||
{
|
||||
deleteButton.Enabled = true;
|
||||
openButton.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;
|
||||
pictureBox1.Image = imgurInfo.Image;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
pictureBox1.Image = pictureBox1.ErrorImage;
|
||||
deleteButton.Enabled = false;
|
||||
openButton.Enabled = false;
|
||||
|
@ -134,48 +157,60 @@ namespace Greenshot.Plugin.Imgur.Forms {
|
|||
}
|
||||
}
|
||||
|
||||
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++) {
|
||||
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++)
|
||||
{
|
||||
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);
|
||||
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)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Should fix Bug #3378699
|
||||
pictureBox1.Image = pictureBox1.ErrorImage;
|
||||
try {
|
||||
try
|
||||
{
|
||||
new PleaseWaitForm().ShowAndWait("Imgur", Language.GetString("imgur", LangKey.communication_wait),
|
||||
delegate {
|
||||
ImgurUtils.DeleteImgurImage(imgurInfo);
|
||||
}
|
||||
delegate { ImgurUtils.DeleteImgurImage(imgurInfo); }
|
||||
);
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn("Problem communicating with Imgur: ", ex);
|
||||
}
|
||||
|
||||
imgurInfo.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
Redraw();
|
||||
}
|
||||
|
||||
private void ClipboardButtonClick(object sender, EventArgs e) {
|
||||
private void ClipboardButtonClick(object sender, EventArgs e)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
ImgurInfo imgurInfo = (ImgurInfo) listview_imgur_uploads.SelectedItems[i].Tag;
|
||||
links.AppendLine(Config.UsePageLink ? imgurInfo.Page : imgurInfo.Original);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
if (result == DialogResult.Yes) {
|
||||
if (result == DialogResult.Yes)
|
||||
{
|
||||
Config.runtimeImgurHistory.Clear();
|
||||
Config.ImgurUploadHistory.Clear();
|
||||
IniConfig.Save();
|
||||
|
@ -188,21 +223,28 @@ namespace Greenshot.Plugin.Imgur.Forms {
|
|||
Hide();
|
||||
}
|
||||
|
||||
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++) {
|
||||
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++)
|
||||
{
|
||||
ImgurInfo imgurInfo = (ImgurInfo) listview_imgur_uploads.SelectedItems[i].Tag;
|
||||
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.
|
||||
if (e.Column == _columnSorter.SortColumn) {
|
||||
if (e.Column == _columnSorter.SortColumn)
|
||||
{
|
||||
// Reverse the current sort direction for this column.
|
||||
_columnSorter.Order = _columnSorter.Order == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the column number that is to be sorted; default to ascending.
|
||||
_columnSorter.SortColumn = e.Column;
|
||||
_columnSorter.Order = SortOrder.Ascending;
|
||||
|
|
|
@ -21,11 +21,13 @@
|
|||
|
||||
using System;
|
||||
|
||||
namespace Greenshot.Plugin.Imgur.Forms {
|
||||
namespace Greenshot.Plugin.Imgur.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of PasswordRequestForm.
|
||||
/// </summary>
|
||||
public partial class SettingsForm : ImgurForm {
|
||||
public partial class SettingsForm : ImgurForm
|
||||
{
|
||||
public SettingsForm()
|
||||
{
|
||||
//
|
||||
|
@ -38,7 +40,8 @@ namespace Greenshot.Plugin.Imgur.Forms {
|
|||
historyButton.Enabled = ImgurUtils.IsHistoryLoadingNeeded();
|
||||
}
|
||||
|
||||
private void ButtonHistoryClick(object sender, EventArgs e) {
|
||||
private void ButtonHistoryClick(object sender, EventArgs e)
|
||||
{
|
||||
ImgurHistory.ShowHistory();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,25 +26,32 @@ using Greenshot.Plugin.Imgur.Forms;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.IniFile;
|
||||
|
||||
namespace Greenshot.Plugin.Imgur {
|
||||
namespace Greenshot.Plugin.Imgur
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of ImgurConfiguration.
|
||||
/// </summary>
|
||||
[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")]
|
||||
public string ImgurApi3Url { 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("CopyLinkToClipboard", Description = "Copy the link, which one is controlled by the UsePageLink, on the clipboard", DefaultValue = "True")]
|
||||
public bool CopyLinkToClipboard { get; set; }
|
||||
|
||||
[IniProperty("UsePageLink", Description = "Use pagelink instead of direct link on the clipboard", DefaultValue = "False")]
|
||||
public bool UsePageLink { get; set; }
|
||||
|
||||
[IniProperty("AnonymousAccess", Description = "Use anonymous access to Imgur", DefaultValue = "true")]
|
||||
public bool AnonymousAccess { get; set; }
|
||||
|
||||
|
@ -63,8 +70,10 @@ namespace Greenshot.Plugin.Imgur {
|
|||
|
||||
[IniProperty("AddTitle", Description = "Is the title passed on to Imgur", DefaultValue = "False")]
|
||||
public bool AddTitle { get; set; }
|
||||
|
||||
[IniProperty("AddFilename", Description = "Is the filename passed on to Imgur", DefaultValue = "False")]
|
||||
public bool AddFilename { get; set; }
|
||||
|
||||
[IniProperty("FilenamePattern", Description = "Filename for the Imgur upload", DefaultValue = "${capturetime:d\"yyyyMMdd-HHmm\"}")]
|
||||
public string FilenamePattern { get; set; }
|
||||
|
||||
|
@ -73,10 +82,7 @@ namespace Greenshot.Plugin.Imgur {
|
|||
|
||||
// Not stored, only run-time!
|
||||
public Dictionary<string, ImgurInfo> runtimeImgurHistory = new Dictionary<string, ImgurInfo>();
|
||||
public int Credits {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public int Credits { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Supply values we can't put as defaults
|
||||
|
@ -94,7 +100,8 @@ namespace Greenshot.Plugin.Imgur {
|
|||
/// A form for username/password
|
||||
/// </summary>
|
||||
/// <returns>bool true if OK was pressed, false if cancel</returns>
|
||||
public bool ShowConfigDialog() {
|
||||
public bool ShowConfigDialog()
|
||||
{
|
||||
SettingsForm settingsForm = new SettingsForm();
|
||||
DialogResult result = settingsForm.ShowDialog();
|
||||
return result == DialogResult.OK;
|
||||
|
|
|
@ -24,14 +24,17 @@ using System.Drawing;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.Interfaces;
|
||||
|
||||
namespace Greenshot.Plugin.Imgur {
|
||||
namespace Greenshot.Plugin.Imgur
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of ImgurDestination.
|
||||
/// </summary>
|
||||
public class ImgurDestination : AbstractDestination {
|
||||
public class ImgurDestination : AbstractDestination
|
||||
{
|
||||
private readonly ImgurPlugin _plugin;
|
||||
|
||||
public ImgurDestination(ImgurPlugin plugin) {
|
||||
public ImgurDestination(ImgurPlugin plugin)
|
||||
{
|
||||
_plugin = plugin;
|
||||
}
|
||||
|
||||
|
@ -39,17 +42,21 @@ namespace Greenshot.Plugin.Imgur {
|
|||
|
||||
public override string Description => Language.GetString("imgur", LangKey.upload_menu_item);
|
||||
|
||||
public override Image DisplayIcon {
|
||||
get {
|
||||
public override Image DisplayIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
ComponentResourceManager resources = new ComponentResourceManager(typeof(ImgurPlugin));
|
||||
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)
|
||||
{
|
||||
ExportMade = _plugin.Upload(captureDetails, surface, out var uploadUrl), Uri = uploadUrl
|
||||
ExportMade = _plugin.Upload(captureDetails, surface, out var uploadUrl),
|
||||
Uri = uploadUrl
|
||||
};
|
||||
ProcessExport(exportInformation, surface);
|
||||
return exportInformation;
|
||||
|
|
|
@ -32,13 +32,10 @@ namespace Greenshot.Plugin.Imgur
|
|||
{
|
||||
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurInfo));
|
||||
|
||||
public string Hash
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string Hash { get; set; }
|
||||
|
||||
private string _deleteHash;
|
||||
|
||||
public string DeleteHash
|
||||
{
|
||||
get { return _deleteHash; }
|
||||
|
@ -49,55 +46,24 @@ namespace Greenshot.Plugin.Imgur
|
|||
}
|
||||
}
|
||||
|
||||
public string Title
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string Title { get; set; }
|
||||
|
||||
public string ImageType
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string ImageType { get; set; }
|
||||
|
||||
public DateTime Timestamp
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public DateTime Timestamp { get; set; }
|
||||
|
||||
public string Original
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string Original { get; set; }
|
||||
|
||||
public string Page
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string Page { get; set; }
|
||||
|
||||
public string SmallSquare
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string SmallSquare { get; set; }
|
||||
|
||||
public string LargeThumbnail
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string LargeThumbnail { get; set; }
|
||||
|
||||
public string DeletePage
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string DeletePage { get; set; }
|
||||
|
||||
private Image _image;
|
||||
|
||||
public Image Image
|
||||
{
|
||||
get { return _image; }
|
||||
|
@ -129,8 +95,10 @@ namespace Greenshot.Plugin.Imgur
|
|||
{
|
||||
_image?.Dispose();
|
||||
}
|
||||
|
||||
_image = null;
|
||||
}
|
||||
|
||||
public static ImgurInfo ParseResponse(string response)
|
||||
{
|
||||
Log.Debug(response);
|
||||
|
@ -154,26 +122,31 @@ namespace Greenshot.Plugin.Imgur
|
|||
{
|
||||
imgurInfo.Hash = nodes.Item(0)?.InnerText;
|
||||
}
|
||||
|
||||
nodes = doc.GetElementsByTagName("hash");
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
imgurInfo.Hash = nodes.Item(0)?.InnerText;
|
||||
}
|
||||
|
||||
nodes = doc.GetElementsByTagName("deletehash");
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
imgurInfo.DeleteHash = nodes.Item(0)?.InnerText;
|
||||
}
|
||||
|
||||
nodes = doc.GetElementsByTagName("type");
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
imgurInfo.ImageType = nodes.Item(0)?.InnerText;
|
||||
}
|
||||
|
||||
nodes = doc.GetElementsByTagName("title");
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
imgurInfo.Title = nodes.Item(0)?.InnerText;
|
||||
}
|
||||
|
||||
nodes = doc.GetElementsByTagName("datetime");
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
|
@ -184,17 +157,20 @@ namespace Greenshot.Plugin.Imgur
|
|||
imgurInfo.Timestamp = epoch.AddSeconds(secondsSince).DateTime;
|
||||
}
|
||||
}
|
||||
|
||||
nodes = doc.GetElementsByTagName("original");
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
imgurInfo.Original = nodes.Item(0)?.InnerText.Replace("http:", "https:");
|
||||
}
|
||||
|
||||
// Version 3 API only has Link
|
||||
nodes = doc.GetElementsByTagName("link");
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
imgurInfo.Original = nodes.Item(0)?.InnerText.Replace("http:", "https:");
|
||||
}
|
||||
|
||||
nodes = doc.GetElementsByTagName("imgur_page");
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
|
@ -205,6 +181,7 @@ namespace Greenshot.Plugin.Imgur
|
|||
// Version 3 doesn't have a page link in the response
|
||||
imgurInfo.Page = $"https://imgur.com/{imgurInfo.Hash}";
|
||||
}
|
||||
|
||||
nodes = doc.GetElementsByTagName("small_square");
|
||||
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);
|
||||
}
|
||||
|
||||
return imgurInfo;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,37 +32,46 @@ using GreenshotPlugin.IniFile;
|
|||
using GreenshotPlugin.Interfaces;
|
||||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
|
||||
namespace Greenshot.Plugin.Imgur {
|
||||
namespace Greenshot.Plugin.Imgur
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the ImgurPlugin code
|
||||
/// </summary>
|
||||
[Plugin("Imgur", true)]
|
||||
public class ImgurPlugin : IGreenshotPlugin {
|
||||
public class ImgurPlugin : IGreenshotPlugin
|
||||
{
|
||||
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurPlugin));
|
||||
private static ImgurConfiguration _config;
|
||||
private ComponentResourceManager _resources;
|
||||
private ToolStripMenuItem _historyMenuItem;
|
||||
private ToolStripMenuItem _itemPlugInConfig;
|
||||
|
||||
public void Dispose() {
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing) {
|
||||
if (disposing) {
|
||||
if (_historyMenuItem != null) {
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (_historyMenuItem != null)
|
||||
{
|
||||
_historyMenuItem.Dispose();
|
||||
_historyMenuItem = null;
|
||||
}
|
||||
if (_itemPlugInConfig != null) {
|
||||
|
||||
if (_itemPlugInConfig != null)
|
||||
{
|
||||
_itemPlugInConfig.Dispose();
|
||||
_itemPlugInConfig = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<IDestination> Destinations() {
|
||||
private IEnumerable<IDestination> Destinations()
|
||||
{
|
||||
yield return new ImgurDestination(this);
|
||||
}
|
||||
|
||||
|
@ -70,7 +79,8 @@ namespace Greenshot.Plugin.Imgur {
|
|||
/// Implementation of the IGreenshotPlugin.Initialize
|
||||
/// </summary>
|
||||
/// <returns>true if plugin is initialized, false if not (doesn't show)</returns>
|
||||
public bool Initialize() {
|
||||
public bool Initialize()
|
||||
{
|
||||
// Get configuration
|
||||
_config = IniConfig.GetIniSection<ImgurConfiguration>();
|
||||
_resources = new ComponentResourceManager(typeof(ImgurPlugin));
|
||||
|
@ -83,15 +93,11 @@ namespace Greenshot.Plugin.Imgur {
|
|||
// Provide the IDestination
|
||||
SimpleServiceProvider.Current.AddService(Destinations());
|
||||
_historyMenuItem = new ToolStripMenuItem(Language.GetString("imgur", LangKey.history));
|
||||
_historyMenuItem.Click += delegate {
|
||||
ImgurHistory.ShowHistory();
|
||||
};
|
||||
_historyMenuItem.Click += delegate { ImgurHistory.ShowHistory(); };
|
||||
itemPlugInRoot.DropDownItems.Add(_historyMenuItem);
|
||||
|
||||
_itemPlugInConfig = new ToolStripMenuItem(Language.GetString("imgur", LangKey.configure));
|
||||
_itemPlugInConfig.Click += delegate {
|
||||
_config.ShowConfigDialog();
|
||||
};
|
||||
_itemPlugInConfig.Click += delegate { _config.ShowConfigDialog(); };
|
||||
itemPlugInRoot.DropDownItems.Add(_itemPlugInConfig);
|
||||
|
||||
PluginUtils.AddToContextMenu(itemPlugInRoot);
|
||||
|
@ -102,20 +108,26 @@ namespace Greenshot.Plugin.Imgur {
|
|||
return true;
|
||||
}
|
||||
|
||||
public void OnLanguageChanged(object sender, EventArgs e) {
|
||||
if (_itemPlugInConfig != null) {
|
||||
public void OnLanguageChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (_itemPlugInConfig != null)
|
||||
{
|
||||
_itemPlugInConfig.Text = Language.GetString("imgur", LangKey.configure);
|
||||
}
|
||||
if (_historyMenuItem != null) {
|
||||
|
||||
if (_historyMenuItem != null)
|
||||
{
|
||||
_historyMenuItem.Text = Language.GetString("imgur", LangKey.history);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateHistoryMenuItem() {
|
||||
private void UpdateHistoryMenuItem()
|
||||
{
|
||||
if (_historyMenuItem == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var form = SimpleServiceProvider.Current.GetInstance<Form>();
|
||||
|
@ -126,18 +138,25 @@ namespace Greenshot.Plugin.Imgur {
|
|||
{
|
||||
return;
|
||||
}
|
||||
if (_config?.ImgurUploadHistory != null && _config.ImgurUploadHistory.Count > 0) {
|
||||
|
||||
if (_config?.ImgurUploadHistory != null && _config.ImgurUploadHistory.Count > 0)
|
||||
{
|
||||
historyMenuItem.Enabled = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
historyMenuItem.Enabled = false;
|
||||
}
|
||||
});
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error loading history", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Shutdown() {
|
||||
public virtual void Shutdown()
|
||||
{
|
||||
Log.Debug("Imgur Plugin shutdown.");
|
||||
Language.LanguageChanged -= OnLanguageChanged;
|
||||
}
|
||||
|
@ -145,7 +164,8 @@ namespace Greenshot.Plugin.Imgur {
|
|||
/// <summary>
|
||||
/// Implementation of the IPlugin.Configure
|
||||
/// </summary>
|
||||
public virtual void Configure() {
|
||||
public virtual void Configure()
|
||||
{
|
||||
_config.ShowConfigDialog();
|
||||
}
|
||||
|
||||
|
@ -156,9 +176,11 @@ namespace Greenshot.Plugin.Imgur {
|
|||
/// <param name="surfaceToUpload">ISurface</param>
|
||||
/// <param name="uploadUrl">out string for the url</param>
|
||||
/// <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);
|
||||
try {
|
||||
try
|
||||
{
|
||||
string filename = Path.GetFileName(FilenameHelper.GetFilenameFromPattern(_config.FilenamePattern, _config.UploadFormat, captureDetails));
|
||||
ImgurInfo imgurInfo = null;
|
||||
|
||||
|
@ -167,7 +189,8 @@ namespace Greenshot.Plugin.Imgur {
|
|||
delegate
|
||||
{
|
||||
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);
|
||||
_config.ImgurUploadHistory.Add(imgurInfo.Hash, imgurInfo.DeleteHash);
|
||||
_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
|
||||
using (Image tmpImage = surfaceToUpload.GetImageForExport()) {
|
||||
using (Image tmpImage = surfaceToUpload.GetImageForExport())
|
||||
{
|
||||
imgurInfo.Image = ImageHelper.CreateThumbnail(tmpImage, 90, 90);
|
||||
}
|
||||
|
||||
IniConfig.Save();
|
||||
|
||||
if (_config.UsePageLink)
|
||||
|
@ -191,12 +217,12 @@ namespace Greenshot.Plugin.Imgur {
|
|||
{
|
||||
uploadUrl = imgurInfo.Original;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(uploadUrl) && _config.CopyLinkToClipboard)
|
||||
{
|
||||
try
|
||||
{
|
||||
ClipboardHelper.SetClipboardData(uploadUrl);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -204,12 +230,16 @@ namespace Greenshot.Plugin.Imgur {
|
|||
uploadUrl = null;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error("Error uploading.", e);
|
||||
MessageBox.Show(Language.GetString("imgur", LangKey.upload_failure) + " " + e.Message);
|
||||
}
|
||||
|
||||
uploadUrl = null;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -30,11 +30,13 @@ using GreenshotPlugin.IniFile;
|
|||
using GreenshotPlugin.Interfaces;
|
||||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
|
||||
namespace Greenshot.Plugin.Imgur {
|
||||
namespace Greenshot.Plugin.Imgur
|
||||
{
|
||||
/// <summary>
|
||||
/// A collection of Imgur helper methods
|
||||
/// </summary>
|
||||
public static class ImgurUtils {
|
||||
public static class ImgurUtils
|
||||
{
|
||||
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurUtils));
|
||||
private const string SmallUrlPattern = "http://i.imgur.com/{0}s.jpg";
|
||||
private static readonly ImgurConfiguration Config = IniConfig.GetIniSection<ImgurConfiguration>();
|
||||
|
@ -45,14 +47,16 @@ namespace Greenshot.Plugin.Imgur {
|
|||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load the complete history of the imgur uploads, with the corresponding information
|
||||
/// </summary>
|
||||
public static void LoadHistory() {
|
||||
public static void LoadHistory()
|
||||
{
|
||||
if (!IsHistoryLoadingNeeded())
|
||||
{
|
||||
return;
|
||||
|
@ -61,8 +65,10 @@ namespace Greenshot.Plugin.Imgur {
|
|||
bool saveNeeded = false;
|
||||
|
||||
// Load the ImUr history
|
||||
foreach (string hash in Config.ImgurUploadHistory.Keys.ToList()) {
|
||||
if (Config.runtimeImgurHistory.ContainsKey(hash)) {
|
||||
foreach (string hash in Config.ImgurUploadHistory.Keys.ToList())
|
||||
{
|
||||
if (Config.runtimeImgurHistory.ContainsKey(hash))
|
||||
{
|
||||
// Already loaded
|
||||
continue;
|
||||
}
|
||||
|
@ -71,18 +77,24 @@ namespace Greenshot.Plugin.Imgur {
|
|||
{
|
||||
var deleteHash = Config.ImgurUploadHistory[hash];
|
||||
ImgurInfo imgurInfo = RetrieveImgurInfo(hash, deleteHash);
|
||||
if (imgurInfo != null) {
|
||||
if (imgurInfo != null)
|
||||
{
|
||||
RetrieveImgurThumbnail(imgurInfo);
|
||||
Config.runtimeImgurHistory[hash] = imgurInfo;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.InfoFormat("Deleting unknown ImgUr {0} from config, delete hash was {1}.", hash, deleteHash);
|
||||
Config.ImgurUploadHistory.Remove(hash);
|
||||
Config.runtimeImgurHistory.Remove(hash);
|
||||
saveNeeded = true;
|
||||
}
|
||||
} catch (WebException wE) {
|
||||
}
|
||||
catch (WebException wE)
|
||||
{
|
||||
bool redirected = false;
|
||||
if (wE.Status == WebExceptionStatus.ProtocolError) {
|
||||
if (wE.Status == WebExceptionStatus.ProtocolError)
|
||||
{
|
||||
HttpWebResponse response = (HttpWebResponse) wE.Response;
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.Forbidden)
|
||||
|
@ -90,22 +102,30 @@ namespace Greenshot.Plugin.Imgur {
|
|||
Log.Error("Imgur loading forbidden", wE);
|
||||
break;
|
||||
}
|
||||
|
||||
// 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);
|
||||
Config.ImgurUploadHistory.Remove(hash);
|
||||
Config.runtimeImgurHistory.Remove(hash);
|
||||
redirected = true;
|
||||
}
|
||||
}
|
||||
if (!redirected) {
|
||||
|
||||
if (!redirected)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (saveNeeded) {
|
||||
|
||||
if (saveNeeded)
|
||||
{
|
||||
// Save needed changes
|
||||
IniConfig.Save();
|
||||
}
|
||||
|
@ -115,7 +135,8 @@ namespace Greenshot.Plugin.Imgur {
|
|||
/// Use this to make sure Imgur knows from where the upload comes.
|
||||
/// </summary>
|
||||
/// <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);
|
||||
}
|
||||
|
||||
|
@ -128,27 +149,36 @@ namespace Greenshot.Plugin.Imgur {
|
|||
/// <param name="title">Title</param>
|
||||
/// <param name="filename">Filename</param>
|
||||
/// <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>();
|
||||
// add title
|
||||
if (title != null && Config.AddTitle) {
|
||||
if (title != null && Config.AddTitle)
|
||||
{
|
||||
otherParameters["title"] = title;
|
||||
}
|
||||
|
||||
// add filename
|
||||
if (filename != null && Config.AddFilename) {
|
||||
if (filename != null && Config.AddFilename)
|
||||
{
|
||||
otherParameters["name"] = filename;
|
||||
}
|
||||
|
||||
string responseString = null;
|
||||
if (Config.AnonymousAccess) {
|
||||
if (Config.AnonymousAccess)
|
||||
{
|
||||
// add key, we only use the other parameters for the AnonymousAccess
|
||||
//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.ServicePoint.Expect100Continue = false;
|
||||
|
||||
SetClientId(webRequest);
|
||||
try {
|
||||
using (var requestStream = webRequest.GetRequestStream()) {
|
||||
try
|
||||
{
|
||||
using (var requestStream = webRequest.GetRequestStream())
|
||||
{
|
||||
ImageOutput.SaveToStream(surfaceToUpload, requestStream, outputSettings);
|
||||
}
|
||||
|
||||
|
@ -160,12 +190,15 @@ namespace Greenshot.Plugin.Imgur {
|
|||
using StreamReader reader = new StreamReader(responseStream, true);
|
||||
responseString = reader.ReadToEnd();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Upload to imgur gave an exception: ", ex);
|
||||
throw;
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var oauth2Settings = new OAuth2Settings
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(responseString))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return ImgurInfo.ParseResponse(responseString);
|
||||
}
|
||||
|
||||
|
@ -212,11 +247,14 @@ namespace Greenshot.Plugin.Imgur {
|
|||
/// Retrieve the thumbnail of an imgur image
|
||||
/// </summary>
|
||||
/// <param name="imgurInfo"></param>
|
||||
public static void RetrieveImgurThumbnail(ImgurInfo imgurInfo) {
|
||||
if (imgurInfo.SmallSquare == null) {
|
||||
public static void RetrieveImgurThumbnail(ImgurInfo imgurInfo)
|
||||
{
|
||||
if (imgurInfo.SmallSquare == null)
|
||||
{
|
||||
Log.Warn("Imgur URL was null, not retrieving thumbnail.");
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
webRequest.ServicePoint.Expect100Continue = false;
|
||||
|
@ -237,7 +275,8 @@ namespace Greenshot.Plugin.Imgur {
|
|||
/// <param name="hash"></param>
|
||||
/// <param name="deleteHash"></param>
|
||||
/// <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";
|
||||
Log.InfoFormat("Retrieving Imgur info for {0} with url {1}", hash, url);
|
||||
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, HTTPMethod.GET);
|
||||
|
@ -254,14 +293,20 @@ namespace Greenshot.Plugin.Imgur {
|
|||
using StreamReader reader = new StreamReader(responseStream, true);
|
||||
responseString = reader.ReadToEnd();
|
||||
}
|
||||
} catch (WebException wE) {
|
||||
if (wE.Status == WebExceptionStatus.ProtocolError) {
|
||||
if (((HttpWebResponse)wE.Response).StatusCode == HttpStatusCode.NotFound) {
|
||||
}
|
||||
catch (WebException wE)
|
||||
{
|
||||
if (wE.Status == WebExceptionStatus.ProtocolError)
|
||||
{
|
||||
if (((HttpWebResponse) wE.Response).StatusCode == HttpStatusCode.NotFound)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
ImgurInfo imgurInfo = null;
|
||||
if (responseString != null)
|
||||
{
|
||||
|
@ -269,6 +314,7 @@ namespace Greenshot.Plugin.Imgur {
|
|||
imgurInfo = ImgurInfo.ParseResponse(responseString);
|
||||
imgurInfo.DeleteHash = deleteHash;
|
||||
}
|
||||
|
||||
return imgurInfo;
|
||||
}
|
||||
|
||||
|
@ -276,16 +322,19 @@ namespace Greenshot.Plugin.Imgur {
|
|||
/// Delete an imgur image, this is done by specifying the delete hash
|
||||
/// </summary>
|
||||
/// <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);
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
string url = Config.ImgurApi3Url + "/image/" + imgurInfo.DeleteHash + ".xml";
|
||||
HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, HTTPMethod.DELETE);
|
||||
webRequest.ServicePoint.Expect100Continue = false;
|
||||
SetClientId(webRequest);
|
||||
string responseString = null;
|
||||
using (WebResponse response = webRequest.GetResponse()) {
|
||||
using (WebResponse response = webRequest.GetResponse())
|
||||
{
|
||||
LogRateLimitInfo(response);
|
||||
var responseStream = response.GetResponseStream();
|
||||
if (responseStream != null)
|
||||
|
@ -294,15 +343,21 @@ namespace Greenshot.Plugin.Imgur {
|
|||
responseString = reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
|
||||
Log.InfoFormat("Delete result: {0}", responseString);
|
||||
} catch (WebException wE) {
|
||||
}
|
||||
catch (WebException wE)
|
||||
{
|
||||
// Allow "Bad request" this means we already deleted it
|
||||
if (wE.Status == WebExceptionStatus.ProtocolError) {
|
||||
if (((HttpWebResponse)wE.Response).StatusCode != HttpStatusCode.BadRequest) {
|
||||
if (wE.Status == WebExceptionStatus.ProtocolError)
|
||||
{
|
||||
if (((HttpWebResponse) wE.Response).StatusCode != HttpStatusCode.BadRequest)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we remove it from the history, if no error occurred
|
||||
Config.runtimeImgurHistory.Remove(imgurInfo.Hash);
|
||||
Config.ImgurUploadHistory.Remove(imgurInfo.Hash);
|
||||
|
@ -314,8 +369,10 @@ namespace Greenshot.Plugin.Imgur {
|
|||
/// </summary>
|
||||
/// <param name="nameValues"></param>
|
||||
/// <param name="key"></param>
|
||||
private static void LogHeader(IDictionary<string, string> nameValues, string key) {
|
||||
if (nameValues.ContainsKey(key)) {
|
||||
private static void LogHeader(IDictionary<string, string> nameValues, string key)
|
||||
{
|
||||
if (nameValues.ContainsKey(key))
|
||||
{
|
||||
Log.InfoFormat("{0}={1}", key, nameValues[key]);
|
||||
}
|
||||
}
|
||||
|
@ -324,13 +381,17 @@ namespace Greenshot.Plugin.Imgur {
|
|||
/// Log the current rate-limit information
|
||||
/// </summary>
|
||||
/// <param name="response"></param>
|
||||
private static void LogRateLimitInfo(WebResponse response) {
|
||||
private static void LogRateLimitInfo(WebResponse response)
|
||||
{
|
||||
IDictionary<string, string> nameValues = new Dictionary<string, string>();
|
||||
foreach (string key in response.Headers.AllKeys) {
|
||||
if (!nameValues.ContainsKey(key)) {
|
||||
foreach (string key in response.Headers.AllKeys)
|
||||
{
|
||||
if (!nameValues.ContainsKey(key))
|
||||
{
|
||||
nameValues.Add(key, response.Headers[key]);
|
||||
}
|
||||
}
|
||||
|
||||
LogHeader(nameValues, "X-RateLimit-Limit");
|
||||
LogHeader(nameValues, "X-RateLimit-Remaining");
|
||||
LogHeader(nameValues, "X-RateLimit-UserLimit");
|
||||
|
@ -340,7 +401,8 @@ namespace Greenshot.Plugin.Imgur {
|
|||
LogHeader(nameValues, "X-RateLimit-ClientRemaining");
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,10 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Greenshot.Plugin.Imgur {
|
||||
public enum LangKey {
|
||||
namespace Greenshot.Plugin.Imgur
|
||||
{
|
||||
public enum LangKey
|
||||
{
|
||||
upload_menu_item,
|
||||
upload_failure,
|
||||
communication_wait,
|
||||
|
|
|
@ -114,6 +114,7 @@ namespace Greenshot.Plugin.Jira
|
|||
{
|
||||
cacheItemPolicy.UpdateCallback = UpdateCallback;
|
||||
}
|
||||
|
||||
if (ActivateRemovedCallback)
|
||||
{
|
||||
cacheItemPolicy.RemovedCallback = RemovedCallback;
|
||||
|
|
|
@ -30,15 +30,18 @@ using GreenshotPlugin.Controls;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.IniFile;
|
||||
|
||||
namespace Greenshot.Plugin.Jira.Forms {
|
||||
public partial class JiraForm : Form {
|
||||
namespace Greenshot.Plugin.Jira.Forms
|
||||
{
|
||||
public partial class JiraForm : Form
|
||||
{
|
||||
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(JiraForm));
|
||||
private readonly JiraConnector _jiraConnector;
|
||||
private Issue _selectedIssue;
|
||||
private readonly GreenshotColumnSorter _columnSorter;
|
||||
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
|
||||
|
||||
public JiraForm(JiraConnector jiraConnector) {
|
||||
public JiraForm(JiraConnector jiraConnector)
|
||||
{
|
||||
InitializeComponent();
|
||||
Icon = GreenshotResources.GetGreenshotIcon();
|
||||
AcceptButton = uploadButton;
|
||||
|
@ -70,6 +73,7 @@ namespace Greenshot.Plugin.Jira.Forms {
|
|||
{
|
||||
MessageBox.Show(Language.GetFormattedString("jira", LangKey.login_error, e.Message));
|
||||
}
|
||||
|
||||
if (_jiraConnector.IsLoggedIn)
|
||||
{
|
||||
var filters = await _jiraConnector.GetFavoriteFiltersAsync();
|
||||
|
@ -79,8 +83,10 @@ namespace Greenshot.Plugin.Jira.Forms {
|
|||
{
|
||||
jiraFilterBox.Items.Add(filter);
|
||||
}
|
||||
|
||||
jiraFilterBox.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
ChangeModus(true);
|
||||
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_comment.Text = Language.GetString("jira", LangKey.label_comment);
|
||||
label_filename.Text = Language.GetString("jira", LangKey.label_filename);
|
||||
}
|
||||
|
||||
private void ChangeModus(bool enabled) {
|
||||
private void ChangeModus(bool enabled)
|
||||
{
|
||||
jiraFilterBox.Enabled = enabled;
|
||||
jiraListView.Enabled = enabled;
|
||||
jiraFilenameBox.Enabled = enabled;
|
||||
jiraCommentBox.Enabled = enabled;
|
||||
}
|
||||
|
||||
public void SetFilename(string filename) {
|
||||
public void SetFilename(string filename)
|
||||
{
|
||||
jiraFilenameBox.Text = filename;
|
||||
}
|
||||
|
||||
public Issue GetJiraIssue() {
|
||||
public Issue GetJiraIssue()
|
||||
{
|
||||
return _selectedIssue;
|
||||
}
|
||||
|
||||
public async Task UploadAsync(IBinaryContainer attachment) {
|
||||
public async Task UploadAsync(IBinaryContainer attachment)
|
||||
{
|
||||
attachment.Filename = jiraFilenameBox.Text;
|
||||
await _jiraConnector.AttachAsync(_selectedIssue.Key, attachment);
|
||||
|
||||
if (!string.IsNullOrEmpty(jiraCommentBox.Text)) {
|
||||
if (!string.IsNullOrEmpty(jiraCommentBox.Text))
|
||||
{
|
||||
await _jiraConnector.AddCommentAsync(_selectedIssue.Key, jiraCommentBox.Text);
|
||||
}
|
||||
}
|
||||
|
||||
private async void JiraFilterBox_SelectedIndexChanged(object sender, EventArgs e) {
|
||||
if (_jiraConnector.IsLoggedIn) {
|
||||
|
||||
private async void JiraFilterBox_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (_jiraConnector.IsLoggedIn)
|
||||
{
|
||||
uploadButton.Enabled = false;
|
||||
var filter = (Filter) jiraFilterBox.SelectedItem;
|
||||
if (filter == null) {
|
||||
if (filter == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IList<Issue> issues = null;
|
||||
try
|
||||
{
|
||||
|
@ -141,25 +156,33 @@ namespace Greenshot.Plugin.Jira.Forms {
|
|||
}
|
||||
|
||||
jiraListView.Items.Clear();
|
||||
if (issues?.Count > 0) {
|
||||
if (issues?.Count > 0)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (!Language.TryGetString("jira", column, out var translation))
|
||||
{
|
||||
translation = string.Empty;
|
||||
}
|
||||
|
||||
jiraListView.Columns.Add(translation);
|
||||
}
|
||||
|
||||
var scaledIconSize = DpiHelper.ScaleWithDpi(CoreConfig.IconSize, DpiHelper.GetDpi(Handle));
|
||||
var imageList = new ImageList {
|
||||
var imageList = new ImageList
|
||||
{
|
||||
ImageSize = scaledIconSize
|
||||
};
|
||||
jiraListView.SmallImageList = imageList;
|
||||
jiraListView.LargeImageList = imageList;
|
||||
|
||||
foreach (var issue in issues) {
|
||||
foreach (var issue in issues)
|
||||
{
|
||||
var item = new ListViewItem
|
||||
{
|
||||
Tag = issue
|
||||
|
@ -187,6 +210,7 @@ namespace Greenshot.Plugin.Jira.Forms {
|
|||
{
|
||||
jiraListView.AutoResizeColumn(i, ColumnHeaderAutoResizeStyle.ColumnContent);
|
||||
}
|
||||
|
||||
jiraListView.Invalidate();
|
||||
jiraListView.Update();
|
||||
}
|
||||
|
@ -196,22 +220,30 @@ namespace Greenshot.Plugin.Jira.Forms {
|
|||
}
|
||||
}
|
||||
|
||||
private void JiraListView_SelectedIndexChanged(object sender, EventArgs e) {
|
||||
if (jiraListView.SelectedItems.Count > 0) {
|
||||
private void JiraListView_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (jiraListView.SelectedItems.Count > 0)
|
||||
{
|
||||
_selectedIssue = (Issue) jiraListView.SelectedItems[0].Tag;
|
||||
jiraKey.Text = _selectedIssue.Key;
|
||||
uploadButton.Enabled = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
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.
|
||||
if (e.Column == _columnSorter.SortColumn) {
|
||||
if (e.Column == _columnSorter.SortColumn)
|
||||
{
|
||||
// Reverse the current sort direction for this column.
|
||||
_columnSorter.Order = _columnSorter.Order == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the column number that is to be sorted; default to ascending.
|
||||
_columnSorter.SortColumn = e.Column;
|
||||
_columnSorter.Order = SortOrder.Ascending;
|
||||
|
@ -221,13 +253,16 @@ namespace Greenshot.Plugin.Jira.Forms {
|
|||
jiraListView.Sort();
|
||||
}
|
||||
|
||||
private async void JiraKeyTextChanged(object sender, EventArgs e) {
|
||||
private async void JiraKeyTextChanged(object sender, EventArgs e)
|
||||
{
|
||||
string jiranumber = jiraKey.Text;
|
||||
uploadButton.Enabled = false;
|
||||
int dashIndex = jiranumber.IndexOf('-');
|
||||
if (dashIndex > 0 && jiranumber.Length > dashIndex+1) {
|
||||
if (dashIndex > 0 && jiranumber.Length > dashIndex + 1)
|
||||
{
|
||||
_selectedIssue = await _jiraConnector.GetIssueAsync(jiraKey.Text);
|
||||
if (_selectedIssue != null) {
|
||||
if (_selectedIssue != null)
|
||||
{
|
||||
uploadButton.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
|
||||
using GreenshotPlugin.Controls;
|
||||
|
||||
namespace Greenshot.Plugin.Jira.Forms {
|
||||
public class JiraFormBase : GreenshotForm {
|
||||
namespace Greenshot.Plugin.Jira.Forms
|
||||
{
|
||||
public class JiraFormBase : GreenshotForm
|
||||
{
|
||||
}
|
||||
}
|
|
@ -19,11 +19,13 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Greenshot.Plugin.Jira.Forms {
|
||||
namespace Greenshot.Plugin.Jira.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of PasswordRequestForm.
|
||||
/// </summary>
|
||||
public partial class SettingsForm : JiraFormBase {
|
||||
public partial class SettingsForm : JiraFormBase
|
||||
{
|
||||
public SettingsForm()
|
||||
{
|
||||
//
|
||||
|
|
|
@ -22,12 +22,14 @@
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.IniFile;
|
||||
|
||||
namespace Greenshot.Plugin.Jira {
|
||||
namespace Greenshot.Plugin.Jira
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of JiraConfiguration.
|
||||
/// </summary>
|
||||
[IniSection("Jira", Description = "Greenshot Jira Plugin configuration")]
|
||||
public class JiraConfiguration : IniSection {
|
||||
public class JiraConfiguration : IniSection
|
||||
{
|
||||
public const string DefaultPrefix = "http://";
|
||||
private const string DefaultUrl = DefaultPrefix + "jira";
|
||||
|
||||
|
|
|
@ -34,14 +34,18 @@ using Dapplo.Jira.SvgWinForms.Converters;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.IniFile;
|
||||
|
||||
namespace Greenshot.Plugin.Jira {
|
||||
namespace Greenshot.Plugin.Jira
|
||||
{
|
||||
/// <summary>
|
||||
/// This encapsulates the JiraClient to make it possible to change as less old Greenshot code as needed
|
||||
/// </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 JiraConfiguration JiraConfig = IniConfig.GetIniSection<JiraConfiguration>();
|
||||
|
||||
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
|
||||
|
||||
// Used to remove the wsdl information from the old SOAP Uri
|
||||
public const string DefaultPostfix = "/rpc/soap/jirasoapservice-v2?wsdl";
|
||||
private IJiraClient _jiraClient;
|
||||
|
@ -57,20 +61,25 @@ namespace Greenshot.Plugin.Jira {
|
|||
if (args.PropertyName == nameof(CoreConfig.IconSize))
|
||||
{
|
||||
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>
|
||||
/// Dispose, logout the users
|
||||
/// </summary>
|
||||
public void Dispose() {
|
||||
public void Dispose()
|
||||
{
|
||||
if (_jiraClient != null)
|
||||
{
|
||||
Logout();
|
||||
}
|
||||
|
||||
FavIcon?.Dispose();
|
||||
}
|
||||
|
||||
|
@ -99,8 +108,13 @@ namespace Greenshot.Plugin.Jira {
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_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);
|
||||
|
||||
_issueTypeBitmapCache = new IssueTypeBitmapCache(_jiraClient);
|
||||
|
@ -126,6 +140,7 @@ namespace Greenshot.Plugin.Jira {
|
|||
Log.Warn("Exception details: ", ex2);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -134,45 +149,58 @@ namespace Greenshot.Plugin.Jira {
|
|||
/// If there are credentials, call the real login.
|
||||
/// </summary>
|
||||
/// <returns>Task</returns>
|
||||
public async Task LoginAsync(CancellationToken cancellationToken = default) {
|
||||
public async Task LoginAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
Logout();
|
||||
try {
|
||||
try
|
||||
{
|
||||
// Get the system name, so the user knows where to login to
|
||||
var credentialsDialog = new CredentialsDialog(JiraConfig.Url)
|
||||
{
|
||||
Name = null
|
||||
};
|
||||
while (credentialsDialog.Show(credentialsDialog.Name) == DialogResult.OK) {
|
||||
if (await DoLoginAsync(credentialsDialog.Name, credentialsDialog.Password, cancellationToken)) {
|
||||
if (credentialsDialog.SaveChecked) {
|
||||
while (credentialsDialog.Show(credentialsDialog.Name) == DialogResult.OK)
|
||||
{
|
||||
if (await DoLoginAsync(credentialsDialog.Name, credentialsDialog.Password, cancellationToken))
|
||||
{
|
||||
if (credentialsDialog.SaveChecked)
|
||||
{
|
||||
credentialsDialog.Confirm(true);
|
||||
}
|
||||
|
||||
IsLoggedIn = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Login failed, confirm this
|
||||
try {
|
||||
try
|
||||
{
|
||||
credentialsDialog.Confirm(false);
|
||||
} catch (ApplicationException e) {
|
||||
}
|
||||
catch (ApplicationException e)
|
||||
{
|
||||
// exception handling ...
|
||||
Log.Error("Problem using the credentials dialog", e);
|
||||
}
|
||||
|
||||
// For every windows version after XP show an incorrect password baloon
|
||||
credentialsDialog.IncorrectPassword = true;
|
||||
// Make sure the dialog is display, the password was false!
|
||||
credentialsDialog.AlwaysDisplay = true;
|
||||
}
|
||||
} catch (ApplicationException e) {
|
||||
}
|
||||
catch (ApplicationException e)
|
||||
{
|
||||
// exception handling ...
|
||||
Log.Error("Problem using the credentials dialog", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// End the session, if there was one
|
||||
/// </summary>
|
||||
public void Logout() {
|
||||
public void Logout()
|
||||
{
|
||||
if (_jiraClient == null || !IsLoggedIn) return;
|
||||
Monitor.Dispose();
|
||||
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.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task CheckCredentialsAsync(CancellationToken cancellationToken = default) {
|
||||
if (!IsLoggedIn) {
|
||||
private async Task CheckCredentialsAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (!IsLoggedIn)
|
||||
{
|
||||
await LoginAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
|
@ -256,7 +286,10 @@ namespace Greenshot.Plugin.Jira {
|
|||
public async Task<IList<Issue>> SearchAsync(Filter filter, CancellationToken cancellationToken = default)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,27 +34,33 @@ using GreenshotPlugin.IniFile;
|
|||
using GreenshotPlugin.Interfaces;
|
||||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
|
||||
namespace Greenshot.Plugin.Jira {
|
||||
namespace Greenshot.Plugin.Jira
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of JiraDestination.
|
||||
/// </summary>
|
||||
public class JiraDestination : AbstractDestination {
|
||||
public class JiraDestination : AbstractDestination
|
||||
{
|
||||
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(JiraDestination));
|
||||
private static readonly JiraConfiguration Config = IniConfig.GetIniSection<JiraConfiguration>();
|
||||
private readonly Issue _jiraIssue;
|
||||
|
||||
public JiraDestination(Issue jiraIssue = null) {
|
||||
public JiraDestination(Issue jiraIssue = null)
|
||||
{
|
||||
_jiraIssue = jiraIssue;
|
||||
}
|
||||
|
||||
public override string Designation => "Jira";
|
||||
|
||||
public override string Description {
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_jiraIssue?.Fields?.Summary == null) {
|
||||
if (_jiraIssue?.Fields?.Summary == null)
|
||||
{
|
||||
return Language.GetString("jira", LangKey.upload_menu_item);
|
||||
}
|
||||
|
||||
// Format the title of this destination
|
||||
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 Image DisplayIcon {
|
||||
public override Image DisplayIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
Image displayIcon = null;
|
||||
|
@ -83,16 +90,19 @@ namespace Greenshot.Plugin.Jira {
|
|||
Log.Warn($"Problem loading issue type for {_jiraIssue.Key}, ignoring", ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (displayIcon == null)
|
||||
{
|
||||
displayIcon = jiraConnector.FavIcon;
|
||||
}
|
||||
}
|
||||
|
||||
if (displayIcon == null)
|
||||
{
|
||||
var resources = new ComponentResourceManager(typeof(JiraPlugin));
|
||||
displayIcon = (Image) resources.GetObject("Jira");
|
||||
}
|
||||
|
||||
return displayIcon;
|
||||
}
|
||||
}
|
||||
|
@ -100,22 +110,27 @@ namespace Greenshot.Plugin.Jira {
|
|||
public override IEnumerable<IDestination> DynamicDestinations()
|
||||
{
|
||||
var jiraConnector = SimpleServiceProvider.Current.GetInstance<JiraConnector>();
|
||||
if (jiraConnector == null || !jiraConnector.IsLoggedIn) {
|
||||
if (jiraConnector == null || !jiraConnector.IsLoggedIn)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
foreach (var jiraDetails in jiraConnector.Monitor.RecentJiras)
|
||||
{
|
||||
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);
|
||||
string filename = Path.GetFileName(FilenameHelper.GetFilename(Config.UploadFormat, captureDetails));
|
||||
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(Config.UploadFormat, Config.UploadJpegQuality, Config.UploadReduceColors);
|
||||
var jiraConnector = SimpleServiceProvider.Current.GetInstance<JiraConnector>();
|
||||
if (_jiraIssue != null) {
|
||||
try {
|
||||
if (_jiraIssue != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Run upload in the background
|
||||
new PleaseWaitForm().ShowAndWait(Description, Language.GetString("jira", LangKey.communication_wait),
|
||||
async () =>
|
||||
|
@ -128,31 +143,37 @@ namespace Greenshot.Plugin.Jira {
|
|||
Log.DebugFormat("Uploaded to Jira {0}", _jiraIssue.Key);
|
||||
exportInformation.ExportMade = true;
|
||||
exportInformation.Uri = surfaceToUpload.UploadUrl;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessageBox.Show(Language.GetString("jira", LangKey.upload_failure) + " " + e.Message);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
var jiraForm = new JiraForm(jiraConnector);
|
||||
jiraForm.SetFilename(filename);
|
||||
var dialogResult = jiraForm.ShowDialog();
|
||||
if (dialogResult == DialogResult.OK) {
|
||||
try {
|
||||
if (dialogResult == DialogResult.OK)
|
||||
{
|
||||
try
|
||||
{
|
||||
surfaceToUpload.UploadUrl = jiraConnector.JiraBaseUri.AppendSegments("browse", jiraForm.GetJiraIssue().Key).AbsoluteUri;
|
||||
// Run upload in the background
|
||||
new PleaseWaitForm().ShowAndWait(Description, Language.GetString("jira", LangKey.communication_wait),
|
||||
async () =>
|
||||
{
|
||||
await jiraForm.UploadAsync(new SurfaceContainer(surfaceToUpload, outputSettings, filename));
|
||||
}
|
||||
async () => { await jiraForm.UploadAsync(new SurfaceContainer(surfaceToUpload, outputSettings, filename)); }
|
||||
);
|
||||
Log.DebugFormat("Uploaded to Jira {0}", jiraForm.GetJiraIssue().Key);
|
||||
exportInformation.ExportMade = true;
|
||||
exportInformation.Uri = surfaceToUpload.UploadUrl;
|
||||
} catch(Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessageBox.Show(Language.GetString("jira", LangKey.upload_failure) + " " + e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProcessExport(exportInformation, surfaceToUpload);
|
||||
return exportInformation;
|
||||
}
|
||||
|
|
|
@ -31,37 +31,17 @@ namespace Greenshot.Plugin.Jira
|
|||
FirstSeenAt = SeenAt = DateTimeOffset.Now;
|
||||
}
|
||||
|
||||
public string ProjectKey
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string ProjectKey { get; set; }
|
||||
|
||||
public string Id
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string Id { get; set; }
|
||||
|
||||
public string JiraKey => ProjectKey + "-" + Id;
|
||||
|
||||
public Issue JiraIssue
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public Issue JiraIssue { get; set; }
|
||||
|
||||
public DateTimeOffset FirstSeenAt
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public DateTimeOffset FirstSeenAt { get; private set; }
|
||||
|
||||
public DateTimeOffset SeenAt
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public DateTimeOffset SeenAt { get; set; }
|
||||
|
||||
public int CompareTo(JiraDetails other)
|
||||
{
|
||||
|
|
|
@ -25,16 +25,8 @@ namespace Greenshot.Plugin.Jira
|
|||
{
|
||||
public class JiraEventArgs : EventArgs
|
||||
{
|
||||
public JiraEventTypes EventType
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public JiraEventTypes EventType { get; set; }
|
||||
|
||||
public JiraDetails Details
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public JiraDetails Details { get; set; }
|
||||
}
|
||||
}
|
|
@ -31,7 +31,6 @@ using GreenshotPlugin.Hooking;
|
|||
|
||||
namespace Greenshot.Plugin.Jira
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
|
@ -44,7 +43,9 @@ namespace Greenshot.Plugin.Jira
|
|||
private readonly WindowsTitleMonitor _monitor;
|
||||
private readonly IList<IJiraClient> _jiraInstances = new List<IJiraClient>();
|
||||
private readonly IDictionary<string, IJiraClient> _projectJiraClientMap = new Dictionary<string, IJiraClient>();
|
||||
|
||||
private readonly int _maxEntries;
|
||||
|
||||
// TODO: Add issues from issueHistory (JQL -> Where.IssueKey.InIssueHistory())
|
||||
private IDictionary<string, JiraDetails> _recentJiras = new Dictionary<string, JiraDetails>();
|
||||
|
||||
|
@ -79,6 +80,7 @@ namespace Greenshot.Plugin.Jira
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// free managed resources
|
||||
_monitor.TitleChangeEvent -= MonitorTitleChangeEvent;
|
||||
_monitor.Dispose();
|
||||
|
@ -143,8 +145,13 @@ namespace Greenshot.Plugin.Jira
|
|||
var issue = await jiraClient.Issue.GetAsync(jiraDetails.JiraKey).ConfigureAwait(false);
|
||||
jiraDetails.JiraIssue = issue;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
|
@ -163,11 +170,13 @@ namespace Greenshot.Plugin.Jira
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var jiraKeyMatch = _jiraKeyPattern.Match(windowTitle);
|
||||
if (!jiraKeyMatch.Success)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Found a possible JIRA title
|
||||
var jiraKey = jiraKeyMatch.Value;
|
||||
var jiraKeyParts = jiraKey.Split('-');
|
||||
|
@ -184,11 +193,16 @@ namespace Greenshot.Plugin.Jira
|
|||
currentJiraDetails.SeenAt = DateTimeOffset.Now;
|
||||
|
||||
// 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
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We detected an unknown JIRA, so add it to our list
|
||||
currentJiraDetails = new JiraDetails
|
||||
{
|
||||
|
@ -205,6 +219,7 @@ namespace Greenshot.Plugin.Jira
|
|||
orderby jiraDetails.SeenAt descending
|
||||
select jiraDetails).Take(_maxEntries).ToDictionary(jd => jd.JiraKey, jd => jd);
|
||||
}
|
||||
|
||||
// Now we can get the title from JIRA itself
|
||||
// ReSharper disable once UnusedVariable
|
||||
var updateTitleTask = DetectedNewJiraIssueAsync(currentJiraDetails);
|
||||
|
|
|
@ -30,21 +30,25 @@ using GreenshotPlugin.Interfaces;
|
|||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
using log4net;
|
||||
|
||||
namespace Greenshot.Plugin.Jira {
|
||||
namespace Greenshot.Plugin.Jira
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the JiraPlugin base code
|
||||
/// </summary>
|
||||
[Plugin("Jira", true)]
|
||||
public class JiraPlugin : IGreenshotPlugin {
|
||||
public class JiraPlugin : IGreenshotPlugin
|
||||
{
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(JiraPlugin));
|
||||
private JiraConfiguration _config;
|
||||
|
||||
public void Dispose() {
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected void Dispose(bool disposing) {
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
var jiraConnector = SimpleServiceProvider.Current.GetInstance<JiraConnector>();
|
||||
|
@ -56,7 +60,8 @@ namespace Greenshot.Plugin.Jira {
|
|||
/// Implementation of the IGreenshotPlugin.Initialize
|
||||
/// </summary>
|
||||
/// <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)
|
||||
_config = IniConfig.GetIniSection<JiraConfiguration>();
|
||||
|
||||
|
@ -94,7 +99,8 @@ namespace Greenshot.Plugin.Jira {
|
|||
return true;
|
||||
}
|
||||
|
||||
public void Shutdown() {
|
||||
public void Shutdown()
|
||||
{
|
||||
Log.Debug("Jira Plugin shutdown.");
|
||||
var jiraConnector = SimpleServiceProvider.Current.GetInstance<JiraConnector>();
|
||||
jiraConnector?.Logout();
|
||||
|
@ -103,18 +109,19 @@ namespace Greenshot.Plugin.Jira {
|
|||
/// <summary>
|
||||
/// Implementation of the IPlugin.Configure
|
||||
/// </summary>
|
||||
public void Configure() {
|
||||
public void Configure()
|
||||
{
|
||||
string url = _config.Url;
|
||||
if (ShowConfigDialog()) {
|
||||
if (ShowConfigDialog())
|
||||
{
|
||||
// check for re-login
|
||||
var jiraConnector = SimpleServiceProvider.Current.GetInstance<JiraConnector>();
|
||||
if (jiraConnector != null && jiraConnector.IsLoggedIn && !string.IsNullOrEmpty(url)) {
|
||||
if (!url.Equals(_config.Url)) {
|
||||
jiraConnector.Logout();
|
||||
Task.Run(async () =>
|
||||
if (jiraConnector != null && jiraConnector.IsLoggedIn && !string.IsNullOrEmpty(url))
|
||||
{
|
||||
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 false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,10 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Greenshot.Plugin.Jira {
|
||||
public enum LangKey {
|
||||
namespace Greenshot.Plugin.Jira
|
||||
{
|
||||
public enum LangKey
|
||||
{
|
||||
upload_menu_item,
|
||||
column_assignee,
|
||||
column_created,
|
||||
|
|
|
@ -114,6 +114,7 @@ namespace Greenshot.Plugin.Jira
|
|||
case LogLevels.Warn:
|
||||
return log.IsWarnEnabled;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Copyright (c) Dapplo and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Greenshot.Plugin.Office.Com
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace Greenshot.Plugin.Office.Com
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not catch an exception from this.
|
||||
// You may want to remove these guards depending on
|
||||
// what you think the semantics should be.
|
||||
|
@ -45,6 +46,7 @@ namespace Greenshot.Plugin.Office.Com
|
|||
{
|
||||
Marshal.ReleaseComObject(ComObject);
|
||||
}
|
||||
|
||||
ComObject = default;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace Greenshot.Plugin.Office.Com
|
|||
{
|
||||
return clsId;
|
||||
}
|
||||
|
||||
return clsId;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,29 +28,37 @@ using GreenshotPlugin.Core;
|
|||
using GreenshotPlugin.Interfaces;
|
||||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
|
||||
namespace Greenshot.Plugin.Office.Destinations {
|
||||
namespace Greenshot.Plugin.Office.Destinations
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of PowerpointDestination.
|
||||
/// </summary>
|
||||
public class ExcelDestination : AbstractDestination {
|
||||
public class ExcelDestination : AbstractDestination
|
||||
{
|
||||
private const int IconApplication = 0;
|
||||
private const int IconWorkbook = 1;
|
||||
private static readonly string ExePath;
|
||||
private readonly string _workbookName;
|
||||
|
||||
static ExcelDestination() {
|
||||
static ExcelDestination()
|
||||
{
|
||||
ExePath = PluginUtils.GetExePath("EXCEL.EXE");
|
||||
if (ExePath != null && File.Exists(ExePath)) {
|
||||
if (ExePath != null && File.Exists(ExePath))
|
||||
{
|
||||
WindowDetails.AddProcessToExcludeFromFreeze("excel");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ExePath = null;
|
||||
}
|
||||
}
|
||||
|
||||
public ExcelDestination() {
|
||||
public ExcelDestination()
|
||||
{
|
||||
}
|
||||
|
||||
public ExcelDestination(string workbookName) {
|
||||
public ExcelDestination(string 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 IEnumerable<IDestination> DynamicDestinations() {
|
||||
foreach (string workbookName in ExcelExporter.GetWorkbooks()) {
|
||||
public override IEnumerable<IDestination> DynamicDestinations()
|
||||
{
|
||||
foreach (string workbookName in ExcelExporter.GetWorkbooks())
|
||||
{
|
||||
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);
|
||||
bool createdFile = false;
|
||||
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());
|
||||
createdFile = true;
|
||||
}
|
||||
if (_workbookName != null) {
|
||||
|
||||
if (_workbookName != null)
|
||||
{
|
||||
ExcelExporter.InsertIntoExistingWorkbook(_workbookName, imageFile, surface.Image.Size);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ExcelExporter.InsertIntoNewWorkbook(imageFile, surface.Image.Size);
|
||||
}
|
||||
|
||||
exportInformation.ExportMade = true;
|
||||
ProcessExport(exportInformation, surface);
|
||||
// Cleanup imageFile if we created it here, so less tmp-files are generated and left
|
||||
if (createdFile) {
|
||||
if (createdFile)
|
||||
{
|
||||
ImageOutput.DeleteNamedTmpFile(imageFile);
|
||||
}
|
||||
|
||||
return exportInformation;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,8 +28,10 @@ using Greenshot.Plugin.Office.OfficeExport.Entities;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.Interfaces;
|
||||
|
||||
namespace Greenshot.Plugin.Office.Destinations {
|
||||
public class OneNoteDestination : AbstractDestination {
|
||||
namespace Greenshot.Plugin.Office.Destinations
|
||||
{
|
||||
public class OneNoteDestination : AbstractDestination
|
||||
{
|
||||
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(WordDestination));
|
||||
private const int ICON_APPLICATION = 0;
|
||||
public const string DESIGNATION = "OneNote";
|
||||
|
@ -37,87 +39,105 @@ namespace Greenshot.Plugin.Office.Destinations {
|
|||
private readonly OneNotePage page;
|
||||
private readonly OneNoteExporter _oneNoteExporter = new OneNoteExporter();
|
||||
|
||||
static OneNoteDestination() {
|
||||
static OneNoteDestination()
|
||||
{
|
||||
exePath = PluginUtils.GetExePath("ONENOTE.EXE");
|
||||
if (exePath != null && File.Exists(exePath)) {
|
||||
if (exePath != null && File.Exists(exePath))
|
||||
{
|
||||
WindowDetails.AddProcessToExcludeFromFreeze("onenote");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
exePath = null;
|
||||
}
|
||||
}
|
||||
|
||||
public OneNoteDestination() {
|
||||
|
||||
public OneNoteDestination()
|
||||
{
|
||||
}
|
||||
|
||||
public OneNoteDestination(OneNotePage page) {
|
||||
public OneNoteDestination(OneNotePage page)
|
||||
{
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
public override string Designation {
|
||||
get {
|
||||
return DESIGNATION;
|
||||
}
|
||||
public override string Designation
|
||||
{
|
||||
get { return DESIGNATION; }
|
||||
}
|
||||
|
||||
public override string Description {
|
||||
get {
|
||||
if (page == null) {
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
if (page == null)
|
||||
{
|
||||
return "Microsoft OneNote";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return page.DisplayName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override int Priority {
|
||||
get {
|
||||
return 4;
|
||||
}
|
||||
public override int Priority
|
||||
{
|
||||
get { return 4; }
|
||||
}
|
||||
|
||||
public override bool IsDynamic {
|
||||
get {
|
||||
return true;
|
||||
}
|
||||
public override bool IsDynamic
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override bool IsActive {
|
||||
get {
|
||||
return base.IsActive && exePath != null;
|
||||
}
|
||||
public override bool IsActive
|
||||
{
|
||||
get { return base.IsActive && exePath != null; }
|
||||
}
|
||||
|
||||
public override Image DisplayIcon {
|
||||
get {
|
||||
return PluginUtils.GetCachedExeIcon(exePath, ICON_APPLICATION);
|
||||
}
|
||||
public override Image DisplayIcon
|
||||
{
|
||||
get { return PluginUtils.GetCachedExeIcon(exePath, ICON_APPLICATION); }
|
||||
}
|
||||
|
||||
public override IEnumerable<IDestination> DynamicDestinations() {
|
||||
foreach (OneNotePage page in _oneNoteExporter.GetPages()) {
|
||||
public override IEnumerable<IDestination> DynamicDestinations()
|
||||
{
|
||||
foreach (OneNotePage page in _oneNoteExporter.GetPages())
|
||||
{
|
||||
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);
|
||||
|
||||
if (page == null) {
|
||||
try {
|
||||
if (page == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
exportInformation.ExportMade = _oneNoteExporter.ExportToNewPage(surface);
|
||||
} catch(Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exportInformation.ErrorMessage = ex.Message;
|
||||
LOG.Error(ex);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
exportInformation.ExportMade = _oneNoteExporter.ExportToPage(surface, page);
|
||||
} catch(Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exportInformation.ErrorMessage = ex.Message;
|
||||
LOG.Error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return exportInformation;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,11 +32,13 @@ using GreenshotPlugin.Interfaces.Plugin;
|
|||
using Microsoft.Office.Interop.Outlook;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Greenshot.Plugin.Office.Destinations {
|
||||
namespace Greenshot.Plugin.Office.Destinations
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of OutlookDestination.
|
||||
/// </summary>
|
||||
public class OutlookDestination : AbstractDestination {
|
||||
public class OutlookDestination : AbstractDestination
|
||||
{
|
||||
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(OutlookDestination));
|
||||
private const int IconApplication = 0;
|
||||
private const int IconMeeting = 2;
|
||||
|
@ -50,17 +52,25 @@ namespace Greenshot.Plugin.Office.Destinations {
|
|||
private readonly OlObjectClass _outlookInspectorType;
|
||||
private readonly OutlookEmailExporter _outlookEmailExporter = new();
|
||||
|
||||
static OutlookDestination() {
|
||||
if (HasOutlook()) {
|
||||
static OutlookDestination()
|
||||
{
|
||||
if (HasOutlook())
|
||||
{
|
||||
IsActiveFlag = true;
|
||||
}
|
||||
|
||||
ExePath = PluginUtils.GetExePath("OUTLOOK.EXE");
|
||||
if (ExePath != null && File.Exists(ExePath)) {
|
||||
if (ExePath != null && File.Exists(ExePath))
|
||||
{
|
||||
WindowDetails.AddProcessToExcludeFromFreeze("outlook");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ExePath = GetOutlookExePath();
|
||||
}
|
||||
if (ExePath == null) {
|
||||
|
||||
if (ExePath == null)
|
||||
{
|
||||
IsActiveFlag = false;
|
||||
}
|
||||
}
|
||||
|
@ -79,13 +89,16 @@ namespace Greenshot.Plugin.Office.Destinations {
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return File.Exists(outlookPath);
|
||||
}
|
||||
|
||||
public OutlookDestination() {
|
||||
public OutlookDestination()
|
||||
{
|
||||
}
|
||||
|
||||
public OutlookDestination(string outlookInspectorCaption, OlObjectClass outlookInspectorType) {
|
||||
public OutlookDestination(string outlookInspectorCaption, OlObjectClass outlookInspectorType)
|
||||
{
|
||||
_outlookInspectorCaption = outlookInspectorCaption;
|
||||
_outlookInspectorType = outlookInspectorType;
|
||||
}
|
||||
|
@ -102,25 +115,32 @@ namespace Greenshot.Plugin.Office.Destinations {
|
|||
|
||||
public override Keys EditorShortcutKeys => Keys.Control | Keys.E;
|
||||
|
||||
public override Image DisplayIcon {
|
||||
public override Image DisplayIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_outlookInspectorCaption == null)
|
||||
{
|
||||
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!
|
||||
return PluginUtils.GetCachedExeIcon(ExePath, IconMeeting);
|
||||
}
|
||||
|
||||
return MailIcon;
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<IDestination> DynamicDestinations() {
|
||||
public override IEnumerable<IDestination> DynamicDestinations()
|
||||
{
|
||||
IDictionary<string, OlObjectClass> inspectorCaptions = _outlookEmailExporter.RetrievePossibleTargets();
|
||||
if (inspectorCaptions != null) {
|
||||
foreach (string inspectorCaption in inspectorCaptions.Keys) {
|
||||
if (inspectorCaptions != null)
|
||||
{
|
||||
foreach (string inspectorCaption in inspectorCaptions.Keys)
|
||||
{
|
||||
yield return new OutlookDestination(inspectorCaption, inspectorCaptions[inspectorCaption]);
|
||||
}
|
||||
}
|
||||
|
@ -133,49 +153,69 @@ namespace Greenshot.Plugin.Office.Destinations {
|
|||
/// <param name="surface"></param>
|
||||
/// <param name="captureDetails"></param>
|
||||
/// <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);
|
||||
// Outlook logic
|
||||
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());
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.InfoFormat("Using already available file: {0}", tmpFile);
|
||||
}
|
||||
|
||||
// Create a attachment name for the image
|
||||
string attachmentName = captureDetails.Title;
|
||||
if (!string.IsNullOrEmpty(attachmentName)) {
|
||||
if (!string.IsNullOrEmpty(attachmentName))
|
||||
{
|
||||
attachmentName = attachmentName.Trim();
|
||||
}
|
||||
|
||||
// Set default if non is set
|
||||
if (string.IsNullOrEmpty(attachmentName)) {
|
||||
if (string.IsNullOrEmpty(attachmentName))
|
||||
{
|
||||
attachmentName = "Greenshot Capture";
|
||||
}
|
||||
|
||||
// Make sure it's "clean" so it doesn't corrupt the header
|
||||
attachmentName = Regex.Replace(attachmentName, @"[^\x20\d\w]", string.Empty);
|
||||
|
||||
if (_outlookInspectorCaption != null) {
|
||||
if (_outlookInspectorCaption != null)
|
||||
{
|
||||
_outlookEmailExporter.ExportToInspector(_outlookInspectorCaption, tmpFile, attachmentName);
|
||||
exportInformation.ExportMade = true;
|
||||
} else {
|
||||
if (!manuallyInitiated) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!manuallyInitiated)
|
||||
{
|
||||
var inspectorCaptions = _outlookEmailExporter.RetrievePossibleTargets();
|
||||
if (inspectorCaptions != null && inspectorCaptions.Count > 0) {
|
||||
if (inspectorCaptions != null && inspectorCaptions.Count > 0)
|
||||
{
|
||||
var destinations = new List<IDestination>
|
||||
{
|
||||
new OutlookDestination()
|
||||
};
|
||||
foreach (string inspectorCaption in inspectorCaptions.Keys) {
|
||||
foreach (string inspectorCaption in inspectorCaptions.Keys)
|
||||
{
|
||||
destinations.Add(new OutlookDestination(inspectorCaption, inspectorCaptions[inspectorCaption]));
|
||||
}
|
||||
|
||||
// Return the ExportInformation from the picker without processing, as this indirectly comes from us self
|
||||
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);
|
||||
return exportInformation;
|
||||
}
|
||||
|
|
|
@ -29,11 +29,13 @@ using GreenshotPlugin.Core;
|
|||
using GreenshotPlugin.Interfaces;
|
||||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
|
||||
namespace Greenshot.Plugin.Office.Destinations {
|
||||
namespace Greenshot.Plugin.Office.Destinations
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of PowerpointDestination.
|
||||
/// </summary>
|
||||
public class PowerpointDestination : AbstractDestination {
|
||||
public class PowerpointDestination : AbstractDestination
|
||||
{
|
||||
private const int IconApplication = 0;
|
||||
private const int IconPresentation = 1;
|
||||
|
||||
|
@ -41,30 +43,39 @@ namespace Greenshot.Plugin.Office.Destinations {
|
|||
private readonly string _presentationName;
|
||||
private readonly PowerpointExporter _powerpointExporter = new PowerpointExporter();
|
||||
|
||||
static PowerpointDestination() {
|
||||
static PowerpointDestination()
|
||||
{
|
||||
ExePath = PluginUtils.GetExePath("POWERPNT.EXE");
|
||||
if (ExePath != null && File.Exists(ExePath)) {
|
||||
if (ExePath != null && File.Exists(ExePath))
|
||||
{
|
||||
WindowDetails.AddProcessToExcludeFromFreeze("powerpnt");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ExePath = null;
|
||||
}
|
||||
}
|
||||
|
||||
public PowerpointDestination() {
|
||||
public PowerpointDestination()
|
||||
{
|
||||
}
|
||||
|
||||
public PowerpointDestination(string presentationName) {
|
||||
public PowerpointDestination(string presentationName)
|
||||
{
|
||||
_presentationName = presentationName;
|
||||
}
|
||||
|
||||
public override string Designation => "Powerpoint";
|
||||
|
||||
public override string Description {
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_presentationName == null) {
|
||||
if (_presentationName == null)
|
||||
{
|
||||
return "Microsoft Powerpoint";
|
||||
}
|
||||
|
||||
return _presentationName;
|
||||
}
|
||||
}
|
||||
|
@ -75,9 +86,12 @@ namespace Greenshot.Plugin.Office.Destinations {
|
|||
|
||||
public override bool IsActive => base.IsActive && ExePath != null;
|
||||
|
||||
public override Image DisplayIcon {
|
||||
get {
|
||||
if (!string.IsNullOrEmpty(_presentationName)) {
|
||||
public override Image DisplayIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_presentationName))
|
||||
{
|
||||
return PluginUtils.GetCachedExeIcon(ExePath, IconPresentation);
|
||||
}
|
||||
|
||||
|
@ -85,37 +99,55 @@ namespace Greenshot.Plugin.Office.Destinations {
|
|||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<IDestination> DynamicDestinations() {
|
||||
foreach (string presentationName in _powerpointExporter.GetPowerpointPresentations()) {
|
||||
public override IEnumerable<IDestination> DynamicDestinations()
|
||||
{
|
||||
foreach (string presentationName in _powerpointExporter.GetPowerpointPresentations())
|
||||
{
|
||||
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);
|
||||
string tmpFile = captureDetails.Filename;
|
||||
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());
|
||||
imageSize = surface.Image.Size;
|
||||
}
|
||||
if (_presentationName != null) {
|
||||
|
||||
if (_presentationName != null)
|
||||
{
|
||||
exportInformation.ExportMade = _powerpointExporter.ExportToPresentation(_presentationName, tmpFile, imageSize, captureDetails.Title);
|
||||
} else {
|
||||
if (!manuallyInitiated) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!manuallyInitiated)
|
||||
{
|
||||
var presentations = _powerpointExporter.GetPowerpointPresentations().ToList();
|
||||
if (presentations != null && presentations.Count > 0) {
|
||||
var destinations = new List<IDestination> {new PowerpointDestination()};
|
||||
foreach (string presentation in presentations) {
|
||||
if (presentations != null && presentations.Count > 0)
|
||||
{
|
||||
var destinations = new List<IDestination>
|
||||
{
|
||||
new PowerpointDestination()
|
||||
};
|
||||
foreach (string presentation in presentations)
|
||||
{
|
||||
destinations.Add(new PowerpointDestination(presentation));
|
||||
}
|
||||
|
||||
// Return the ExportInformation from the picker without processing, as this indirectly comes from us self
|
||||
return ShowPickerMenu(false, surface, captureDetails, destinations);
|
||||
}
|
||||
} else if (!exportInformation.ExportMade) {
|
||||
}
|
||||
else if (!exportInformation.ExportMade)
|
||||
{
|
||||
exportInformation.ExportMade = _powerpointExporter.InsertIntoNewPresentation(tmpFile, imageSize, captureDetails.Title);
|
||||
}
|
||||
}
|
||||
|
||||
ProcessExport(exportInformation, surface);
|
||||
return exportInformation;
|
||||
}
|
||||
|
|
|
@ -30,29 +30,35 @@ using GreenshotPlugin.Core;
|
|||
using GreenshotPlugin.Interfaces;
|
||||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
|
||||
namespace Greenshot.Plugin.Office.Destinations {
|
||||
namespace Greenshot.Plugin.Office.Destinations
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of EmailDestination.
|
||||
/// </summary>
|
||||
public class WordDestination : AbstractDestination {
|
||||
public class WordDestination : AbstractDestination
|
||||
{
|
||||
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(WordDestination));
|
||||
private const int IconApplication = 0;
|
||||
private const int IconDocument = 1;
|
||||
private static readonly string ExePath;
|
||||
private readonly string _documentCaption;
|
||||
private readonly WordExporter _wordExporter = new WordExporter();
|
||||
static WordDestination() {
|
||||
|
||||
static WordDestination()
|
||||
{
|
||||
ExePath = PluginUtils.GetExePath("WINWORD.EXE");
|
||||
if (ExePath != null && !File.Exists(ExePath)) {
|
||||
if (ExePath != null && !File.Exists(ExePath))
|
||||
{
|
||||
ExePath = null;
|
||||
}
|
||||
}
|
||||
|
||||
public WordDestination() {
|
||||
|
||||
public WordDestination()
|
||||
{
|
||||
}
|
||||
|
||||
public WordDestination(string wordCaption) {
|
||||
public WordDestination(string 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 IEnumerable<IDestination> DynamicDestinations() {
|
||||
foreach (string wordCaption in _wordExporter.GetWordDocuments()) {
|
||||
public override IEnumerable<IDestination> DynamicDestinations()
|
||||
{
|
||||
foreach (string wordCaption in _wordExporter.GetWordDocuments())
|
||||
{
|
||||
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);
|
||||
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());
|
||||
}
|
||||
if (_documentCaption != null) {
|
||||
try {
|
||||
|
||||
if (_documentCaption != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_wordExporter.InsertIntoExistingDocument(_documentCaption, tmpFile);
|
||||
exportInformation.ExportMade = true;
|
||||
} catch (Exception) {
|
||||
try {
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
_wordExporter.InsertIntoExistingDocument(_documentCaption, tmpFile);
|
||||
exportInformation.ExportMade = true;
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex);
|
||||
// TODO: Change to general logic in ProcessExport
|
||||
surface.SendMessageEvent(this, SurfaceMessageTyp.Error, Language.GetFormattedString("destination_exportfailed", Description));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!manuallyInitiated) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!manuallyInitiated)
|
||||
{
|
||||
var documents = _wordExporter.GetWordDocuments().ToList();
|
||||
if (documents != null && documents.Count > 0) {
|
||||
if (documents != null && documents.Count > 0)
|
||||
{
|
||||
var destinations = new List<IDestination>
|
||||
{
|
||||
new WordDestination()
|
||||
};
|
||||
foreach (string document in documents) {
|
||||
foreach (string document in documents)
|
||||
{
|
||||
destinations.Add(new WordDestination(document));
|
||||
}
|
||||
|
||||
// Return the ExportInformation from the picker without processing, as this indirectly comes from us self
|
||||
return ShowPickerMenu(false, surface, captureDetails, destinations);
|
||||
}
|
||||
}
|
||||
try {
|
||||
|
||||
try
|
||||
{
|
||||
_wordExporter.InsertIntoNewDocument(tmpFile, null, null);
|
||||
exportInformation.ExportMade = true;
|
||||
} catch(Exception) {
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Retry once, just in case
|
||||
try {
|
||||
try
|
||||
{
|
||||
_wordExporter.InsertIntoNewDocument(tmpFile, null, null);
|
||||
exportInformation.ExportMade = true;
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex);
|
||||
// TODO: Change to general logic in ProcessExport
|
||||
surface.SendMessageEvent(this, SurfaceMessageTyp.Error, Language.GetFormattedString("destination_exportfailed", Description));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProcessExport(exportInformation, surface);
|
||||
return exportInformation;
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -23,32 +23,40 @@ using Greenshot.Plugin.Office.OfficeInterop;
|
|||
using GreenshotPlugin.IniFile;
|
||||
using Microsoft.Office.Interop.PowerPoint;
|
||||
|
||||
namespace Greenshot.Plugin.Office {
|
||||
|
||||
namespace Greenshot.Plugin.Office
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of CoreConfiguration.
|
||||
/// </summary>
|
||||
[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")]
|
||||
public EmailFormat OutlookEmailFormat { get; set; }
|
||||
|
||||
[IniProperty("EmailSubjectPattern", Description = "Email subject pattern, works like the OutputFileFilenamePattern", DefaultValue = "${title}")]
|
||||
public string EmailSubjectPattern { get; set; }
|
||||
|
||||
[IniProperty("EmailTo", Description = "Default value for the to in emails that are created", DefaultValue = "")]
|
||||
public string EmailTo { get; set; }
|
||||
|
||||
[IniProperty("EmailCC", Description = "Default value for the CC in emails that are created", DefaultValue = "")]
|
||||
public string EmailCC { get; set; }
|
||||
|
||||
[IniProperty("EmailBCC", Description = "Default value for the BCC in emails that are created", DefaultValue = "")]
|
||||
public string EmailBCC { get; set; }
|
||||
|
||||
[IniProperty("OutlookAllowExportInMeetings", Description = "For Outlook: Allow export in meeting items", DefaultValue = "False")]
|
||||
public bool OutlookAllowExportInMeetings { get; set; }
|
||||
|
||||
[IniProperty("WordLockAspectRatio", Description = "For Word: Lock the aspect ratio of the image", DefaultValue = "True")]
|
||||
public bool WordLockAspectRatio { get; set; }
|
||||
|
||||
[IniProperty("PowerpointLockAspectRatio", Description = "For Powerpoint: Lock the aspect ratio of the image", DefaultValue = "True")]
|
||||
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; }
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@ namespace Greenshot.Plugin.Office.OfficeExport.Entities
|
|||
{
|
||||
return string.Format("{0} / {1}", Parent.Name, Name);
|
||||
}
|
||||
|
||||
return string.Format("{0} / {1} / {2}", Parent.Parent.Name, Parent.Name, Name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,10 +53,12 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
// Ignore, probably no excel running
|
||||
return null;
|
||||
}
|
||||
|
||||
if (excelApplication?.ComObject != null)
|
||||
{
|
||||
InitializeVariables(excelApplication);
|
||||
}
|
||||
|
||||
return excelApplication;
|
||||
}
|
||||
|
||||
|
@ -71,6 +73,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
excelApplication = DisposableCom.Create(new Application());
|
||||
}
|
||||
|
||||
InitializeVariables(excelApplication);
|
||||
return excelApplication;
|
||||
}
|
||||
|
@ -108,6 +111,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Version.TryParse(excelApplication.ComObject.Version, out _excelVersion))
|
||||
{
|
||||
LOG.Warn("Assuming Excel version 1997.");
|
||||
|
@ -195,5 +199,4 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
InsertIntoExistingWorkbook(workbook, tmpFile, imageSize);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -38,7 +38,10 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
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 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 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);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -126,6 +130,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
// Ignore, probably no OneNote running
|
||||
return null;
|
||||
}
|
||||
|
||||
return oneNoteApplication;
|
||||
}
|
||||
|
||||
|
@ -140,6 +145,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
oneNoteApplication = DisposableCom.Create(new Application());
|
||||
}
|
||||
|
||||
return oneNoteApplication;
|
||||
}
|
||||
|
||||
|
@ -183,6 +189,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
if ("one:Section".Equals(xmlReader.Name))
|
||||
{
|
||||
string id = xmlReader.GetAttribute("ID");
|
||||
|
@ -196,6 +203,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
if ("one:Page".Equals(xmlReader.Name))
|
||||
{
|
||||
// Skip deleted items
|
||||
|
@ -214,6 +222,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
page.IsCurrentlyViewed = "true".Equals(xmlReader.GetAttribute("isCurrentlyViewed"));
|
||||
pages.Add(page);
|
||||
}
|
||||
|
@ -233,20 +242,24 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
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);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.Warn("Problem retrieving onenote destinations, ignoring: ", ex);
|
||||
}
|
||||
|
||||
pages.Sort((page1, page2) =>
|
||||
{
|
||||
if (page1.IsCurrentlyViewed || page2.IsCurrentlyViewed)
|
||||
{
|
||||
return page2.IsCurrentlyViewed.CompareTo(page1.IsCurrentlyViewed);
|
||||
}
|
||||
|
||||
return string.Compare(page1.DisplayName, page2.DisplayName, StringComparison.Ordinal);
|
||||
});
|
||||
return pages;
|
||||
|
@ -264,6 +277,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// ReSharper disable once RedundantAssignment
|
||||
string unfiledNotesPath = "";
|
||||
oneNoteApplication.ComObject.GetSpecialLocation(specialLocation, out unfiledNotesPath);
|
||||
|
@ -285,6 +299,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string id = xmlReader.GetAttribute("ID");
|
||||
string path = xmlReader.GetAttribute("path");
|
||||
if (unfiledNotesPath.Equals(path))
|
||||
|
@ -301,6 +316,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 AccountKey = "9375CFF0413111d3B88A00104B2A6676";
|
||||
private const string NewSignatureValue = "New Signature";
|
||||
|
||||
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
|
||||
private const string AttachmentContentId = @"http://schemas.microsoft.com/mapi/proptag/0x3712001E";
|
||||
|
||||
|
@ -90,6 +92,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
return ExportToInspector(null, activeExplorer, mailItem.Class, mailItem, tmpFile, attachmentName);
|
||||
}
|
||||
|
||||
break;
|
||||
case AppointmentItem appointmentItem:
|
||||
if ((_outlookVersion.Major >= (int) OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
|
||||
|
@ -99,6 +102,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
return ExportToInspector(null, activeExplorer, appointmentItem.Class, null, tmpFile, attachmentName);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -110,6 +114,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG.DebugFormat("Got {0} inspectors to check", inspectors.ComObject.Count);
|
||||
for (int i = 1; i <= inspectors.ComObject.Count; i++)
|
||||
{
|
||||
|
@ -130,6 +135,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return ExportToInspector(inspector, null, mailItem.Class, mailItem, tmpFile, attachmentName);
|
||||
|
@ -138,6 +144,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
LOG.Error($"Export to {currentCaption} failed.", exExport);
|
||||
}
|
||||
|
||||
break;
|
||||
case AppointmentItem appointmentItem:
|
||||
if ((_outlookVersion.Major >= (int) OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
|
||||
|
@ -153,6 +160,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
// skip, can't export to olAppointment
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
|
@ -168,6 +177,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -181,7 +191,8 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
/// <param name="explorer"></param>
|
||||
/// <param name="itemClass"></param>
|
||||
/// <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 isAppointment = OlObjectClass.olAppointment.Equals(itemClass);
|
||||
|
@ -190,6 +201,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
LOG.Warn("Item is no mail or appointment.");
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Make sure the inspector is activated, only this way the word editor is active!
|
||||
|
@ -200,6 +212,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
isTextFormat = OlBodyFormat.olFormatPlain.Equals(mailItem.BodyFormat);
|
||||
}
|
||||
|
||||
if (isAppointment || !isTextFormat)
|
||||
{
|
||||
// Check for wordmail, if so use the wordexporter
|
||||
|
@ -219,6 +232,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
wordDocument = DisposableCom.Create(tmpWordDocument);
|
||||
}
|
||||
}
|
||||
|
||||
if (wordDocument != null)
|
||||
{
|
||||
using (wordDocument)
|
||||
|
@ -248,6 +262,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
LOG.Info("Trying export for outlook < 2007.");
|
||||
}
|
||||
}
|
||||
|
||||
// Only use mailitem as it should be filled!!
|
||||
if (mailItem != null)
|
||||
{
|
||||
|
@ -341,9 +356,11 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
caption = explorer.ComObject.Caption;
|
||||
}
|
||||
|
||||
LOG.Warn($"Problem while trying to add attachment to Item '{caption}'", ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (inspector != null)
|
||||
|
@ -360,6 +377,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
LOG.Warn("Problem activating inspector/explorer: ", ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG.Debug("Finished!");
|
||||
return true;
|
||||
}
|
||||
|
@ -376,27 +394,32 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
/// <param name="cc"></param>
|
||||
/// <param name="bcc"></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));
|
||||
if (newItem == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var newMail = newItem.ComObject;
|
||||
newMail.Subject = subject;
|
||||
if (!string.IsNullOrEmpty(to))
|
||||
{
|
||||
newMail.To = to;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(cc))
|
||||
{
|
||||
newMail.CC = cc;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(bcc))
|
||||
{
|
||||
newMail.BCC = bcc;
|
||||
}
|
||||
|
||||
newMail.BodyFormat = OlBodyFormat.olFormatHTML;
|
||||
string bodyString = null;
|
||||
// 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);
|
||||
}
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case EmailFormat.Text:
|
||||
|
@ -421,9 +445,11 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
bodyString = "";
|
||||
}
|
||||
|
||||
newMail.Body = bodyString;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
string contentId = Path.GetFileName(tmpFile);
|
||||
|
@ -456,6 +482,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
href = $"<A HREF=\"{url}\">";
|
||||
hrefEnd = "</A>";
|
||||
}
|
||||
|
||||
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>";
|
||||
if (bodyString == null)
|
||||
|
@ -482,9 +509,11 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
bodyString = fallbackBody;
|
||||
}
|
||||
}
|
||||
|
||||
newMail.HTMLBody = bodyString;
|
||||
break;
|
||||
}
|
||||
|
||||
// So not save, otherwise the email is always stored in Draft folder.. (newMail.Save();)
|
||||
newMail.Display(false);
|
||||
|
||||
|
@ -528,12 +557,14 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
exported = true;
|
||||
}
|
||||
}
|
||||
|
||||
return exported;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.Error("Error while creating an outlook mail item: ", e);
|
||||
}
|
||||
|
||||
return exported;
|
||||
}
|
||||
|
||||
|
@ -548,6 +579,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
outlookApplication = DisposableCom.Create(new Application());
|
||||
}
|
||||
|
||||
InitializeVariables(outlookApplication);
|
||||
return outlookApplication;
|
||||
}
|
||||
|
@ -568,10 +600,12 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
// Ignore, probably no outlook running
|
||||
return null;
|
||||
}
|
||||
|
||||
if ((outlookApplication != null) && (outlookApplication.ComObject != null))
|
||||
{
|
||||
InitializeVariables(outlookApplication);
|
||||
}
|
||||
|
||||
return outlookApplication;
|
||||
}
|
||||
|
||||
|
@ -587,6 +621,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string defaultProfile = (string) profilesKey.GetValue(DefaultProfileValue);
|
||||
LOG.DebugFormat("defaultProfile={0}", defaultProfile);
|
||||
using var profileKey = profilesKey.OpenSubKey(defaultProfile + @"\" + AccountKey, false);
|
||||
|
@ -604,6 +639,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string signatureName = "";
|
||||
foreach (byte b in val)
|
||||
{
|
||||
|
@ -612,6 +648,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
signatureName += (char) b;
|
||||
}
|
||||
}
|
||||
|
||||
LOG.DebugFormat("Found email signature: {0}", signatureName);
|
||||
var extension = format switch
|
||||
{
|
||||
|
@ -628,6 +665,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -642,11 +680,13 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Version.TryParse(outlookApplication.ComObject.Version, out _outlookVersion))
|
||||
{
|
||||
LOG.Warn("Assuming outlook version 1997.");
|
||||
_outlookVersion = new Version((int) OfficeVersions.Office97, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Preventing retrieval of currentUser if Outlook is older than 2007
|
||||
if (_outlookVersion.Major >= (int) OfficeVersions.Office2007)
|
||||
{
|
||||
|
@ -657,6 +697,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
using var currentUser = DisposableCom.Create(mapiNamespace.ComObject.CurrentUser);
|
||||
_currentUser = currentUser.ComObject.Name;
|
||||
}
|
||||
|
||||
LOG.InfoFormat("Current user: {0}", _currentUser);
|
||||
}
|
||||
catch (Exception exNs)
|
||||
|
@ -701,6 +742,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
inspectorCaptions.Add(caption, mailItem.Class);
|
||||
}
|
||||
|
||||
break;
|
||||
case AppointmentItem appointmentItem:
|
||||
if ((_outlookVersion.Major >= (int) OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
|
||||
|
@ -710,6 +752,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
inspectorCaptions.Add(caption, appointmentItem.Class);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -740,6 +783,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
inspectorCaptions.Add(caption, mailItem.Class);
|
||||
break;
|
||||
case AppointmentItem appointmentItem:
|
||||
|
@ -756,6 +800,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
// skip, can't export to olAppointment
|
||||
continue;
|
||||
}
|
||||
|
||||
inspectorCaptions.Add(caption, appointmentItem.Class);
|
||||
break;
|
||||
default:
|
||||
|
@ -769,6 +814,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
LOG.Warn("Problem retrieving word destinations, ignoring: ", ex);
|
||||
}
|
||||
|
||||
return inspectorCaptions;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
left = pageSetup.ComObject.SlideWidth / 2 - imageSize.Width / 2f;
|
||||
top = pageSetup.ComObject.SlideHeight / 2 - imageSize.Height / 2f;
|
||||
}
|
||||
|
||||
float width = imageSize.Width;
|
||||
float height = imageSize.Height;
|
||||
IDisposableCom<Shape> shapeForCaption = null;
|
||||
|
@ -86,6 +87,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
shapeForLocation.ComObject.Left = left;
|
||||
}
|
||||
|
||||
shapeForLocation.ComObject.Width = imageSize.Width;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
shapeForLocation.ComObject.Height = imageSize.Height;
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -106,6 +109,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
using var slides = DisposableCom.Create(presentation.ComObject.Slides);
|
||||
slide = DisposableCom.Create(slides.ComObject.Add(slides.ComObject.Count + 1, PpSlideLayout.ppLayoutBlank));
|
||||
}
|
||||
|
||||
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));
|
||||
|
@ -117,20 +121,24 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
shape.ComObject.LockAspectRatio = MsoTriState.msoFalse;
|
||||
}
|
||||
|
||||
shape.ComObject.ScaleHeight(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromMiddle);
|
||||
shape.ComObject.ScaleWidth(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromMiddle);
|
||||
if (hasScaledWidth)
|
||||
{
|
||||
shape.ComObject.Width = width;
|
||||
}
|
||||
|
||||
if (hasScaledHeight)
|
||||
{
|
||||
shape.ComObject.Height = height;
|
||||
}
|
||||
|
||||
shape.ComObject.Left = left;
|
||||
shape.ComObject.Top = top;
|
||||
shape.ComObject.AlternativeText = title;
|
||||
}
|
||||
|
||||
if (shapeForCaption != null)
|
||||
{
|
||||
try
|
||||
|
@ -148,6 +156,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
LOG.Warn("Problem setting the title to a text-range", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Activate/Goto the slide
|
||||
try
|
||||
{
|
||||
|
@ -194,10 +203,12 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!presentation.ComObject.Name.StartsWith(presentationName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
AddPictureToPresentation(presentation, tmpFile, imageSize, title);
|
||||
|
@ -209,6 +220,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -223,6 +235,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
powerPointApplication = DisposableCom.Create(new Application());
|
||||
}
|
||||
|
||||
InitializeVariables(powerPointApplication);
|
||||
return powerPointApplication;
|
||||
}
|
||||
|
@ -243,10 +256,12 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
// Ignore, probably no PowerPoint running
|
||||
return null;
|
||||
}
|
||||
|
||||
if (powerPointApplication?.ComObject != null)
|
||||
{
|
||||
InitializeVariables(powerPointApplication);
|
||||
}
|
||||
|
||||
return powerPointApplication;
|
||||
}
|
||||
|
||||
|
@ -271,10 +286,12 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (presentation.ComObject.ReadOnly == MsoTriState.msoTrue)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsAfter2003())
|
||||
{
|
||||
if (presentation.ComObject.Final)
|
||||
|
@ -282,6 +299,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
yield return presentation.ComObject.Name;
|
||||
}
|
||||
}
|
||||
|
@ -296,6 +314,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Version.TryParse(powerpointApplication.ComObject.Version, out _powerpointVersion))
|
||||
{
|
||||
LOG.Warn("Assuming Powerpoint version 1997.");
|
||||
|
@ -332,6 +351,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isPictureAdded;
|
||||
}
|
||||
|
||||
|
@ -340,5 +360,4 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
return _powerpointVersion.Major > (int) OfficeVersions.Office2003;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -53,6 +53,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
shape.ComObject.LockAspectRatio = MsoTriState.msoTrue;
|
||||
}
|
||||
|
||||
selection.ComObject.InsertAfter("\r\n");
|
||||
selection.ComObject.MoveDown(WdUnits.wdLine, 1, Type.Missing);
|
||||
return shape;
|
||||
|
@ -69,6 +70,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
wordApplication = DisposableCom.Create(new Application());
|
||||
}
|
||||
|
||||
InitializeVariables(wordApplication);
|
||||
return wordApplication;
|
||||
}
|
||||
|
@ -89,10 +91,12 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
// Ignore, probably no word running
|
||||
return null;
|
||||
}
|
||||
|
||||
if ((wordApplication != null) && (wordApplication.ComObject != null))
|
||||
{
|
||||
InitializeVariables(wordApplication);
|
||||
}
|
||||
|
||||
return wordApplication;
|
||||
}
|
||||
|
||||
|
@ -116,6 +120,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsAfter2003())
|
||||
{
|
||||
if (document.ComObject.Final)
|
||||
|
@ -139,6 +144,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Version.TryParse(wordApplication.ComObject.Version, out _wordVersion))
|
||||
{
|
||||
LOG.Warn("Assuming Word version 1997.");
|
||||
|
@ -172,6 +178,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -184,7 +191,8 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
/// <param name="address">string</param>
|
||||
/// <param name="tooltip">string with the tooltip of the image</param>
|
||||
/// <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.
|
||||
// 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);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add Picture
|
||||
using (var shape = AddPictureToSelection(selection, tmpFile))
|
||||
{
|
||||
|
@ -214,6 +223,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
screentip = tooltip;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using var hyperlinks = DisposableCom.Create(wordDocument.ComObject.Hyperlinks);
|
||||
|
@ -225,6 +235,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
wordApplication.ComObject.Activate();
|
||||
|
@ -254,6 +266,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
LOG.Warn("Error activating word application", ex);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
wordDocument.ComObject.Activate();
|
||||
|
@ -263,6 +276,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
LOG.Warn("Error activating word document", ex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -279,6 +293,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
wordApplication.ComObject.Visible = true;
|
||||
wordApplication.ComObject.Activate();
|
||||
// Create new Document
|
||||
|
@ -299,6 +314,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
screentip = tooltip;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using var hyperlinks = DisposableCom.Create(wordDocument.ComObject.Hyperlinks);
|
||||
|
@ -313,6 +329,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
wordDocument.ComObject.Activate();
|
||||
|
@ -322,6 +339,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
|
|||
{
|
||||
LOG.Warn("Error activating word document", ex);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using var activeWindow = DisposableCom.Create(wordDocument.ComObject.ActiveWindow);
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace Greenshot.Plugin.Office.OfficeInterop
|
|||
/// Use the plain text format
|
||||
/// </summary>
|
||||
Text,
|
||||
|
||||
/// <summary>
|
||||
/// Use HTML format
|
||||
/// </summary>
|
||||
|
|
|
@ -28,26 +28,32 @@ namespace Greenshot.Plugin.Office.OfficeInterop
|
|||
/// Office 97
|
||||
/// </summary>
|
||||
Office97 = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Office 2003
|
||||
/// </summary>
|
||||
Office2003 = 11,
|
||||
|
||||
/// <summary>
|
||||
/// Office 2007
|
||||
/// </summary>
|
||||
Office2007 = 12,
|
||||
|
||||
/// <summary>
|
||||
/// Office 2010
|
||||
/// </summary>
|
||||
Office2010 = 14,
|
||||
|
||||
/// <summary>
|
||||
/// Office 2013
|
||||
/// </summary>
|
||||
Office2013 = 15,
|
||||
|
||||
/// <summary>
|
||||
/// Office 2016
|
||||
/// </summary>
|
||||
Office2016 = 16,
|
||||
|
||||
/// <summary>
|
||||
/// Office 2019
|
||||
/// </summary>
|
||||
|
|
|
@ -26,7 +26,8 @@ using GreenshotPlugin.Core;
|
|||
using GreenshotPlugin.Interfaces;
|
||||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
|
||||
namespace Greenshot.Plugin.Office {
|
||||
namespace Greenshot.Plugin.Office
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the OfficePlugin base code
|
||||
/// </summary>
|
||||
|
@ -35,59 +36,87 @@ namespace Greenshot.Plugin.Office {
|
|||
{
|
||||
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OfficePlugin));
|
||||
|
||||
public void Dispose() {
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected void Dispose(bool disposing) {
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
private IEnumerable<IDestination> Destinations() {
|
||||
private IEnumerable<IDestination> Destinations()
|
||||
{
|
||||
IDestination destination;
|
||||
try {
|
||||
try
|
||||
{
|
||||
destination = new ExcelDestination();
|
||||
} catch {
|
||||
}
|
||||
catch
|
||||
{
|
||||
destination = null;
|
||||
}
|
||||
if (destination != null) {
|
||||
|
||||
if (destination != null)
|
||||
{
|
||||
yield return destination;
|
||||
}
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
destination = new PowerpointDestination();
|
||||
} catch {
|
||||
}
|
||||
catch
|
||||
{
|
||||
destination = null;
|
||||
}
|
||||
if (destination != null) {
|
||||
|
||||
if (destination != null)
|
||||
{
|
||||
yield return destination;
|
||||
}
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
destination = new WordDestination();
|
||||
} catch {
|
||||
}
|
||||
catch
|
||||
{
|
||||
destination = null;
|
||||
}
|
||||
if (destination != null) {
|
||||
|
||||
if (destination != null)
|
||||
{
|
||||
yield return destination;
|
||||
}
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
destination = new OutlookDestination();
|
||||
} catch {
|
||||
}
|
||||
catch
|
||||
{
|
||||
destination = null;
|
||||
}
|
||||
if (destination != null) {
|
||||
|
||||
if (destination != null)
|
||||
{
|
||||
yield return destination;
|
||||
}
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
destination = new OneNoteDestination();
|
||||
} catch {
|
||||
}
|
||||
catch
|
||||
{
|
||||
destination = null;
|
||||
}
|
||||
if (destination != null) {
|
||||
|
||||
if (destination != null)
|
||||
{
|
||||
yield return destination;
|
||||
}
|
||||
}
|
||||
|
@ -97,19 +126,22 @@ namespace Greenshot.Plugin.Office {
|
|||
/// Implementation of the IGreenshotPlugin.Initialize
|
||||
/// </summary>
|
||||
/// <returns>true if plugin is initialized, false if not (doesn't show)</returns>
|
||||
public bool Initialize() {
|
||||
public bool Initialize()
|
||||
{
|
||||
SimpleServiceProvider.Current.AddService(Destinations());
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Shutdown() {
|
||||
public void Shutdown()
|
||||
{
|
||||
LOG.Debug("Office Plugin shutdown.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of the IPlugin.Configure
|
||||
/// </summary>
|
||||
public void Configure() {
|
||||
public void Configure()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,10 +19,12 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Greenshot.Plugin.Photobucket.Forms {
|
||||
namespace Greenshot.Plugin.Photobucket.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is needed for design-time resolving of the language files
|
||||
/// </summary>
|
||||
public class PhotobucketForm : GreenshotPlugin.Controls.GreenshotForm {
|
||||
public class PhotobucketForm : GreenshotPlugin.Controls.GreenshotForm
|
||||
{
|
||||
}
|
||||
}
|
|
@ -19,11 +19,13 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Greenshot.Plugin.Photobucket.Forms {
|
||||
namespace Greenshot.Plugin.Photobucket.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of PasswordRequestForm.
|
||||
/// </summary>
|
||||
public partial class SettingsForm : PhotobucketForm {
|
||||
public partial class SettingsForm : PhotobucketForm
|
||||
{
|
||||
public SettingsForm()
|
||||
{
|
||||
//
|
||||
|
|
|
@ -19,8 +19,10 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Greenshot.Plugin.Photobucket {
|
||||
public enum LangKey {
|
||||
namespace Greenshot.Plugin.Photobucket
|
||||
{
|
||||
public enum LangKey
|
||||
{
|
||||
upload_menu_item,
|
||||
upload_failure,
|
||||
communication_wait,
|
||||
|
|
|
@ -25,26 +25,35 @@ using GreenshotPlugin.Controls;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.IniFile;
|
||||
|
||||
namespace Greenshot.Plugin.Photobucket {
|
||||
namespace Greenshot.Plugin.Photobucket
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of PhotobucketConfiguration.
|
||||
/// </summary>
|
||||
[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")]
|
||||
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("UsePageLink", Description = "Use pagelink instead of direct link on the clipboard", DefaultValue = "False")]
|
||||
public bool UsePageLink { get; set; }
|
||||
|
||||
[IniProperty("Token", Description = "The Photobucket token", Encrypted = true, ExcludeIfNull = true)]
|
||||
public string Token { get; set; }
|
||||
|
||||
[IniProperty("TokenSecret", Description = "The Photobucket token secret", Encrypted = true, ExcludeIfNull = true)]
|
||||
public string TokenSecret { get; set; }
|
||||
|
||||
[IniProperty("SubDomain", Description = "The Photobucket api subdomain", Encrypted = true, ExcludeIfNull = true)]
|
||||
public string SubDomain { get; set; }
|
||||
|
||||
[IniProperty("Username", Description = "The Photobucket api username", ExcludeIfNull = true)]
|
||||
public string Username { get; set; }
|
||||
|
||||
|
@ -52,18 +61,19 @@ namespace Greenshot.Plugin.Photobucket {
|
|||
/// A form for username/password
|
||||
/// </summary>
|
||||
/// <returns>bool true if OK was pressed, false if cancel</returns>
|
||||
public bool ShowConfigDialog() {
|
||||
public bool ShowConfigDialog()
|
||||
{
|
||||
SettingsForm settingsForm = null;
|
||||
|
||||
new PleaseWaitForm().ShowAndWait("Photobucket", Language.GetString("photobucket", LangKey.communication_wait),
|
||||
delegate {
|
||||
settingsForm = new SettingsForm();
|
||||
}
|
||||
delegate { settingsForm = new SettingsForm(); }
|
||||
);
|
||||
DialogResult result = settingsForm.ShowDialog();
|
||||
if (result == DialogResult.OK) {
|
||||
if (result == DialogResult.OK)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,11 +25,13 @@ using System.Drawing;
|
|||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.Interfaces;
|
||||
|
||||
namespace Greenshot.Plugin.Photobucket {
|
||||
namespace Greenshot.Plugin.Photobucket
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of PhotobucketDestination.
|
||||
/// </summary>
|
||||
public class PhotobucketDestination : AbstractDestination {
|
||||
public class PhotobucketDestination : AbstractDestination
|
||||
{
|
||||
private readonly PhotobucketPlugin _plugin;
|
||||
private readonly string _albumPath;
|
||||
|
||||
|
@ -38,24 +40,31 @@ namespace Greenshot.Plugin.Photobucket {
|
|||
/// </summary>
|
||||
/// <param name="plugin"></param>
|
||||
/// <param name="albumPath">path to the album, null for default</param>
|
||||
public PhotobucketDestination(PhotobucketPlugin plugin, string albumPath = null) {
|
||||
public PhotobucketDestination(PhotobucketPlugin plugin, string albumPath = null)
|
||||
{
|
||||
_plugin = plugin;
|
||||
_albumPath = albumPath;
|
||||
}
|
||||
|
||||
public override string Designation => "Photobucket";
|
||||
|
||||
public override string Description {
|
||||
get {
|
||||
if (_albumPath != null) {
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_albumPath != null)
|
||||
{
|
||||
return _albumPath;
|
||||
}
|
||||
|
||||
return Language.GetString("photobucket", LangKey.upload_menu_item);
|
||||
}
|
||||
}
|
||||
|
||||
public override Image DisplayIcon {
|
||||
get {
|
||||
public override Image DisplayIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
ComponentResourceManager resources = new ComponentResourceManager(typeof(PhotobucketPlugin));
|
||||
return (Image) resources.GetObject("Photobucket");
|
||||
}
|
||||
|
@ -63,9 +72,11 @@ namespace Greenshot.Plugin.Photobucket {
|
|||
|
||||
public override bool IsDynamic => true;
|
||||
|
||||
public override IEnumerable<IDestination> DynamicDestinations() {
|
||||
public override IEnumerable<IDestination> DynamicDestinations()
|
||||
{
|
||||
IList<string> albums = null;
|
||||
try {
|
||||
try
|
||||
{
|
||||
albums = PhotobucketUtils.RetrievePhotobucketAlbums();
|
||||
}
|
||||
catch
|
||||
|
@ -73,10 +84,13 @@ namespace Greenshot.Plugin.Photobucket {
|
|||
// ignored
|
||||
}
|
||||
|
||||
if (albums == null || albums.Count == 0) {
|
||||
if (albums == null || albums.Count == 0)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
foreach (string album in albums) {
|
||||
|
||||
foreach (string album in albums)
|
||||
{
|
||||
yield return new PhotobucketDestination(_plugin, album);
|
||||
}
|
||||
}
|
||||
|
@ -88,13 +102,16 @@ namespace Greenshot.Plugin.Photobucket {
|
|||
/// <param name="surface"></param>
|
||||
/// <param name="captureDetails"></param>
|
||||
/// <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);
|
||||
bool uploaded = _plugin.Upload(captureDetails, surface, _albumPath, out var uploadUrl);
|
||||
if (uploaded) {
|
||||
if (uploaded)
|
||||
{
|
||||
exportInformation.ExportMade = true;
|
||||
exportInformation.Uri = uploadUrl;
|
||||
}
|
||||
|
||||
ProcessExport(exportInformation, surface);
|
||||
return exportInformation;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,8 @@ namespace Greenshot.Plugin.Photobucket
|
|||
/// <summary>
|
||||
/// Description of PhotobucketInfo.
|
||||
/// </summary>
|
||||
public class PhotobucketInfo {
|
||||
public class PhotobucketInfo
|
||||
{
|
||||
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(PhotobucketInfo));
|
||||
|
||||
public string Original { get; set; }
|
||||
|
@ -41,27 +42,37 @@ namespace Greenshot.Plugin.Photobucket
|
|||
/// </summary>
|
||||
/// <param name="response">XML</param>
|
||||
/// <returns>PhotobucketInfo object</returns>
|
||||
public static PhotobucketInfo FromUploadResponse(string response) {
|
||||
public static PhotobucketInfo FromUploadResponse(string response)
|
||||
{
|
||||
Log.Debug(response);
|
||||
PhotobucketInfo photobucketInfo = new PhotobucketInfo();
|
||||
try {
|
||||
try
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(response);
|
||||
var nodes = doc.GetElementsByTagName("url");
|
||||
if(nodes.Count > 0) {
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
photobucketInfo.Original = nodes.Item(0)?.InnerText;
|
||||
}
|
||||
|
||||
nodes = doc.GetElementsByTagName("browseurl");
|
||||
if(nodes.Count > 0) {
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
photobucketInfo.Page = nodes.Item(0)?.InnerText;
|
||||
}
|
||||
|
||||
nodes = doc.GetElementsByTagName("thumb");
|
||||
if(nodes.Count > 0) {
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
photobucketInfo.Thumbnail = nodes.Item(0)?.InnerText;
|
||||
}
|
||||
} catch(Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.ErrorFormat("Could not parse Photobucket response due to error {0}, response was: {1}", e.Message, response);
|
||||
}
|
||||
|
||||
return photobucketInfo;
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue