summaryrefslogtreecommitdiff
path: root/lib/process_xml.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/process_xml.cpp')
-rw-r--r--lib/process_xml.cpp1577
1 files changed, 0 insertions, 1577 deletions
diff --git a/lib/process_xml.cpp b/lib/process_xml.cpp
deleted file mode 100644
index 3e3e72f1..00000000
--- a/lib/process_xml.cpp
+++ /dev/null
@@ -1,1577 +0,0 @@
-// **************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
-// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#include "process_xml.h"
-#include <utility>
-#include <zenxml/xml.h>
-#include "ffs_paths.h"
-#include <zen/file_handling.h>
-#include <zen/file_io.h>
-//#include <zen/time.h>
-#include "xml_base.h"
-
-using namespace zen;
-using namespace xmlAccess; //functionally needed for correct overload resolution!!!
-using namespace std::rel_ops;
-
-namespace
-{
-//-------------------------------------------------------------------------------------------------------------------------------
-const int XML_FORMAT_VER_GLOBAL = 1;
-const int XML_FORMAT_VER_FFS_GUI = 3; //for FFS 5.22
-const int XML_FORMAT_VER_FFS_BATCH = 3; //
-//-------------------------------------------------------------------------------------------------------------------------------
-}
-
-XmlType getXmlType(const zen::XmlDoc& doc) //throw()
-{
- if (doc.root().getNameAs<std::string>() == "FreeFileSync")
- {
- std::string type;
- if (doc.root().getAttribute("XmlType", type))
- {
- if (type == "GUI")
- return XML_TYPE_GUI;
- else if (type == "BATCH")
- return XML_TYPE_BATCH;
- else if (type == "GLOBAL")
- return XML_TYPE_GLOBAL;
- }
- }
- return XML_TYPE_OTHER;
-}
-
-
-XmlType xmlAccess::getXmlType(const Zstring& filename) //throw()
-{
- try
- {
- //do NOT use zen::loadStream as it will needlessly load even huge files!
- XmlDoc doc = loadXmlDocument(filename); //throw FfsXmlError, quick exit if file is not an FFS XML
- return ::getXmlType(doc);
- }
- catch (const FfsXmlError&)
- {
- return XML_TYPE_OTHER;
- }
-}
-
-
-void setXmlType(XmlDoc& doc, XmlType type) //throw()
-{
- switch (type)
- {
- case XML_TYPE_GUI:
- doc.root().setAttribute("XmlType", "GUI");
- break;
- case XML_TYPE_BATCH:
- doc.root().setAttribute("XmlType", "BATCH");
- break;
- case XML_TYPE_GLOBAL:
- doc.root().setAttribute("XmlType", "GLOBAL");
- break;
- case XML_TYPE_OTHER:
- assert(false);
- break;
- }
-}
-
-//################################################################################################################
-
-Zstring xmlAccess::getGlobalConfigFile()
-{
- return zen::getConfigDir() + Zstr("GlobalSettings.xml");
-}
-
-
-void xmlAccess::OptionalDialogs::resetDialogs()
-{
- warningDependentFolders = true;
- warningFolderPairRaceCondition = true;
- warningSignificantDifference = true;
- warningNotEnoughDiskSpace = true;
- warningUnresolvedConflicts = true;
- warningDatabaseError = true;
- warningRecyclerMissing = true;
- warningInputFieldEmpty = true;
- warningDirectoryLockFailed = true;
- popupOnConfigChange = true;
- confirmSyncStart = true;
- confirmExternalCommandMassInvoke = true;
-}
-
-
-xmlAccess::XmlGuiConfig xmlAccess::convertBatchToGui(const xmlAccess::XmlBatchConfig& batchCfg) //noexcept
-{
- XmlGuiConfig output;
- output.mainCfg = batchCfg.mainCfg;
-
- switch (batchCfg.handleError)
- {
- case ON_ERROR_POPUP:
- case ON_ERROR_STOP:
- output.handleError = ON_GUIERROR_POPUP;
- break;
- case ON_ERROR_IGNORE:
- output.handleError = ON_GUIERROR_IGNORE;
- break;
- }
- return output;
-}
-
-
-xmlAccess::XmlBatchConfig xmlAccess::convertGuiToBatch(const xmlAccess::XmlGuiConfig& guiCfg) //noexcept
-{
- XmlBatchConfig output; //use default batch-settings
- output.mainCfg = guiCfg.mainCfg;
-
- switch (guiCfg.handleError)
- {
- case ON_GUIERROR_POPUP:
- output.handleError = ON_ERROR_POPUP;
- break;
- case ON_GUIERROR_IGNORE:
- output.handleError = ON_ERROR_IGNORE;
- break;
- }
- return output;
-}
-
-
-xmlAccess::XmlBatchConfig xmlAccess::convertGuiToBatchPreservingExistingBatch(const xmlAccess::XmlGuiConfig& guiCfg, const Zstring& referenceBatchFile) //noexcept
-{
- //try to take over batch-specific settings from reference file if possible
- if (!referenceBatchFile.empty())
- try
- {
- XmlBatchConfig batchCfg;
- readConfig(referenceBatchFile, batchCfg); //throw FfsXmlError
-
- batchCfg.mainCfg = guiCfg.mainCfg;
- return batchCfg;
- }
- catch (xmlAccess::FfsXmlError&) {}
-
- return convertGuiToBatch(guiCfg);
-}
-
-
-namespace
-{
-std::vector<Zstring> splitFilterByLines(const Zstring& filterPhrase)
-{
- if (filterPhrase.empty())
- return std::vector<Zstring>();
- return split(filterPhrase, Zstr('\n'));
-}
-
-Zstring mergeFilterLines(const std::vector<Zstring>& filterLines)
-{
- if (filterLines.empty())
- return Zstring();
- Zstring out = filterLines[0];
- std::for_each(filterLines.begin() + 1, filterLines.end(), [&](const Zstring& line) { out += Zstr('\n'); out += line; });
- return out;
-}
-}
-
-
-namespace zen
-{
-template <> inline
-void writeText(const CompareVariant& value, std::string& output)
-{
- switch (value)
- {
- case zen::CMP_BY_TIME_SIZE:
- output = "TimeAndSize";
- break;
- case zen::CMP_BY_CONTENT:
- output = "Content";
- break;
- }
-}
-
-template <> inline
-bool readText(const std::string& input, CompareVariant& value)
-{
- std::string tmp = input;
- zen::trim(tmp);
- warn_static("remove after migration. 2013.08.20")
- if (tmp == "ByTimeAndSize") //obsolete
- value = zen::CMP_BY_TIME_SIZE;
- else if (tmp == "ByContent") //obsolete
- value = zen::CMP_BY_CONTENT;
- else
-
- if (tmp == "TimeAndSize")
- value = zen::CMP_BY_TIME_SIZE;
- else if (tmp == "Content")
- value = zen::CMP_BY_CONTENT;
- else
- return false;
- return true;
-}
-
-
-template <> inline
-void writeText(const SyncDirection& value, std::string& output)
-{
- switch (value)
- {
- case SyncDirection::LEFT:
- output = "left";
- break;
- case SyncDirection::RIGHT:
- output = "right";
- break;
- case SyncDirection::NONE:
- output = "none";
- break;
- }
-}
-
-template <> inline
-bool readText(const std::string& input, SyncDirection& value)
-{
- std::string tmp = input;
- zen::trim(tmp);
- if (tmp == "left")
- value = SyncDirection::LEFT;
- else if (tmp == "right")
- value = SyncDirection::RIGHT;
- else if (tmp == "none")
- value = SyncDirection::NONE;
- else
- return false;
- return true;
-}
-
-
-template <> inline
-void writeText(const OnError& value, std::string& output)
-{
- switch (value)
- {
- case ON_ERROR_IGNORE:
- output = "Ignore";
- break;
- case ON_ERROR_POPUP:
- output = "Popup";
- break;
- case ON_ERROR_STOP:
- output = "Stop";
- break;
- }
-}
-
-template <> inline
-bool readText(const std::string& input, OnError& value)
-{
- std::string tmp = input;
- zen::trim(tmp);
- warn_static("remove after migration. 2013.08.20")
- if (tmp == "Exit") //obsolete
- value = ON_ERROR_STOP;
- else if (tmp == "Abort") //obsolete: 2013.09.04
- value = ON_ERROR_STOP;
- else
-
- if (tmp == "Ignore")
- value = ON_ERROR_IGNORE;
- else if (tmp == "Popup")
- value = ON_ERROR_POPUP;
- else if (tmp == "Stop")
- value = ON_ERROR_STOP;
- else
- return false;
- return true;
-}
-
-
-template <> inline
-void writeText(const OnGuiError& value, std::string& output)
-{
- switch (value)
- {
- case ON_GUIERROR_IGNORE:
- output = "Ignore";
- break;
- case ON_GUIERROR_POPUP:
- output = "Popup";
- break;
- }
-}
-
-template <> inline
-bool readText(const std::string& input, OnGuiError& value)
-{
- std::string tmp = input;
- zen::trim(tmp);
- if (tmp == "Ignore")
- value = ON_GUIERROR_IGNORE;
- else if (tmp == "Popup")
- value = ON_GUIERROR_POPUP;
- else
- return false;
- return true;
-}
-
-
-template <> inline
-void writeText(const FileIconSize& value, std::string& output)
-{
- switch (value)
- {
- case ICON_SIZE_SMALL:
- output = "Small";
- break;
- case ICON_SIZE_MEDIUM:
- output = "Medium";
- break;
- case ICON_SIZE_LARGE:
- output = "Large";
- break;
- }
-}
-
-
-template <> inline
-bool readText(const std::string& input, FileIconSize& value)
-{
- std::string tmp = input;
- zen::trim(tmp);
- if (tmp == "Small")
- value = ICON_SIZE_SMALL;
- else if (tmp == "Medium")
- value = ICON_SIZE_MEDIUM;
- else if (tmp == "Large")
- value = ICON_SIZE_LARGE;
- else
- return false;
- return true;
-}
-
-
-template <> inline
-void writeText(const DeletionPolicy& value, std::string& output)
-{
- switch (value)
- {
- case DELETE_PERMANENTLY:
- output = "Permanent";
- break;
- case DELETE_TO_RECYCLER:
- output = "RecycleBin";
- break;
- case DELETE_TO_VERSIONING:
- output = "Versioning";
- break;
- }
-}
-
-template <> inline
-bool readText(const std::string& input, DeletionPolicy& value)
-{
- std::string tmp = input;
- zen::trim(tmp);
- //------------------
- warn_static("remove after migration?")
- if (tmp == "DeletePermanently")//obsolete name
- value = DELETE_PERMANENTLY;
- else if (tmp == "MoveToRecycleBin")//obsolete name
- value = DELETE_TO_RECYCLER;
- else if (tmp == "MoveToCustomDirectory")//obsolete name
- value = DELETE_TO_VERSIONING;
- else
-
- if (tmp == "Permanent")
- value = DELETE_PERMANENTLY;
- else if (tmp == "RecycleBin")
- value = DELETE_TO_RECYCLER;
- else if (tmp == "Versioning")
- value = DELETE_TO_VERSIONING;
- else
- return false;
- return true;
-}
-
-
-template <> inline
-void writeText(const SymLinkHandling& value, std::string& output)
-{
- switch (value)
- {
- case SYMLINK_EXCLUDE:
- output = "Exclude";
- break;
- case SYMLINK_USE_DIRECTLY:
- output = "Direct";
- break;
- case SYMLINK_FOLLOW_LINK:
- output = "Follow";
- break;
- }
-}
-
-template <> inline
-bool readText(const std::string& input, SymLinkHandling& value)
-{
- std::string tmp = input;
- zen::trim(tmp);
- warn_static("remove after migration. 2013.08.20")
- if (tmp == "UseDirectly") //obsolete!
- value = SYMLINK_USE_DIRECTLY;
- else if (tmp == "FollowLink") //obsolete!
- value = SYMLINK_FOLLOW_LINK;
- else if (tmp == "Ignore") //obsolete!
- value = SYMLINK_EXCLUDE;
- else
-
- if (tmp == "Exclude")
- value = SYMLINK_EXCLUDE;
- else if (tmp == "Direct")
- value = SYMLINK_USE_DIRECTLY;
- else if (tmp == "Follow")
- value = SYMLINK_FOLLOW_LINK;
- else
- return false;
- return true;
-}
-
-
-template <> inline
-void writeText(const ColumnTypeRim& value, std::string& output)
-{
- switch (value)
- {
- case COL_TYPE_DIRECTORY:
- output = "Base";
- break;
- case COL_TYPE_FULL_PATH:
- output = "Full";
- break;
- case COL_TYPE_REL_PATH:
- output = "Rel";
- break;
- case COL_TYPE_FILENAME:
- output = "Name";
- break;
- case COL_TYPE_SIZE:
- output = "Size";
- break;
- case COL_TYPE_DATE:
- output = "Date";
- break;
- case COL_TYPE_EXTENSION:
- output = "Ext";
- break;
- }
-}
-
-template <> inline
-bool readText(const std::string& input, ColumnTypeRim& value)
-{
- std::string tmp = input;
- zen::trim(tmp);
- if (tmp == "Base")
- value = COL_TYPE_DIRECTORY;
- else if (tmp == "Full")
- value = COL_TYPE_FULL_PATH;
- else if (tmp == "Rel")
- value = COL_TYPE_REL_PATH;
- else if (tmp == "Name")
- value = COL_TYPE_FILENAME;
- else if (tmp == "Size")
- value = COL_TYPE_SIZE;
- else if (tmp == "Date")
- value = COL_TYPE_DATE;
- else if (tmp == "Ext")
- value = COL_TYPE_EXTENSION;
- else
- return false;
- return true;
-}
-
-
-template <> inline
-void writeText(const ColumnTypeNavi& value, std::string& output)
-{
- switch (value)
- {
- case COL_TYPE_NAVI_BYTES:
- output = "Bytes";
- break;
- case COL_TYPE_NAVI_DIRECTORY:
- output = "Tree";
- break;
- case COL_TYPE_NAVI_ITEM_COUNT:
- output = "Count";
- break;
- }
-}
-
-template <> inline
-bool readText(const std::string& input, ColumnTypeNavi& value)
-{
- std::string tmp = input;
- zen::trim(tmp);
- if (tmp == "Bytes")
- value = COL_TYPE_NAVI_BYTES;
- else if (tmp == "Tree")
- value = COL_TYPE_NAVI_DIRECTORY;
- else if (tmp == "Count")
- value = COL_TYPE_NAVI_ITEM_COUNT;
- else
- return false;
- return true;
-}
-
-
-template <> inline
-void writeText(const UnitSize& value, std::string& output)
-{
- switch (value)
- {
- case USIZE_NONE:
- output = "None";
- break;
- case USIZE_BYTE:
- output = "Byte";
- break;
- case USIZE_KB:
- output = "KB";
- break;
- case USIZE_MB:
- output = "MB";
- break;
- }
-}
-
-template <> inline
-bool readText(const std::string& input, UnitSize& value)
-{
- std::string tmp = input;
- zen::trim(tmp);
- warn_static("remove after migration. 2013.08.20")
- if (tmp == "Inactive") //obsolete!
- value = USIZE_NONE;
- else
-
- if (tmp == "None")
- value = USIZE_NONE;
- else if (tmp == "Byte")
- value = USIZE_BYTE;
- else if (tmp == "KB")
- value = USIZE_KB;
- else if (tmp == "MB")
- value = USIZE_MB;
- else
- return false;
- return true;
-}
-
-template <> inline
-void writeText(const UnitTime& value, std::string& output)
-{
- switch (value)
- {
- case UTIME_NONE:
- output = "None";
- break;
- case UTIME_TODAY:
- output = "Today";
- break;
- case UTIME_THIS_MONTH:
- output = "Month";
- break;
- case UTIME_THIS_YEAR:
- output = "Year";
- break;
- case UTIME_LAST_X_DAYS:
- output = "x-days";
- break;
- }
-}
-
-template <> inline
-bool readText(const std::string& input, UnitTime& value)
-{
- std::string tmp = input;
- zen::trim(tmp);
- warn_static("remove after migration. 2013.08.20")
- if (tmp == "Inactive") //obsolete!
- value = UTIME_NONE;
- else
-
- if (tmp == "None")
- value = UTIME_NONE;
- else if (tmp == "Today")
- value = UTIME_TODAY;
- else if (tmp == "Month")
- value = UTIME_THIS_MONTH;
- else if (tmp == "Year")
- value = UTIME_THIS_YEAR;
- else if (tmp == "x-days")
- value = UTIME_LAST_X_DAYS;
- else
- return false;
- return true;
-}
-
-template <> inline
-void writeText(const VersioningStyle& value, std::string& output)
-{
- switch (value)
- {
- case VER_STYLE_REPLACE:
- output = "Replace";
- break;
- case VER_STYLE_ADD_TIMESTAMP:
- output = "TimeStamp";
- break;
- }
-}
-
-template <> inline
-bool readText(const std::string& input, VersioningStyle& value)
-{
- std::string tmp = input;
- zen::trim(tmp);
- warn_static("remove after migration. 2013.08.20")
- if (tmp == "AddTimeStamp") //obsolete
- value = VER_STYLE_ADD_TIMESTAMP;
- else
-
- if (tmp == "Replace")
- value = VER_STYLE_REPLACE;
- else if (tmp == "TimeStamp")
- value = VER_STYLE_ADD_TIMESTAMP;
- else
- return false;
- return true;
-}
-
-
-template <> inline
-void writeText(const DirectionConfig::Variant& value, std::string& output)
-{
- switch (value)
- {
- case DirectionConfig::TWOWAY:
- output = "TwoWay";
- break;
- case DirectionConfig::MIRROR:
- output = "Mirror";
- break;
- case DirectionConfig::UPDATE:
- output = "Update";
- break;
- case DirectionConfig::CUSTOM:
- output = "Custom";
- break;
- }
-}
-
-template <> inline
-bool readText(const std::string& input, DirectionConfig::Variant& value)
-{
- std::string tmp = input;
- zen::trim(tmp);
- warn_static("remove after migration. 2013.08.20")
- if (tmp == "Automatic") //obsolete!
- value = DirectionConfig::TWOWAY;
- else
-
- if (tmp == "TwoWay")
- value = DirectionConfig::TWOWAY;
- else if (tmp == "Mirror")
- value = DirectionConfig::MIRROR;
- else if (tmp == "Update")
- value = DirectionConfig::UPDATE;
- else if (tmp == "Custom")
- value = DirectionConfig::CUSTOM;
- else
- return false;
- return true;
-}
-
-
-template <> inline
-bool readStruc(const XmlElement& input, ColumnAttributeRim& value)
-{
- XmlIn in(input);
- bool rv1 = in.attribute("Type", value.type_);
- bool rv2 = in.attribute("Visible", value.visible_);
- bool rv3 = in.attribute("Width", value.offset_); //offset == width if stretch is 0
- bool rv4 = in.attribute("Stretch", value.stretch_);
- return rv1 && rv2 && rv3 && rv4;
-}
-
-template <> inline
-void writeStruc(const ColumnAttributeRim& value, XmlElement& output)
-{
- XmlOut out(output);
- out.attribute("Type", value.type_);
- out.attribute("Visible", value.visible_);
- out.attribute("Width", value.offset_);
- out.attribute("Stretch", value.stretch_);
-}
-
-
-template <> inline
-bool readStruc(const XmlElement& input, ColumnAttributeNavi& value)
-{
- XmlIn in(input);
- bool rv1 = in.attribute("Type", value.type_);
- bool rv2 = in.attribute("Visible", value.visible_);
- bool rv3 = in.attribute("Width", value.offset_); //offset == width if stretch is 0
- bool rv4 = in.attribute("Stretch", value.stretch_);
- return rv1 && rv2 && rv3 && rv4;
-}
-
-template <> inline
-void writeStruc(const ColumnAttributeNavi& value, XmlElement& output)
-{
- XmlOut out(output);
- out.attribute("Type", value.type_);
- out.attribute("Visible", value.visible_);
- out.attribute("Width", value.offset_);
- out.attribute("Stretch", value.stretch_);
-}
-
-
-template <> inline
-bool readStruc(const XmlElement& input, ViewFilterDefault& value)
-{
- XmlIn in(input);
-
- bool success = true;
- auto readAttr = [&](XmlIn& elemIn, const char name[], bool& v)
- {
- if (!elemIn.attribute(name, v))
- success = false;
- };
-
- XmlIn catView = in["CategoryView"];
- readAttr(catView, "LeftOnly" , value.leftOnly);
- readAttr(catView, "RightOnly" , value.rightOnly);
- readAttr(catView, "LeftNewer" , value.leftNewer);
- readAttr(catView, "RightNewer", value.rightNewer);
- readAttr(catView, "Different" , value.different);
- readAttr(catView, "Equal" , value.equal);
- readAttr(catView, "Conflict" , value.conflict);
-
- XmlIn actView = in["ActionView"];
- readAttr(actView, "CreateLeft" , value.createLeft);
- readAttr(actView, "CreateRight", value.createRight);
- readAttr(actView, "UpdateLeft" , value.updateLeft);
- readAttr(actView, "UpdateRight", value.updateRight);
- readAttr(actView, "DeleteLeft" , value.deleteLeft);
- readAttr(actView, "DeleteRight", value.deleteRight);
- readAttr(actView, "DoNothing" , value.doNothing);
-
- return success; //[!] avoid short-circuit evaluation above
-}
-
-template <> inline
-void writeStruc(const ViewFilterDefault& value, XmlElement& output)
-{
- XmlOut out(output);
-
- XmlOut catView = out["CategoryView"];
- catView.attribute("LeftOnly" , value.leftOnly);
- catView.attribute("RightOnly" , value.rightOnly);
- catView.attribute("LeftNewer" , value.leftNewer);
- catView.attribute("RightNewer", value.rightNewer);
- catView.attribute("Different" , value.different);
- catView.attribute("Equal" , value.equal);
- catView.attribute("Conflict" , value.conflict);
-
- XmlOut actView = out["ActionView"];
- actView.attribute("CreateLeft" , value.createLeft);
- actView.attribute("CreateRight", value.createRight);
- actView.attribute("UpdateLeft" , value.updateLeft);
- actView.attribute("UpdateRight", value.updateRight);
- actView.attribute("DeleteLeft" , value.deleteLeft);
- actView.attribute("DeleteRight", value.deleteRight);
- actView.attribute("DoNothing" , value.doNothing);
-}
-
-
-template <> inline
-bool readStruc(const XmlElement& input, ConfigHistoryItem& value)
-{
- XmlIn in(input);
- bool rv1 = in(value.configFile);
- //bool rv2 = in.attribute("LastUsed", value.lastUseTime);
- return rv1 /*&& rv2*/;
-}
-
-
-template <> inline
-void writeStruc(const ConfigHistoryItem& value, XmlElement& output)
-{
- XmlOut out(output);
- out(value.configFile);
- //out.attribute("LastUsed", value.lastUseTime);
-}
-}
-
-
-namespace
-{
-void readConfig(const XmlIn& in, CompConfig& cmpConfig)
-{
- in["Variant" ](cmpConfig.compareVar);
-
- warn_static("remove check after migration. 2013.09.7")
- if (in["HandleSymlinks"])//obsolete name
- in["HandleSymlinks"](cmpConfig.handleSymlinks);
- else
- in["Symlinks"](cmpConfig.handleSymlinks);
-}
-
-
-void readConfig(const XmlIn& in, DirectionConfig& directCfg)
-{
- in["Variant"](directCfg.var);
-
- XmlIn inCustDir = in["CustomDirections"];
- inCustDir["LeftOnly" ](directCfg.custom.exLeftSideOnly);
- inCustDir["RightOnly" ](directCfg.custom.exRightSideOnly);
- inCustDir["LeftNewer" ](directCfg.custom.leftNewer);
- inCustDir["RightNewer"](directCfg.custom.rightNewer);
- inCustDir["Different" ](directCfg.custom.different);
- inCustDir["Conflict" ](directCfg.custom.conflict);
-
- warn_static("remove check after migration. 2013.08.17")
- if (in["DetectMovedFiles"]) //new value: remove check
- in["DetectMovedFiles"](directCfg.detectMovedFiles);
-}
-
-
-void readConfig(const XmlIn& in, SyncConfig& syncCfg)
-{
- readConfig(in, syncCfg.directionCfg);
-
- in["DeletionPolicy"](syncCfg.handleDeletion);
-
- warn_static("remove after migration?")
- if (in["CustomDeletionFolder"])
- in["CustomDeletionFolder"](syncCfg.versioningDirectory);//obsolete name
- else
- in["VersioningFolder"](syncCfg.versioningDirectory);
-
- warn_static("remove after migration?")
- if (in["VersioningFolder"] &&
- in["VersioningFolder"].get()->getAttribute("Style", syncCfg.versioningStyle)) //new parameter, do not complain when missing
- ;
- else if (in["VersioningStyle"]) //obsolete name
- in["VersioningStyle"](syncCfg.versioningStyle);
- else
- syncCfg.versioningStyle = VER_STYLE_ADD_TIMESTAMP; //obsolete fallback
-}
-
-
-void readConfig(const XmlIn& in, FilterConfig& filter)
-{
- warn_static("remove after migration?")
- auto haveFilterAsSingleString = [&]() -> bool
- {
- if (in["Include"])
- if (auto elem = in["Include"].get())
- {
- std::string tmp;
- if (elem->getValue(tmp))
- return !tmp.empty();
- }
- return false;
- };
- if (haveFilterAsSingleString()) //obsolete style
- {
- in["Include"](filter.includeFilter);
- in["Exclude"](filter.excludeFilter);
- }
- else
- {
- std::vector<Zstring> tmp = splitFilterByLines(filter.includeFilter); //default value
- in["Include"](tmp);
- filter.includeFilter = mergeFilterLines(tmp);
-
- std::vector<Zstring> tmp2 = splitFilterByLines(filter.excludeFilter); //default value
- in["Exclude"](tmp2);
- filter.excludeFilter = mergeFilterLines(tmp2);
- }
-
- in["TimeSpan"](filter.timeSpan);
- warn_static("remove after migration?")
- if (in["UnitTimeSpan"]) in["UnitTimeSpan"](filter.unitTimeSpan);//obsolete name
- else
- in["TimeSpan"].attribute("Type", filter.unitTimeSpan);
-
- in["SizeMin"](filter.sizeMin);
- if (in["UnitSizeMin"]) in["UnitSizeMin"](filter.unitSizeMin);//obsolete name
- else
- in["SizeMin"].attribute("Unit", filter.unitSizeMin);
-
- in["SizeMax"](filter.sizeMax);
- if (in["UnitSizeMax"]) in["UnitSizeMax"](filter.unitSizeMax);//obsolete name
- else
- in["SizeMax"].attribute("Unit", filter.unitSizeMax);
-}
-
-
-void readConfig(const XmlIn& in, FolderPairEnh& enhPair)
-{
- //read folder pairs
- in["Left" ](enhPair.leftDirectory);
- in["Right"](enhPair.rightDirectory);
-
- //###########################################################
- //alternate comp configuration (optional)
- if (XmlIn inAltCmp = in["CompareConfig"])
- {
- CompConfig altCmpCfg;
- readConfig(inAltCmp, altCmpCfg);
-
- enhPair.altCmpConfig = std::make_shared<CompConfig>(altCmpCfg);
- }
- //###########################################################
- //alternate sync configuration (optional)
- if (XmlIn inAltSync = in["SyncConfig"])
- {
- SyncConfig altSyncCfg;
- readConfig(inAltSync, altSyncCfg);
-
- enhPair.altSyncConfig = std::make_shared<SyncConfig>(altSyncCfg);
- }
-
- //###########################################################
- //alternate filter configuration
- if (XmlIn inLocFilter = in["LocalFilter"])
- readConfig(inLocFilter, enhPair.localFilter);
-}
-
-
-void readConfig(const XmlIn& in, MainConfiguration& mainCfg)
-{
- //read compare settings
- XmlIn inMain = in["MainConfig"];
-
- readConfig(inMain["Comparison"], mainCfg.cmpConfig);
- //###########################################################
-
- //read sync configuration
- readConfig(inMain["SyncConfig"], mainCfg.syncCfg);
- //###########################################################
-
- //read filter settings
- readConfig(inMain["GlobalFilter"], mainCfg.globalFilter);
-
- //###########################################################
- //read all folder pairs
- mainCfg.additionalPairs.clear();
-
- bool firstItem = true;
- for (XmlIn inPair = inMain["FolderPairs"]["Pair"]; inPair; inPair.next())
- {
- FolderPairEnh newPair;
- readConfig(inPair, newPair);
-
- if (firstItem)
- {
- firstItem = false;
- mainCfg.firstPair = newPair; //set first folder pair
- }
- else
- mainCfg.additionalPairs.push_back(newPair); //set additional folder pairs
- }
-
- warn_static("remove after migration?")
- if (inMain["ExecuteWhenFinished"]) inMain["ExecuteWhenFinished"](mainCfg.onCompletion); //obsolete name
- else
- inMain["OnCompletion"](mainCfg.onCompletion);
-}
-
-
-void readConfig(const XmlIn& in, xmlAccess::XmlGuiConfig& config)
-{
- readConfig(in, config.mainCfg); //read main config
-
- //read GUI specific config data
- XmlIn inGuiCfg = in["GuiConfig"];
-
- warn_static("remove after migration?")
- if (inGuiCfg["HideFiltered" ]) //obsolete name
- inGuiCfg["HideFiltered" ](config.hideExcludedItems);
- else if (inGuiCfg["ShowFiltered" ]) //obsolete name
- {
- inGuiCfg["ShowFiltered"](config.hideExcludedItems);
- config.hideExcludedItems = !config.hideExcludedItems;
- }
- else
- inGuiCfg["HideExcluded"](config.hideExcludedItems);
-
- inGuiCfg["HandleError" ](config.handleError);
-
- warn_static("remove after migration?")
- if (inGuiCfg["SyncPreviewActive"]) //obsolete name
- inGuiCfg["SyncPreviewActive"](config.highlightSyncAction);
- else
- {
- std::string val;
- if (inGuiCfg["MiddleGridView"](val)) //refactor into enum!?
- config.highlightSyncAction = val == "Action";
- }
-}
-
-
-void readConfig(const XmlIn& in, xmlAccess::XmlBatchConfig& config)
-{
- readConfig(in, config.mainCfg); //read main config
-
- //read GUI specific config data
- XmlIn inBatchCfg = in["BatchConfig"];
-
- inBatchCfg["HandleError" ](config.handleError);
- inBatchCfg["ShowProgress" ](config.showProgress);
-
- warn_static("remove after migration?")
- if (inBatchCfg["LogfileDirectory"]) inBatchCfg["LogfileDirectory"](config.logFileDirectory); //obsolete name
- else
- inBatchCfg["LogfileFolder"](config.logFileDirectory);
-
- if (inBatchCfg["LogfileCountMax" ]) inBatchCfg["LogfileCountMax"](config.logfilesCountLimit); //obsolete name
- else
- inBatchCfg["LogfileFolder"].attribute("Limit", config.logfilesCountLimit);
-}
-
-
-void readConfig(const XmlIn& in, XmlGlobalSettings& config)
-{
- XmlIn inShared = in["Shared"];
-
- inShared["Language"].attribute("Id", config.programLanguage);
-
- inShared["FailSafeFileCopy" ].attribute("Enabled", config.failsafeFileCopy);
- inShared["CopyLockedFiles" ].attribute("Enabled", config.copyLockedFiles);
- inShared["CopyFilePermissions" ].attribute("Enabled", config.copyFilePermissions);
- inShared["AutomaticRetry" ].attribute("Count" , config.automaticRetryCount);
- inShared["AutomaticRetry" ].attribute("Delay" , config.automaticRetryDelay);
- inShared["FileTimeTolerance" ].attribute("Seconds", config.fileTimeTolerance);
- inShared["RunWithBackgroundPriority"].attribute("Enabled", config.runWithBackgroundPriority);
- inShared["LockDirectoriesDuringSync"].attribute("Enabled", config.createLockFile);
- inShared["VerifyCopiedFiles" ].attribute("Enabled", config.verifyFileCopy);
- inShared["LastSyncsLogSizeMax" ].attribute("Bytes" , config.lastSyncsLogFileSizeMax);
-
- XmlIn inOpt = inShared["OptionalDialogs"];
- inOpt["WarnUnresolvedConflicts" ].attribute("Enabled", config.optDialogs.warningUnresolvedConflicts);
- inOpt["WarnNotEnoughDiskSpace" ].attribute("Enabled", config.optDialogs.warningNotEnoughDiskSpace);
- inOpt["WarnSignificantDifference" ].attribute("Enabled", config.optDialogs.warningSignificantDifference);
- inOpt["WarnRecycleBinNotAvailable" ].attribute("Enabled", config.optDialogs.warningRecyclerMissing);
- inOpt["WarnInputFieldEmpty" ].attribute("Enabled", config.optDialogs.warningInputFieldEmpty);
- inOpt["WarnDatabaseError" ].attribute("Enabled", config.optDialogs.warningDatabaseError);
- inOpt["WarnDependentFolders" ].attribute("Enabled", config.optDialogs.warningDependentFolders);
- inOpt["WarnFolderPairRaceCondition"].attribute("Enabled", config.optDialogs.warningFolderPairRaceCondition);
- inOpt["WarnDirectoryLockFailed" ].attribute("Enabled", config.optDialogs.warningDirectoryLockFailed);
- inOpt["ConfirmSaveConfig" ].attribute("Enabled", config.optDialogs.popupOnConfigChange);
- inOpt["ConfirmStartSync" ].attribute("Enabled", config.optDialogs.confirmSyncStart);
- inOpt["ConfirmExternalCommandMassInvoke"].attribute("Enabled", config.optDialogs.confirmExternalCommandMassInvoke);
-
- //gui specific global settings (optional)
- XmlIn inGui = in["Gui"];
- XmlIn inWnd = inGui["MainDialog"];
-
- //read application window size and position
- inWnd.attribute("Width", config.gui.dlgSize.x);
- inWnd.attribute("Height", config.gui.dlgSize.y);
- inWnd.attribute("PosX", config.gui.dlgPos.x);
- inWnd.attribute("PosY", config.gui.dlgPos.y);
- inWnd.attribute("Maximized", config.gui.isMaximized);
-
- XmlIn inManualDel = inWnd["ManualDeletion"];
- //inManualDel.attribute("DeleteOnBothSides", config.gui.deleteOnBothSides);
- inManualDel.attribute("UseRecycler" , config.gui.useRecyclerForManualDeletion);
-
- inWnd["CaseSensitiveSearch"].attribute("Enabled", config.gui.textSearchRespectCase);
- inWnd["FolderPairsVisible" ].attribute("Max", config.gui.maxFolderPairsVisible);
-
- //###########################################################
-
- XmlIn inOverview = inWnd["OverviewPanel"];
- inOverview.attribute("ShowPercentage", config.gui.showPercentBar);
- inOverview.attribute("SortByColumn", config.gui.naviLastSortColumn);
- inOverview.attribute("SortAscending", config.gui.naviLastSortAscending);
-
- //read column attributes
- XmlIn inColNavi = inOverview["Columns"];
- inColNavi(config.gui.columnAttribNavi);
-
- XmlIn inMainGrid = inWnd["MainGrid"];
- inMainGrid.attribute("ShowIcons", config.gui.showIcons);
- inMainGrid.attribute("IconSize", config.gui.iconSize);
- inMainGrid.attribute("SashOffset", config.gui.sashOffset);
-
- XmlIn inColLeft = inMainGrid["ColumnsLeft"];
- inColLeft(config.gui.columnAttribLeft);
-
- XmlIn inColRight = inMainGrid["ColumnsRight"];
- inColRight(config.gui.columnAttribRight);
- //###########################################################
-
- inWnd["ViewFilterDefault"](config.gui.viewFilterDefault);
- inWnd["Perspective2" ](config.gui.guiPerspectiveLast);
-
- std::vector<Zstring> tmp = splitFilterByLines(config.gui.defaultExclusionFilter); //default value
- inGui["DefaultExclusionFilter"](tmp);
- config.gui.defaultExclusionFilter = mergeFilterLines(tmp);
-
- //load config file history
- inGui["LastUsedConfig"](config.gui.lastUsedConfigFiles);
-
- inGui["ConfigHistory"](config.gui.cfgFileHistory);
- inGui["ConfigHistory"].attribute("MaxSize", config.gui.cfgFileHistMax);
-
- inGui["FolderHistoryLeft" ](config.gui.folderHistoryLeft);
- inGui["FolderHistoryRight"](config.gui.folderHistoryRight);
- inGui["FolderHistoryLeft"].attribute("MaxSize", config.gui.folderHistMax);
-
- inGui["OnCompletionHistory"](config.gui.onCompletionHistory);
- inGui["OnCompletionHistory"].attribute("MaxSize", config.gui.onCompletionHistoryMax);
-
- //external applications
- inGui["ExternalApplications"](config.gui.externelApplications);
-
- //last update check
- inGui["LastVersionCheck"](config.gui.lastUpdateCheck);
-
- //batch specific global settings
- //XmlIn inBatch = in["Batch"];
-}
-
-
-bool needsMigration(const XmlDoc& doc, int currentXmlFormatVer)
-{
- //(try to) migrate old configuration if needed
- int xmlFormatVer = 0;
- /*bool success = */doc.root().getAttribute("XmlFormat", xmlFormatVer);
- return xmlFormatVer < currentXmlFormatVer;
-}
-
-
-template <class ConfigType>
-void readConfig(const Zstring& filename, XmlType type, ConfigType& cfg, int currentXmlFormatVer, bool& needMigration) //throw FfsXmlError
-{
- XmlDoc doc = loadXmlDocument(filename); //throw FfsXmlError
-
- if (getXmlType(doc) != type) //throw()
- throw FfsXmlError(replaceCpy(_("File %x does not contain a valid configuration."), L"%x", fmtFileName(filename)));
-
- XmlIn in(doc);
- ::readConfig(in, cfg);
-
- if (in.errorsOccured())
- throw FfsXmlError(replaceCpy(_("Configuration file %x loaded partially only."), L"%x", fmtFileName(filename)) + L"\n\n" +
- getErrorMessageFormatted(in.getErrorsAs<std::wstring>()), FfsXmlError::WARNING);
-
- //(try to) migrate old configuration if needed
- needMigration = needsMigration(doc, currentXmlFormatVer);
-}
-}
-
-
-void xmlAccess::readConfig(const Zstring& filename, xmlAccess::XmlGuiConfig& cfg)
-{
- bool needMigration = false;
- ::readConfig(filename, XML_TYPE_GUI, cfg, XML_FORMAT_VER_FFS_GUI, needMigration); //throw FfsXmlError
-
- if (needMigration) //(try to) migrate old configuration
- try { xmlAccess::writeConfig(cfg, filename); /*throw FfsXmlError*/ }
- catch (FfsXmlError&) { assert(false); } //don't bother user!
-}
-
-
-void xmlAccess::readConfig(const Zstring& filename, xmlAccess::XmlBatchConfig& cfg)
-{
- bool needMigration = false;
- ::readConfig(filename, XML_TYPE_BATCH, cfg, XML_FORMAT_VER_FFS_BATCH, needMigration); //throw FfsXmlError
-
- if (needMigration) //(try to) migrate old configuration
- try { xmlAccess::writeConfig(cfg, filename); /*throw FfsXmlError*/ }
- catch (FfsXmlError&) { assert(false); } //don't bother user!
-}
-
-
-void xmlAccess::readConfig(xmlAccess::XmlGlobalSettings& cfg)
-{
- bool needMigration = false;
- ::readConfig(getGlobalConfigFile(), XML_TYPE_GLOBAL, cfg, XML_FORMAT_VER_GLOBAL, needMigration); //throw FfsXmlError
-}
-
-
-namespace
-{
-template <class XmlCfg>
-XmlCfg parseConfig(const XmlDoc& doc, const Zstring& filename, int currentXmlFormatVer, std::unique_ptr<FfsXmlError>& warning) //nothrow
-{
- XmlCfg cfg;
- XmlIn in(doc);
- ::readConfig(in, cfg);
-
- if (in.errorsOccured())
- {
- if (!warning)
- warning = make_unique<FfsXmlError>(replaceCpy(_("Configuration file %x loaded partially only."), L"%x", fmtFileName(filename)) + L"\n\n" +
- getErrorMessageFormatted(in.getErrorsAs<std::wstring>()), FfsXmlError::WARNING);
- }
- else
- {
- //(try to) migrate old configuration if needed
- if (needsMigration(doc, currentXmlFormatVer))
- try { xmlAccess::writeConfig(cfg, filename); /*throw FfsXmlError*/ }
- catch (FfsXmlError&) { assert(false); } //don't bother user!
- }
- return cfg;
-}
-}
-
-
-void xmlAccess::readAnyConfig(const std::vector<Zstring>& filenames, XmlGuiConfig& config) //throw FfsXmlError
-{
- assert(!filenames.empty());
-
- std::vector<zen::MainConfiguration> mainCfgs;
- std::unique_ptr<FfsXmlError> warning;
-
- for (auto it = filenames.begin(); it != filenames.end(); ++it)
- {
- const Zstring& filename = *it;
- const bool firstItem = it == filenames.begin(); //init all non-"mainCfg" settings with first config file
-
- XmlDoc doc = loadXmlDocument(filename); //throw FfsXmlError
- //do NOT use zen::loadStream as it will superfluously load even huge files!
-
- switch (::getXmlType(doc))
- {
- case XML_TYPE_GUI:
- {
- XmlGuiConfig guiCfg = parseConfig<XmlGuiConfig>(doc, filename, XML_FORMAT_VER_FFS_GUI, warning); //nothrow
- if (firstItem)
- config = guiCfg;
- mainCfgs.push_back(guiCfg.mainCfg);
- }
- break;
-
- case XML_TYPE_BATCH:
- {
- XmlBatchConfig batchCfg = parseConfig<XmlBatchConfig>(doc, filename, XML_FORMAT_VER_FFS_BATCH, warning); //nothrow
- if (firstItem)
- config = convertBatchToGui(batchCfg);
- mainCfgs.push_back(batchCfg.mainCfg);
- }
- break;
-
- case XML_TYPE_GLOBAL:
- case XML_TYPE_OTHER:
- throw FfsXmlError(replaceCpy(_("File %x does not contain a valid configuration."), L"%x", fmtFileName(filename)));
- }
- }
-
- config.mainCfg = merge(mainCfgs);
-
- if (warning)
- throw* warning;
-}
-
-//################################################################################################
-
-namespace
-{
-void writeConfig(const CompConfig& cmpConfig, XmlOut& out)
-{
- out["Variant" ](cmpConfig.compareVar);
- out["Symlinks"](cmpConfig.handleSymlinks);
-}
-
-
-void writeConfig(const DirectionConfig& directCfg, XmlOut& out)
-{
- out["Variant"](directCfg.var);
-
- XmlOut outCustDir = out["CustomDirections"];
- outCustDir["LeftOnly" ](directCfg.custom.exLeftSideOnly);
- outCustDir["RightOnly" ](directCfg.custom.exRightSideOnly);
- outCustDir["LeftNewer" ](directCfg.custom.leftNewer);
- outCustDir["RightNewer"](directCfg.custom.rightNewer);
- outCustDir["Different" ](directCfg.custom.different);
- outCustDir["Conflict" ](directCfg.custom.conflict);
-
- out["DetectMovedFiles"](directCfg.detectMovedFiles);
-}
-
-
-void writeConfig(const SyncConfig& syncCfg, XmlOut& out)
-{
- writeConfig(syncCfg.directionCfg, out);
-
- out["DeletionPolicy" ](syncCfg.handleDeletion);
- out["VersioningFolder"](syncCfg.versioningDirectory);
- //out["VersioningFolder"].attribute("Limit", syncCfg.versionCountLimit);
- out["VersioningFolder"].attribute("Style", syncCfg.versioningStyle);
-}
-
-
-void writeConfig(const FilterConfig& filter, XmlOut& out)
-{
- out["Include"](splitFilterByLines(filter.includeFilter));
- out["Exclude"](splitFilterByLines(filter.excludeFilter));
-
- out["TimeSpan"](filter.timeSpan);
- out["TimeSpan"].attribute("Type", filter.unitTimeSpan);
-
- out["SizeMin"](filter.sizeMin);
- out["SizeMin"].attribute("Unit", filter.unitSizeMin);
-
- out["SizeMax"](filter.sizeMax);
- out["SizeMax"].attribute("Unit", filter.unitSizeMax);
-}
-
-
-void writeConfigFolderPair(const FolderPairEnh& enhPair, XmlOut& out)
-{
- XmlOut outPair = out.ref().addChild("Pair");
-
- //read folder pairs
- outPair["Left" ](enhPair.leftDirectory);
- outPair["Right"](enhPair.rightDirectory);
-
- //###########################################################
- //alternate comp configuration (optional)
- if (enhPair.altCmpConfig.get())
- {
- XmlOut outAlt = outPair["CompareConfig"];
- writeConfig(*enhPair.altCmpConfig, outAlt);
- }
- //###########################################################
- //alternate sync configuration (optional)
- if (enhPair.altSyncConfig.get())
- {
- XmlOut outAltSync = outPair["SyncConfig"];
- writeConfig(*enhPair.altSyncConfig, outAltSync);
- }
-
- //###########################################################
- //alternate filter configuration
- if (enhPair.localFilter != FilterConfig()) //don't spam .ffs_gui file with default filter entries
- {
- XmlOut outFilter = outPair["LocalFilter"];
- writeConfig(enhPair.localFilter, outFilter);
- }
-}
-
-
-void writeConfig(const MainConfiguration& mainCfg, XmlOut& out)
-{
- XmlOut outMain = out["MainConfig"];
-
- XmlOut outCmp = outMain["Comparison"];
-
- writeConfig(mainCfg.cmpConfig, outCmp);
- //###########################################################
-
- XmlOut outSync = outMain["SyncConfig"];
-
- writeConfig(mainCfg.syncCfg, outSync);
- //###########################################################
-
- XmlOut outFilter = outMain["GlobalFilter"];
- //write filter settings
- writeConfig(mainCfg.globalFilter, outFilter);
-
- //###########################################################
- //write all folder pairs
-
- XmlOut outFp = outMain["FolderPairs"];
-
- //write first folder pair
- writeConfigFolderPair(mainCfg.firstPair, outFp);
-
- //write additional folder pairs
- std::for_each(mainCfg.additionalPairs.begin(), mainCfg.additionalPairs.end(),
- [&](const FolderPairEnh& fp) { writeConfigFolderPair(fp, outFp); });
-
- outMain["OnCompletion"](mainCfg.onCompletion);
-}
-
-
-void writeConfig(const XmlGuiConfig& config, XmlOut& out)
-{
- writeConfig(config.mainCfg, out); //write main config
-
- //write GUI specific config data
- XmlOut outGuiCfg = out["GuiConfig"];
-
- outGuiCfg["HideExcluded" ](config.hideExcludedItems);
- outGuiCfg["HandleError" ](config.handleError);
- outGuiCfg["MiddleGridView"](config.highlightSyncAction ? "Action" : "Category"); //refactor into enum!?
-}
-
-void writeConfig(const XmlBatchConfig& config, XmlOut& out)
-{
-
- writeConfig(config.mainCfg, out); //write main config
-
- //write GUI specific config data
- XmlOut outBatchCfg = out["BatchConfig"];
-
- outBatchCfg["HandleError" ](config.handleError);
- outBatchCfg["ShowProgress" ](config.showProgress);
- outBatchCfg["LogfileFolder" ](config.logFileDirectory);
- outBatchCfg["LogfileFolder"].attribute("Limit", config.logfilesCountLimit);
-}
-
-
-void writeConfig(const XmlGlobalSettings& config, XmlOut& out)
-{
- XmlOut outShared = out["Shared"];
-
- outShared["Language"].attribute("Id", config.programLanguage);
-
- outShared["FailSafeFileCopy" ].attribute("Enabled", config.failsafeFileCopy);
- outShared["CopyLockedFiles" ].attribute("Enabled", config.copyLockedFiles);
- outShared["CopyFilePermissions" ].attribute("Enabled", config.copyFilePermissions);
- outShared["AutomaticRetry" ].attribute("Count" , config.automaticRetryCount);
- outShared["AutomaticRetry" ].attribute("Delay" , config.automaticRetryDelay);
- outShared["FileTimeTolerance" ].attribute("Seconds", config.fileTimeTolerance);
- outShared["RunWithBackgroundPriority"].attribute("Enabled", config.runWithBackgroundPriority);
- outShared["LockDirectoriesDuringSync"].attribute("Enabled", config.createLockFile);
- outShared["VerifyCopiedFiles" ].attribute("Enabled", config.verifyFileCopy);
- outShared["LastSyncsLogSizeMax" ].attribute("Bytes" , config.lastSyncsLogFileSizeMax);
-
- XmlOut outOpt = outShared["OptionalDialogs"];
- outOpt["WarnUnresolvedConflicts" ].attribute("Enabled", config.optDialogs.warningUnresolvedConflicts);
- outOpt["WarnNotEnoughDiskSpace" ].attribute("Enabled", config.optDialogs.warningNotEnoughDiskSpace);
- outOpt["WarnSignificantDifference" ].attribute("Enabled", config.optDialogs.warningSignificantDifference);
- outOpt["WarnRecycleBinNotAvailable" ].attribute("Enabled", config.optDialogs.warningRecyclerMissing);
- outOpt["WarnInputFieldEmpty" ].attribute("Enabled", config.optDialogs.warningInputFieldEmpty);
- outOpt["WarnDatabaseError" ].attribute("Enabled", config.optDialogs.warningDatabaseError);
- outOpt["WarnDependentFolders" ].attribute("Enabled", config.optDialogs.warningDependentFolders);
- outOpt["WarnFolderPairRaceCondition"].attribute("Enabled", config.optDialogs.warningFolderPairRaceCondition);
- outOpt["WarnDirectoryLockFailed" ].attribute("Enabled", config.optDialogs.warningDirectoryLockFailed);
- outOpt["ConfirmSaveConfig" ].attribute("Enabled", config.optDialogs.popupOnConfigChange);
- outOpt["ConfirmStartSync" ].attribute("Enabled", config.optDialogs.confirmSyncStart);
- outOpt["ConfirmExternalCommandMassInvoke"].attribute("Enabled", config.optDialogs.confirmExternalCommandMassInvoke);
-
- //gui specific global settings (optional)
- XmlOut outGui = out["Gui"];
- XmlOut outWnd = outGui["MainDialog"];
-
- //write application window size and position
- outWnd.attribute("Width", config.gui.dlgSize.x);
- outWnd.attribute("Height", config.gui.dlgSize.y);
- outWnd.attribute("PosX", config.gui.dlgPos.x);
- outWnd.attribute("PosY", config.gui.dlgPos.y);
- outWnd.attribute("Maximized", config.gui.isMaximized);
-
- XmlOut outManualDel = outWnd["ManualDeletion"];
- //outManualDel.attribute("DeleteOnBothSides", config.gui.deleteOnBothSides);
- outManualDel.attribute("UseRecycler" , config.gui.useRecyclerForManualDeletion);
-
- outWnd["CaseSensitiveSearch"].attribute("Enabled", config.gui.textSearchRespectCase);
- outWnd["FolderPairsVisible" ].attribute("Max", config.gui.maxFolderPairsVisible);
-
- //###########################################################
-
- XmlOut outOverview = outWnd["OverviewPanel"];
- outOverview.attribute("ShowPercentage", config.gui.showPercentBar);
- outOverview.attribute("SortByColumn", config.gui.naviLastSortColumn);
- outOverview.attribute("SortAscending", config.gui.naviLastSortAscending);
-
- //write column attributes
- XmlOut outColNavi = outOverview["Columns"];
- outColNavi(config.gui.columnAttribNavi);
-
- XmlOut outMainGrid = outWnd["MainGrid"];
- outMainGrid.attribute("ShowIcons", config.gui.showIcons);
- outMainGrid.attribute("IconSize", config.gui.iconSize);
- outMainGrid.attribute("SashOffset", config.gui.sashOffset);
-
- XmlOut outColLeft = outMainGrid["ColumnsLeft"];
- outColLeft(config.gui.columnAttribLeft);
-
- XmlOut outColRight = outMainGrid["ColumnsRight"];
- outColRight(config.gui.columnAttribRight);
- //###########################################################
-
- outWnd["ViewFilterDefault"](config.gui.viewFilterDefault);
- outWnd["Perspective2" ](config.gui.guiPerspectiveLast);
-
- outGui["DefaultExclusionFilter"](splitFilterByLines(config.gui.defaultExclusionFilter));
-
- //load config file history
- outGui["LastUsedConfig"](config.gui.lastUsedConfigFiles);
-
- outGui["ConfigHistory" ](config.gui.cfgFileHistory);
- outGui["ConfigHistory"].attribute("MaxSize", config.gui.cfgFileHistMax);
-
- outGui["FolderHistoryLeft" ](config.gui.folderHistoryLeft);
- outGui["FolderHistoryRight"](config.gui.folderHistoryRight);
- outGui["FolderHistoryLeft" ].attribute("MaxSize", config.gui.folderHistMax);
-
- outGui["OnCompletionHistory"](config.gui.onCompletionHistory);
- outGui["OnCompletionHistory"].attribute("MaxSize", config.gui.onCompletionHistoryMax);
-
- //external applications
- outGui["ExternalApplications"](config.gui.externelApplications);
-
- //last update check
- outGui["LastVersionCheck"](config.gui.lastUpdateCheck);
-
- //batch specific global settings
- //XmlOut outBatch = out["Batch"];
-}
-
-
-template <class ConfigType>
-void writeConfig(const ConfigType& config, XmlType type, int xmlFormatVer, const Zstring& filename)
-{
- XmlDoc doc("FreeFileSync");
- setXmlType(doc, type); //throw()
-
- doc.root().setAttribute("XmlFormat", xmlFormatVer);
-
- XmlOut out(doc);
- writeConfig(config, out);
-
- saveXmlDocument(doc, filename); //throw FfsXmlError
-}
-}
-
-void xmlAccess::writeConfig(const XmlGuiConfig& cfg, const Zstring& filename)
-{
- ::writeConfig(cfg, XML_TYPE_GUI, XML_FORMAT_VER_FFS_GUI, filename); //throw FfsXmlError
-}
-
-
-void xmlAccess::writeConfig(const XmlBatchConfig& cfg, const Zstring& filename)
-{
- ::writeConfig(cfg, XML_TYPE_BATCH, XML_FORMAT_VER_FFS_BATCH, filename); //throw FfsXmlError
-}
-
-
-void xmlAccess::writeConfig(const XmlGlobalSettings& cfg)
-{
- ::writeConfig(cfg, XML_TYPE_GLOBAL, XML_FORMAT_VER_GLOBAL, getGlobalConfigFile()); //throw FfsXmlError
-}
-
-
-std::wstring xmlAccess::extractJobName(const Zstring& configFilename)
-{
- const Zstring shortName = afterLast(configFilename, FILE_NAME_SEPARATOR); //returns the whole string if separator not found
- const Zstring jobName = beforeLast(shortName, Zstr('.')); //returns empty string if seperator not found
- return utfCvrtTo<std::wstring>(jobName.empty() ? shortName : jobName);
-}
bgstack15