Merge branch 'master' into ui_changes

Conflicts:
	Duplicati/Server/webroot/ngax/templates/edituri.html
This commit is contained in:
agrajaghh
2016-10-27 21:13:53 +02:00
35 changed files with 419 additions and 145 deletions
@@ -54,32 +54,29 @@ namespace Duplicati.GUI.TrayIcon
{
set
{
m_appIndicator.IconName = GetTrayIconFilename(value);
switch(value)
{
case TrayIcons.Paused:
m_appIndicator.IconName = "normal-pause";
m_appIndicator.IconDesc = "Paused";
break;
case TrayIcons.Running:
m_appIndicator.IconName = "normal-running";
m_appIndicator.IconDesc = "Running";
break;
case TrayIcons.IdleError:
m_appIndicator.IconName = "normal-error";
m_appIndicator.IconDesc = "Error";
break;
case TrayIcons.RunningError:
m_appIndicator.IconName = "normal-running";
break;
case TrayIcons.PausedError:
m_appIndicator.IconName = "normal-pause";
m_appIndicator.IconDesc = "Paused";
break;
case TrayIcons.Idle:
default:
m_appIndicator.IconName = "normal";
m_appIndicator.IconDesc = "Ready";
break;
case TrayIcons.Paused:
m_appIndicator.IconDesc = "Paused";
break;
case TrayIcons.Running:
m_appIndicator.IconDesc = "Running";
break;
case TrayIcons.IdleError:
m_appIndicator.IconDesc = "Error";
break;
case TrayIcons.RunningError:
m_appIndicator.IconDesc = "Running";
break;
case TrayIcons.PausedError:
m_appIndicator.IconDesc = "Paused";
break;
case TrayIcons.Idle:
default:
m_appIndicator.IconDesc = "Ready";
break;
}
}
}
@@ -372,5 +372,29 @@
<Link>OSXTrayHost\rumps.py</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="SVGIcons\dark\context_menu_open.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="SVGIcons\dark\context_menu_pause.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="SVGIcons\dark\context_menu_quit.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="SVGIcons\dark\context_menu_resume.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="SVGIcons\light\context_menu_open.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="SVGIcons\light\context_menu_pause.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="SVGIcons\light\context_menu_quit.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="SVGIcons\light\context_menu_resume.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
@@ -24,11 +24,16 @@ namespace Duplicati.GUI.TrayIcon
{
public class GtkRunner : TrayIconBase
{
private static string m_svgfolder;
/// <summary>
/// Static constructor that ensures the Gtk environment is initialized
/// </summary>
static GtkRunner()
{
m_svgfolder = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "SVGIcons");
m_svgfolder = System.IO.Path.Combine(m_svgfolder, "dark");
Gtk.Application.Init();
}
@@ -45,34 +50,36 @@ namespace Duplicati.GUI.TrayIcon
private static Dictionary<MenuIcons, Gtk.Image> _icons = new Dictionary<MenuIcons, Gtk.Image>();
public MenuItem MenuItem { get { return m_item; } }
private string GetFilenameForIcon(MenuIcons icon)
{
switch (icon)
{
case MenuIcons.Pause:
return "context_menu_pause";
case MenuIcons.Quit:
return "context_menu_quit";
case MenuIcons.Resume:
return "context_menu_resume";
case MenuIcons.Status:
return "context_menu_open";
default:
return null;
}
}
private Gtk.Image GetIcon(MenuIcons icon)
{
if (Duplicati.Library.Utility.Utility.IsClientOSX)
return null;
if (!_icons.ContainsKey(icon))
{
switch(icon)
_icons[icon] = null;
var filename = GetFilenameForIcon(icon);
if (filename != null)
{
case MenuIcons.None:
_icons[icon] = null;
break;
case MenuIcons.Pause:
_icons[icon] = ImageToGtk(ImageLoader.Pause);
break;
case MenuIcons.Quit:
_icons[icon] = ImageToGtk(ImageLoader.CloseMenuIcon);
break;
case MenuIcons.Resume:
_icons[icon] = ImageToGtk(ImageLoader.Play);
break;
case MenuIcons.Status:
_icons[icon] = ImageToGtk(ImageLoader.StatusMenuIcon);
break;
default:
_icons[icon] = null;
break;
filename = System.IO.Path.Combine(m_svgfolder, System.IO.Path.ChangeExtension(filename, ".svg"));
if (System.IO.File.Exists(filename))
_icons[icon] = new Gtk.Image(filename);
}
}
@@ -89,9 +96,9 @@ namespace Duplicati.GUI.TrayIcon
if (!Duplicati.Library.Utility.Utility.IsClientOSX)
if (icon != MenuIcons.None) {
((ImageMenuItem)m_item).Image = GetIcon(icon);
//TODO: Not sure we should do this, it overrides policy?
m_item.ExposeEvent += DrawImageMenuItemImage;
// On some (older versions) of GDK, this hack is required
//m_item.ExposeEvent += DrawImageMenuItemImage;
}
if (subitems != null && subitems.Count > 0)
@@ -116,6 +123,7 @@ namespace Duplicati.GUI.TrayIcon
m_callback();
}
/*
/// <summary> Draw the image to the image menu item. Taken from: http://mono.1490590.n4.nabble.com/ImageMenuItem-does-not-display-the-image-Linux-platform-tp3510861p3511376.html </summary>
/// The event source. <see cref="System.Object"/>
/// The event args. <see cref="Gtk.ExposeEventArgs"/>
@@ -133,7 +141,8 @@ namespace Duplicati.GUI.TrayIcon
args.Event.Window.DrawPixbuf(mainGC, image.Pixbuf, 0, 0, r.Left + 2,
r.Top + (r.Height - image.Pixbuf.Height) / 2, -1, -1, Gdk.RgbDither.None, 0, 0);
}
}
*/
public string Text
{
@@ -176,7 +185,9 @@ namespace Duplicati.GUI.TrayIcon
protected virtual void CreateTrayInstance()
{
m_trayIcon = new StatusIcon();
// Sometimes the tray icon will not display
// if it is not created with an icon
m_trayIcon = StatusIcon.NewFromStock(Stock.About);
}
protected override void Run (string[] args)
@@ -231,33 +242,63 @@ namespace Duplicati.GUI.TrayIcon
Gtk.Image img = new Gtk.Image(stream);
return img;
}
}
}
protected static string GetTrayIconFilename(TrayIcons icon)
{
switch (icon)
{
case TrayIcons.Paused:
return "normal-pause";
case TrayIcons.Running:
return "normal-running";
case TrayIcons.IdleError:
return "normal-error";
case TrayIcons.RunningError:
return "normal-running";
case TrayIcons.PausedError:
return "normal-pause";
case TrayIcons.Idle:
default:
return "normal";
}
}
protected static Pixbuf GetIcon(TrayIcons icon)
{
if (!_images.ContainsKey(icon))
{
switch(icon)
if (Duplicati.Library.Utility.Utility.IsClientOSX)
{
case TrayIcons.Paused:
_images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.PauseIcon).ToBitmap());
break;
case TrayIcons.Running:
_images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.WorkingIcon).ToBitmap());
break;
case TrayIcons.IdleError:
_images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.ErrorIcon).ToBitmap());
break;
case TrayIcons.RunningError:
_images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.WorkingIcon).ToBitmap());
break;
case TrayIcons.PausedError:
switch (icon)
{
case TrayIcons.Paused:
_images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.PauseIcon).ToBitmap());
break;
case TrayIcons.Idle:
default:
_images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.NormalIcon).ToBitmap());
break;
break;
case TrayIcons.Running:
_images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.WorkingIcon).ToBitmap());
break;
case TrayIcons.IdleError:
_images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.ErrorIcon).ToBitmap());
break;
case TrayIcons.RunningError:
_images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.WorkingIcon).ToBitmap());
break;
case TrayIcons.PausedError:
_images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.PauseIcon).ToBitmap());
break;
case TrayIcons.Idle:
default:
_images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.NormalIcon).ToBitmap());
break;
}
}
else
{
_images[icon] = null;
var filename = System.IO.Path.Combine(m_svgfolder, System.IO.Path.ChangeExtension(GetTrayIconFilename(icon), ".svg"));
if (System.IO.File.Exists(filename))
_images[icon] = new Pixbuf(filename);
}
}
@@ -116,6 +116,7 @@ def get_input():
img = NSImage.alloc().initWithData_(data)
img.setScalesWhenResized_(True)
img.setSize_((18, 18))
img.setTemplate_(True)
app.icon = img
print "info:Image updated"
@@ -0,0 +1,13 @@
<svg id="tray_menu_icons" data-name="tray menu icons" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<defs>
<style>
.cls-1 {
fill: #65b1dd;
}
</style>
</defs>
<title>tray context menu icons</title>
<g id="show_Kopie" data-name="show Kopie">
<polygon class="cls-1" points="8 4.001 2 10.301 3.5 11.876 8 7.072 12.5 11.876 14 10.301 8 4.001"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 427 B

@@ -0,0 +1,14 @@
<svg id="tray_menu_icons" data-name="tray menu icons" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<defs>
<style>
.cls-1 {
fill: #65b1dd;
}
</style>
</defs>
<title>tray context menu icons</title>
<g id="pause_Kopie" data-name="pause Kopie">
<rect class="cls-1" x="4" y="2" width="3" height="12"/>
<rect class="cls-1" x="9" y="2" width="3" height="12"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 445 B

@@ -0,0 +1,13 @@
<svg id="tray_menu_icons" data-name="tray menu icons" xmlns="http://www.w3.org/2000/svg" width="15.997" height="16" viewBox="0 0 15.997 16">
<defs>
<style>
.cls-1 {
fill: #65b1dd;
}
</style>
</defs>
<title>tray context menu icons</title>
<g id="stop_Kopie" data-name="stop Kopie">
<polygon id="stop" class="cls-1" points="13.998 3.95 12.048 2 7.998 6.05 3.948 2 1.998 3.95 6.049 8 1.998 12.05 3.948 14 7.998 9.95 12.048 14 13.998 12.05 9.949 8 13.998 3.95"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 513 B

@@ -0,0 +1,13 @@
<svg id="tray_menu_icons" data-name="tray menu icons" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<defs>
<style>
.cls-1 {
fill: #65b1dd;
}
</style>
</defs>
<title>tray context menu icons</title>
<g id="resume_Kopie" data-name="resume Kopie">
<polygon class="cls-1" points="5 14 13 8 5 2 5 14"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 384 B

@@ -0,0 +1,13 @@
<svg id="tray_menu_icons" data-name="tray menu icons" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<defs>
<style>
.cls-1 {
fill: #65b1dd;
}
</style>
</defs>
<title>tray context menu icons</title>
<g id="show_Kopie" data-name="show Kopie">
<polygon class="cls-1" points="8 4.001 2 10.301 3.5 11.876 8 7.072 12.5 11.876 14 10.301 8 4.001"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 427 B

@@ -0,0 +1,14 @@
<svg id="tray_menu_icons" data-name="tray menu icons" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<defs>
<style>
.cls-1 {
fill: #65b1dd;
}
</style>
</defs>
<title>tray context menu icons</title>
<g id="pause_Kopie" data-name="pause Kopie">
<rect class="cls-1" x="4" y="2" width="3" height="12"/>
<rect class="cls-1" x="9" y="2" width="3" height="12"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 445 B

@@ -0,0 +1,13 @@
<svg id="tray_menu_icons" data-name="tray menu icons" xmlns="http://www.w3.org/2000/svg" width="15.997" height="16" viewBox="0 0 15.997 16">
<defs>
<style>
.cls-1 {
fill: #65b1dd;
}
</style>
</defs>
<title>tray context menu icons</title>
<g id="stop_Kopie" data-name="stop Kopie">
<polygon id="stop" class="cls-1" points="13.998 3.95 12.048 2 7.998 6.05 3.948 2 1.998 3.95 6.049 8 1.998 12.05 3.948 14 7.998 9.95 12.048 14 13.998 12.05 9.949 8 13.998 3.95"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 513 B

@@ -0,0 +1,13 @@
<svg id="tray_menu_icons" data-name="tray menu icons" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<defs>
<style>
.cls-1 {
fill: #65b1dd;
}
</style>
</defs>
<title>tray context menu icons</title>
<g id="resume_Kopie" data-name="resume Kopie">
<polygon class="cls-1" points="5 14 13 8 5 2 5 14"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 384 B

@@ -63,9 +63,29 @@ namespace Duplicati.Library.Modules.Builtin
}
#endregion
#region Implementation of IGenericSourceModule
public Dictionary<string, string> ParseSourcePaths(ref string[] paths, ref string filter, Dictionary<string, string> commandlineOptions)
{
// Early exit in case we are non-windows to prevent attempting to load Windows-only components
if (!Utility.Utility.IsClientWindows)
{
Logging.Log.WriteMessage("Hyper-V backup works only on Windows OS", Logging.LogMessageType.Warning);
if (paths != null)
paths = paths.Where(x => !x.Equals(m_HyperVPathAllRegExp, StringComparison.OrdinalIgnoreCase) && !Regex.IsMatch(x, m_HyperVPathGuidRegExp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)).ToArray();
return new Dictionary<string, string>();
}
// Windows, do the real stuff!
return RealParseSourcePaths(ref paths, ref filter, commandlineOptions);
}
// Make sure the JIT does not attempt to inline this call and thus load
// referenced types from System.Management here
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
private Dictionary<string, string> RealParseSourcePaths(ref string[] paths, ref string filter, Dictionary<string, string> commandlineOptions)
{
var changedOptions = new Dictionary<string, string>();
var filtersInclude = new List<string>();
@@ -84,15 +104,7 @@ namespace Duplicati.Library.Modules.Builtin
filter = string.Join(System.IO.Path.PathSeparator.ToString(), remainingfilters);
}
if (!Utility.Utility.IsClientWindows)
{
Logging.Log.WriteMessage("Hyper-V backup works only on Windows OS", Logging.LogMessageType.Warning);
if(paths != null)
paths = paths.Where(x => !x.Equals(m_HyperVPathAllRegExp, StringComparison.OrdinalIgnoreCase) && !Regex.IsMatch(x, m_HyperVPathGuidRegExp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)).ToArray();
}
if (paths == null || !ContainFilesForBackup(paths) || !Utility.Utility.IsClientWindows)
if (paths == null || !ContainFilesForBackup(paths))
return changedOptions;
if (commandlineOptions.Keys.Contains("vss-exclude-writers"))
File diff suppressed because one or more lines are too long
@@ -51,6 +51,7 @@ backupApp.directive('restoreFilePicker', function() {
id: data.data.Files[n].Path,
size: data.data.Files[n].Sizes[0],
iconCls: leaf ? 'x-tree-icon-leaf' : '',
entrytype: AppUtils.getEntryTypeFromIconCls(leaf ? 'x-tree-icon-leaf' : ''),
leaf: leaf
});
}
@@ -294,7 +295,8 @@ backupApp.directive('restoreFilePicker', function() {
expanded: items[n].expanded,
iconCls: items[n].iconCls,
leaf: items[n].leaf,
id: items[n].Path
id: items[n].Path,
entrytype: AppUtils.getEntryTypeFromIconCls(items[n].iconCls)
};
if (items[n].Children) {
@@ -33,6 +33,11 @@ backupApp.directive('sourceFolderPicker', function() {
return scope.systeminfo.CaseSensitiveFilesystem ? path : path.toLowerCase();
}
function setEntryType(n)
{
n.entrytype = AppUtils.getEntryTypeFromIconCls(n.iconCls);
}
function setIconCls(n) {
var cp = compareablePath(n.id);
@@ -56,6 +61,8 @@ backupApp.directive('sourceFolderPicker', function() {
n.iconCls = 'x-tree-icon-broken';
else if (cp.substr(cp.length - 1, 1) != dirsep)
n.iconCls = 'x-tree-icon-leaf';
setEntryType(n);
}
function indexOfPathInArray(array, item) {
@@ -227,9 +234,11 @@ backupApp.directive('sourceFolderPicker', function() {
}, function(data) {
var p = data.config.data.path;
var ix = findInList(sources, compareablePath(p));
if (ix != null && sources[ix].id == p)
sources[ix].iconCls = 'x-tree-icon-broken';
var ix = findInList(sourceNodeChildren, compareablePath(p));
if (ix != null && sourceNodeChildren[ix].id == p) {
sourceNodeChildren[ix].iconCls = 'x-tree-icon-broken';
setEntryType(sourceNodeChildren[ix]);
}
});
}
}
@@ -327,6 +336,10 @@ backupApp.directive('sourceFolderPicker', function() {
AppService.post('/filesystem?onlyfolders=false&showhidden=true', {path: node.id}).then(function(data) {
node.children = data.data;
node.loading = false;
if (node.children != null)
for(var i in node.children)
setEntryType(node.children[i]);
updateIncludeFlags(node, node.include);
@@ -26,6 +26,11 @@ backupApp.directive('destinationFolderPicker', function() {
return scope.systeminfo.CaseSensitiveFilesystem ? path : path.toLowerCase();
};
function setEntryType(n)
{
n.entrytype = AppUtils.getEntryTypeFromIconCls(n.iconCls);
}
function setIconCls(n) {
var cp = compareablePath(n.id);
var dirsep = scope.systeminfo.DirectorySeparator || '/';
@@ -42,6 +47,8 @@ backupApp.directive('destinationFolderPicker', function() {
n.iconCls = 'x-tree-icon-home';
else if (cp.substr(cp.length - 1, 1) != dirsep)
n.iconCls = 'x-tree-icon-leaf';
setEntryType(n);
}
$scope.toggleExpanded = function(node) {
@@ -59,6 +66,10 @@ backupApp.directive('destinationFolderPicker', function() {
AppService.post('/filesystem?onlyfolders=true&showhidden=true', {path: node.id}).then(function(data) {
node.children = data.data;
node.loading = false;
if (node.children != null)
for(var i in node.children)
setEntryType(node.children[i]);
}, function() {
node.loading = false;
@@ -118,7 +129,10 @@ backupApp.directive('destinationFolderPicker', function() {
usernode.children.push(data.data[i]);
}
else
systemnode.children.push(data.data[i]);
{
setEntryType(data.data[i]);
systemnode.children.push(data.data[i]);
}
}
updateHideUserNode();
@@ -41,6 +41,40 @@ backupApp.service('AppUtils', function($rootScope, $timeout, $cookies, DialogSer
if (m) $timeout(m);
};
this.getEntryTypeFromIconCls = function(cls)
{
// Entry type is used in as the ALT entry,
// to guide screen reading software for visually
// impaired users
var res = gettextCatalog.getString('Folder');
if (cls == 'x-tree-icon-mydocuments')
res = gettextCatalog.getString('My Documents');
else if (cls == gettextCatalog.getString('x-tree-icon-mymusic'))
res = gettextCatalog.getString('My Music');
else if (cls == 'x-tree-icon-mypictures')
res = gettextCatalog.getString('My Pictures');
else if (cls == 'x-tree-icon-desktop')
res = gettextCatalog.getString('Desktop');
else if (cls == 'x-tree-icon-home')
res = gettextCatalog.getString('Home');
else if (cls == 'x-tree-icon-hypervmachine')
res = gettextCatalog.getString('Hyper-V Machine');
else if (cls == 'x-tree-icon-hyperv')
res = gettextCatalog.getString('Hyper-V Machines');
else if (cls == 'x-tree-icon-broken')
res = gettextCatalog.getString('Broken access');
else if (cls == 'x-tree-icon-locked')
res = gettextCatalog.getString('Access denied');
else if (cls == 'x-tree-icon-symlink')
res = gettextCatalog.getString('Symbolic link');
else if (cls == 'x-tree-icon-leaf')
res = gettextCatalog.getString('File');
return res;
}
function reloadTexts() {
apputils.fileSizeMultipliers = [
{name: gettextCatalog.getString('byte'), value: ''},
@@ -1,12 +1,12 @@
<ul dx-start-with="treedata" class="tree-view">
<li ng-repeat="node in $dxPrior.children" ng-class="{hidden: node.invisible || (node.hidden &amp;&amp; !ngShowHidden)}">
<div ng-class="{selected: node.selected}">
<a class="nav" ng-click="toggleExpanded(node)" ng-class="{expanded: node.expanded, leaf: node.leaf}"></a>
<a class="check" ng-click="toggleCheck(node)" ng-class="{include: node.include == '+', exclude: node.include == '-', partial: node.include == ' ', root: node.root}"></a>
<a class="type {{node.iconCls}}" ng-class="{invisible: node.hidden, loading: node.loading}"></a>
<div ng-class="{selected: node.selected}" alt="{{node.selected ? 'selected' : 'not selected'}}">
<a class="nav" ng-click="toggleExpanded(node)" ng-class="{expanded: node.expanded, leaf: node.leaf}" alt="{{node.expanded ? 'expanded' : 'contracted'}}"></a>
<a class="check" ng-click="toggleCheck(node)" ng-class="{include: node.include == '+', exclude: node.include == '-', partial: node.include == ' ', root: node.root}" alt="{{node.include == ' ' ? 'partially included' : (node.include == '-' ? 'excluded' : (node.include == '+' ? 'included' : 'not checked'))}}"></a>
<a class="type {{node.iconCls}}" alt="{{loading ? 'loading' : node.entrytype}}" ng-class="{invisible: node.hidden, loading: node.loading}"></a>
<span ng-click="toggleSelected(node)" ng-bind-html="node.text | highlight:ngSearchFilter"></span>
</div>
<ul ng-class="{expanded: node.expanded}" dx-connect="node"/>
<ul ng-class="{expanded: node.expanded}" dx-connect="node" alt="{{node.expanded ? 'expanded' : 'contracted'}}"/>
</li>
</ul>
@@ -1,12 +1,12 @@
<ul dx-start-with="treedata" class="tree-view">
<li ng-repeat="node in $dxPrior.children" ng-class="{hidden: (node.hidden &amp;&amp; !ngShowHidden)}">
<div ng-class="{selected: node.selected}">
<a class="nav" ng-click="toggleExpanded(node)" ng-class="{expanded: node.expanded, leaf: node.leaf}"></a>
<a class="check" ng-click="toggleCheck(node)" ng-class="{include: node.include == '+', exclude: node.include == '-', partial: node.include == ' ', root: node.root}"></a>
<a class="type {{node.iconCls}}" ng-class="{invisible: node.hidden, loading: node.loading}"></a>
<div ng-class="{selected: node.selected}" alt="{{node.selected ? 'selected' : 'not selected'}}">
<a class="nav" ng-click="toggleExpanded(node)" alt="{{node.expanded ? 'expanded' : 'contracted'}}" ng-class="{expanded: node.expanded, leaf: node.leaf}"></a>
<a class="check" ng-click="toggleCheck(node)" alt="{{node.include == ' ' ? 'partially included' : (node.include == '-' ? 'excluded' : (node.include == '+' ? 'included' : 'not checked'))}}" ng-class="{include: node.include == '+', exclude: node.include == '-', partial: node.include == ' ', root: node.root}"></a>
<a class="type {{node.iconCls}}" alt="{{loading ? 'loading' : node.entrytype}}" ng-class="{invisible: node.hidden, loading: node.loading}"></a>
<span ng-click="toggleSelected(node)" title="{{ node.tooltip }}">{{ node.text }}</span>
</div>
<ul ng-class="{expanded: node.expanded, include: node.include, exclude: node.exclude}" dx-connect="node"/>
<ul ng-class="{expanded: node.expanded, include: node.include, exclude: node.exclude}" alt="{{node.include == '+' ? 'included' : (node.include == '-' ? 'excluded' : 'partially included')}}" dx-connect="node"/>
</li>
</ul>
@@ -1,11 +1,11 @@
<ul dx-start-with="treedata" class="tree-view">
<li ng-repeat="node in $dxPrior.children" ng-class="{hidden: node.invisible || (node.hidden &amp;&amp; !ngShowHidden)}">
<div ng-class="{selected: node.selected}">
<a class="nav" ng-click="toggleExpanded(node)" ng-class="{expanded: node.expanded, leaf: node.leaf}"></a>
<a class="type {{node.iconCls}}" ng-class="{invisible: node.hidden, loading: node.loading}"></a>
<div ng-class="{selected: node.selected}" alt="{{node.selected ? 'selected' : 'not selected'}}">
<a class="nav" ng-click="toggleExpanded(node)" ng-class="{expanded: node.expanded, leaf: node.leaf}" alt="{{node.expanded ? 'expanded' : 'contracted'}}"></a>
<a class="type {{node.iconCls}}" alt="{{loading ? 'loading' : node.entrytype}}" ng-class="{invisible: node.hidden, loading: node.loading}"></a>
<span ng-click="toggleSelected(node)">{{ node.text }}</span>
</div>
<ul ng-class="{expanded: node.expanded}" dx-connect="node"/>
<ul ng-class="{expanded: node.expanded}" alt="{{node.expanded ? 'expanded' : 'contracted'}}" dx-connect="node"/>
</li>
</ul>
+1
View File
@@ -5,4 +5,5 @@ cd $SCRIPT_DIR
cd ../../Duplicati/
find . -type f -name *.cs > $SCRIPT_DIR"/"filelist_cs.txt
xgettext -k --from-code=UTF-8 --output=$SCRIPT_DIR"/"localization.pot --files-from=$SCRIPT_DIR"/"filelist_cs.txt --language=C# --keyword=LC.L
sed -i "s/charset=CHARSET/charset=UTF-8/g" $SCRIPT_DIR"/"localization.pot
rm $SCRIPT_DIR"/"filelist_cs.txt
Binary file not shown.
+19 -8
View File
@@ -8,12 +8,12 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-10-23 23:35+0200\n"
"POT-Creation-Date: 2016-10-26 13:13+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: ForGorNorPor <ForGorNorPor44@mailinator.com>, 2016\n"
"Language-Team: German (https://www.transifex.com/duplicati/teams/67655/de/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -710,6 +710,17 @@ msgid ""
" a username and password is supplied, the same credentials are used for all "
"destinations."
msgstr ""
"Diese Option erlaubt es mehrere Zielpfade anzugeben. Der Hauptzielpfad wird "
"vor allen Pfaden aus der Liste dieser Option angeben. Vor Beginn des Backups"
" wird jeder Ordner aus der Liste auf seine Existenz geprüft und optional auf"
" das Vorhandensein der Markierungsdatei, die angegeben wurde mit --{0}. Der "
"erste Pfad der existiert und möglicherweise eine Markierungsdatei enthält "
"wird dann als Zielpfad verwendet. Mehrere Zielpfade werden mit \"{1}\" von "
"einander getrennt. Unter Windows kann der Pfad ein UNC Pfad sein und der "
"Laufwerksbuchstabe darf als Sternchen (*) angegeben werden z.B.: "
"\"*:\\backup\", was bedeutet, dass alle Laufwerksbuchstaben geprüft werden. "
"Wenn ein Nutzername und ein Passwort angegeben wurden, werden sie für alle "
"Zielpfade verwendet."
#: Library/Backend/File/Strings.cs:7
msgid "A list of secondary target paths"
@@ -2429,12 +2440,12 @@ msgstr ""
msgid ""
"When matching timestamps, Duplicati will adjust the times by a small "
"fraction to ensure that minor time differences do not cause unexpected "
"updated. If the option --{0} is set to keep a week of backups, and the "
"backup is made the same time each week, it is possible that a the clock "
"drifts slightly, such that full week has just passed, causing Duplicati to "
"delete the older backup earlier than expected. To avoid this, Duplicati "
"inserts a 1% tolerance (max 1 hour). Use this option to disable the "
"tolerance, and use strict time checking"
"updates. If the option --{0} is set to keep a week of backups, and the "
"backup is made the same time each week, it is possible that the clock drifts"
" slightly, such that full week has just passed, causing Duplicati to delete "
"the older backup earlier than expected. To avoid this, Duplicati inserts a "
"1% tolerance (max 1 hour). Use this option to disable the tolerance, and use"
" strict time checking"
msgstr ""
#: Library/Main/Strings.cs:107
Binary file not shown.
+8 -8
View File
@@ -8,12 +8,12 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-10-23 23:35+0200\n"
"POT-Creation-Date: 2016-10-26 13:13+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Pruebas Pruebas <pruebaspruebas77@gmail.com>, 2016\n"
"Language-Team: Spanish (https://www.transifex.com/duplicati/teams/67655/es/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -2372,12 +2372,12 @@ msgstr ""
msgid ""
"When matching timestamps, Duplicati will adjust the times by a small "
"fraction to ensure that minor time differences do not cause unexpected "
"updated. If the option --{0} is set to keep a week of backups, and the "
"backup is made the same time each week, it is possible that a the clock "
"drifts slightly, such that full week has just passed, causing Duplicati to "
"delete the older backup earlier than expected. To avoid this, Duplicati "
"inserts a 1% tolerance (max 1 hour). Use this option to disable the "
"tolerance, and use strict time checking"
"updates. If the option --{0} is set to keep a week of backups, and the "
"backup is made the same time each week, it is possible that the clock drifts"
" slightly, such that full week has just passed, causing Duplicati to delete "
"the older backup earlier than expected. To avoid this, Duplicati inserts a "
"1% tolerance (max 1 hour). Use this option to disable the tolerance, and use"
" strict time checking"
msgstr ""
#: Library/Main/Strings.cs:107
Binary file not shown.
+8 -8
View File
@@ -8,12 +8,12 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-10-23 23:35+0200\n"
"POT-Creation-Date: 2016-10-26 13:13+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Glaude Ratinier <zitoire@yahoo.fr>, 2016\n"
"Language-Team: French (https://www.transifex.com/duplicati/teams/67655/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: fr\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
@@ -2415,12 +2415,12 @@ msgstr ""
msgid ""
"When matching timestamps, Duplicati will adjust the times by a small "
"fraction to ensure that minor time differences do not cause unexpected "
"updated. If the option --{0} is set to keep a week of backups, and the "
"backup is made the same time each week, it is possible that a the clock "
"drifts slightly, such that full week has just passed, causing Duplicati to "
"delete the older backup earlier than expected. To avoid this, Duplicati "
"inserts a 1% tolerance (max 1 hour). Use this option to disable the "
"tolerance, and use strict time checking"
"updates. If the option --{0} is set to keep a week of backups, and the "
"backup is made the same time each week, it is possible that the clock drifts"
" slightly, such that full week has just passed, causing Duplicati to delete "
"the older backup earlier than expected. To avoid this, Duplicati inserts a "
"1% tolerance (max 1 hour). Use this option to disable the tolerance, and use"
" strict time checking"
msgstr ""
#: Library/Main/Strings.cs:107
+8 -8
View File
@@ -8,13 +8,13 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-10-25 22:36+0200\n"
"POT-Creation-Date: 2016-10-26 13:13+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: CommandLine/Program.cs:262
@@ -2295,12 +2295,12 @@ msgstr ""
msgid ""
"When matching timestamps, Duplicati will adjust the times by a small "
"fraction to ensure that minor time differences do not cause unexpected "
"updated. If the option --{0} is set to keep a week of backups, and the "
"backup is made the same time each week, it is possible that a the clock "
"drifts slightly, such that full week has just passed, causing Duplicati to "
"delete the older backup earlier than expected. To avoid this, Duplicati "
"inserts a 1% tolerance (max 1 hour). Use this option to disable the "
"tolerance, and use strict time checking"
"updates. If the option --{0} is set to keep a week of backups, and the "
"backup is made the same time each week, it is possible that the clock drifts "
"slightly, such that full week has just passed, causing Duplicati to delete "
"the older backup earlier than expected. To avoid this, Duplicati inserts a "
"1% tolerance (max 1 hour). Use this option to disable the tolerance, and use "
"strict time checking"
msgstr ""
#: Library/Main/Strings.cs:107
@@ -615,8 +615,8 @@ msgstr "doppelte Option {{opt}}"
#: templates/delete.html:15
msgid ""
"Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n"
" When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n"
"Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\r\n"
" When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\r\n"
" If you are using the local database for backups from the commandline, you should keep the database."
msgstr ""
"Jedes Backup hat eine lokale Datenbank.\n"
@@ -614,13 +614,13 @@ msgstr "Opciones de duplicado {{opt}}"
#: templates/delete.html:15
msgid ""
"Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n"
" When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n"
"Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\r\n"
" When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\r\n"
" If you are using the local database for backups from the commandline, you should keep the database."
msgstr ""
"Cada copia tiene una base de datos local asociada que almacena información sobre la copia de seguridad remota en la máquina local.\n"
"Al eliminar una copia de seguridad, también puede borrar la base de datos local sin afectar a la habilidad de restaurar los archivos remotos.\n"
"Si está utilizando la base de datos local para copias de seguridad desde la línea de comandos, debe mantener la base de datos."
"Cada copia tiene una base de datos local asociada a ella, esta almacena información sobre la copia de seguridad remota en el equipo local.\r\n"
" Al eliminar una copia de seguridad, puede borrar la base de datos local sin afectar a la capacidad de restaurar los archivos remotos.\r\n"
" Si está utilizando la base de datos local para copias de seguridad desde la línea de comandos, debe mantener la base de datos."
#: templates/localdatabase.html:8
msgid ""
@@ -615,10 +615,13 @@ msgstr "Option de duplication {{opt}}"
#: templates/delete.html:15
msgid ""
"Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n"
" When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n"
"Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\r\n"
" When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\r\n"
" If you are using the local database for backups from the commandline, you should keep the database."
msgstr ""
"Chaque sauvegarde a une base de données locale associée à elle, elle stocke des informations localement à propos de la sauvegarde distante.\n"
"Quand vous supprimez une sauvegarde, vous pouvez aussi supprimer la base de données locale sans affecter votre capacité à restaurer vos fichiers distants.\n"
"Si vous utilisez la base de données locale pour vos sauvegardes à partir de la ligne de commande, vous devez conserver la base de données."
#: templates/localdatabase.html:8
msgid ""
@@ -618,8 +618,8 @@ msgstr ""
#: templates/delete.html:15
msgid ""
"Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\n"
" When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\n"
"Each backup has a local database associated with it, which stores information about the remote backup on the local machine.\r\n"
" When deleting a backup, you can also delete the local database without affecting the ability to restore the remote files.\r\n"
" If you are using the local database for backups from the commandline, you should keep the database."
msgstr ""
+1 -1
View File
@@ -1 +1 @@
28
29
+13
View File
@@ -1,3 +1,16 @@
2016-10-27 - 2.0.1.29_canary_2016-10-27
==========
* Better support for LVM snapshots, thanks @a1ezzz
* Fixed additional Debian dependencies, thanks @a1ezzz
* Additional translation files, Spanish and French
* Improved HyperV support from CLI and UI, thanks @mnaiman and @agrajaghh
* Fixed a bug with log-spam from Windows Service, thanks @mnaiman
* Fixed issue with backup metadata and user that do not exist locally, thanks @gerco
* Improved screen reading support
* Fixed OSX icon on dark statusbar
* Fixed crashes on Linux related to icon format
* Updated GTK support and switched to SVG icons
2016-10-19
==========
* Some additions to the translation system