예제 #1
0
        public void Dispose()
        {
            if (!m_IsDisposed)
            {
                m_Logger.Log("Disposing page", XCad.Base.Enums.LoggerMessageSeverity_e.Debug);

                foreach (var ctrl in m_Page.Binding.Bindings.Select(b => b.Control).OfType <IDisposable>())
                {
                    try
                    {
                        ctrl.Dispose();
                    }
                    catch (Exception ex)
                    {
                        m_Logger.Log(ex);
                    }
                }

                m_IconsConv.Dispose();

                m_IsDisposed = true;

                Disposed?.Invoke(this);
            }
        }
예제 #2
0
        private void InvokeTrigger(Triggers_e trigger)
        {
            CommandMacroInfo[] cmds;

            if (m_Triggers.TryGetValue(trigger, out cmds))
            {
                cmds = cmds.Where(c => c.Scope.IsInScope(m_App)).ToArray();

                if (cmds != null && cmds.Any())
                {
                    m_Logger.Log($"Invoking {cmds.Length} command(s) for the trigger {trigger}");

                    foreach (var cmd in cmds)
                    {
                        try
                        {
                            m_MacroRunner.RunMacro(cmd.MacroPath, cmd.EntryPoint, false, cmd.Arguments);
                        }
                        catch (Exception ex)
                        {
                            m_Logger.Log(ex);
                            m_Msg.ShowError(ex, $"Failed to run a macro '{cmd.Title}' on trigger '{trigger}'");
                        }
                    }
                }
            }
        }
예제 #3
0
        private void OnPopupNotClosed(Process prc, IntPtr hWnd)
        {
            using (var vbaErrPopup = new VbaErrorPopup(hWnd))
            {
                if (vbaErrPopup.IsVbaErrorPopup)
                {
                    var curMacro = m_CurrentContext.CurrentMacro;

                    if (curMacro != null)
                    {
                        curMacro.InternalMacroException = new VbaMacroException(vbaErrPopup.ErrorText);
                    }

                    m_Logger.Log($"Closing VBA Error popup window: {hWnd}", LoggerMessageSeverity_e.Debug);

                    vbaErrPopup.Close();
                }
                else
                {
                    m_Logger.Log($"Blocking popup window is not closed: {hWnd}", LoggerMessageSeverity_e.Debug);

                    m_JournalWriter.WriteLine("Failed to close the blocking popup window");
                }
            }
        }
예제 #4
0
            public void Dispose()
            {
                if (m_CloseDrawing)
                {
                    if (CanClose(m_Drawing))
                    {
                        m_Logger.Log("Closing temp drawing document for QR code");
                        m_Drawing.Close();
                    }
                    else
                    {
                        Debug.Assert(false, "Drawing cannot be closed");
                    }
                }

                if (m_CloseDocument)
                {
                    if (CanClose(Document))
                    {
                        m_Logger.Log("Closing temp referenced document for QR code");
                        Document.Close();
                    }
                    else
                    {
                        Debug.Assert(false, "Document cannot be closed");
                    }
                }
            }
예제 #5
0
        private void OnPageClosed(PageCloseReasons_e reason)
        {
            if (reason == PageCloseReasons_e.Okay)
            {
                try
                {
                    IXDocument[] docs    = null;
                    var          rootDoc = m_Data.Input.Document;

                    switch (m_Data.Input.Scope)
                    {
                    case InputScope_e.AllReferences:
                        docs = m_Data.Input.AllDocuments.References
                               .Where(d => d.IsChecked).Select(d => d.Document).ToArray();
                        break;

                    case InputScope_e.Selection:
                        docs = m_Data.Input.Components
                               .Distinct(new ComponentDocumentSafeEqualityComparer())
                               .Select(c => c.ReferencedDocument).ToArray();
                        break;

                    default:
                        throw new NotSupportedException();
                    }

                    var input = docs.ToList();
                    ProcessInput?.Invoke(m_Host.Extension.Application, input);

                    var exec = new AssemblyBatchRunJobExecutor(m_Host.Extension.Application, m_MacroRunnerSvc,
                                                               input.ToArray(), m_Logger, m_Data.Macros.Macros.Macros.Select(x => x.Data).ToArray(),
                                                               m_Data.Options.ActivateDocuments, m_Data.Options.AllowReadOnly,
                                                               m_Data.Options.AllowRapid, m_Data.Options.AutoSave);

                    var vm = new JobResultVM(rootDoc.Title, exec, m_CadDesc, m_Logger);

                    using (var cancelHandler = new EscapeBatchExecutorCancelHandler(exec, m_Host.Extension.Application, m_Dispatcher))
                    {
                        vm.TryRunBatch();
                    }

                    var wnd = m_Host.Extension.CreatePopupWindow <ResultsWindow>();
                    wnd.Control.Title       = $"{rootDoc.Title} batch job result";
                    wnd.Control.DataContext = vm;
                    wnd.Show();
                }
                catch (OperationCanceledException)
                {
                }
                catch (Exception ex)
                {
                    m_Msg.ShowError(ex);
                    m_Logger.Log(ex);
                }
            }
        }
예제 #6
0
        public void Dispose()
        {
            m_Logger.Log("Disposing page");

            foreach (var ctrl in m_Page.Binding.Bindings.Select(b => b.Control).OfType <IDisposable>())
            {
                ctrl.Dispose();
            }

            m_IconsConv.Dispose();
        }
        public void Dispose()
        {
            m_Logger.Log("Disposing page", XCad.Base.Enums.LoggerMessageSeverity_e.Debug);

            foreach (var ctrl in m_Page.Binding.Bindings.Select(b => b.Control).OfType <IDisposable>())
            {
                ctrl.Dispose();
            }

            m_IconsConv.Dispose();
        }
예제 #8
0
 public void RunMacroCommand(CommandMacroInfo cmd)
 {
     try
     {
         m_MacroRunner.RunMacro(cmd.MacroPath, cmd.EntryPoint, cmd.UnloadAfterRun);
     }
     catch (Exception ex)
     {
         m_Logger.Log(ex);
         m_Msg.ShowError(ex, $"Failed to run macro: '{cmd.Title}'");
     }
 }
예제 #9
0
        private void OnCommandClick(Commands_e spec)
        {
            try
            {
                switch (spec)
                {
                case Commands_e.Configuration:

                    var vm = Resolve <CommandManagerVM>();

                    vm.Load(m_ToolbarConfMgr.Toolbar.Clone(), m_ToolbarConfMgr.FilePath);

                    var popup = m_Host.Extension.CreatePopupWindow <CommandManagerForm>();
                    popup.Control.DataContext           = vm;
                    popup.Control.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner;

                    if (popup.ShowDialog() == true)
                    {
                        try
                        {
                            m_ToolbarConfMgr.Toolbar  = vm.ToolbarInfo;
                            m_ToolbarConfMgr.FilePath = vm.ToolbarSpecificationPath;

                            if (m_ToolbarConfMgr.SettingsChanged)
                            {
                                m_ToolbarConfMgr.SaveSettings();
                            }

                            if (m_ToolbarConfMgr.ToolbarChanged)
                            {
                                m_ToolbarConfMgr.SaveToolbar();

                                //TODO: make this message SOLIDWORKS specific only as other CAD systems might have different conditions for loading of toolbar
                                m_Msg.ShowInformation("Toolbar settings have been changed. Restart SOLIDWORKS to load the command manager and menu. If commands in the toolbar have been changed (added or removed) then it might be required to restart SOLIDWORKS twice for the changes to be applied");
                            }
                        }
                        catch (Exception ex)
                        {
                            m_Logger.Log(ex);
                            m_Msg.ShowError(ex, "Failed to save toolbar specification");
                        }
                    }
                    break;
                }
            }
            catch (Exception ex)
            {
                m_Logger.Log(ex);
                m_Msg.ShowError(ex, "Unknown error");
                m_Logger.Log(ex);
            }
        }
예제 #10
0
 private void TryEnableAddIns(List <string> guids)
 {
     try
     {
         if (guids?.Any() == true)
         {
             SwApplicationFactory.EnableAddInsStartup(guids);
         }
     }
     catch (Exception ex)
     {
         m_Logger.Log(ex);
     }
 }
예제 #11
0
파일: SwAddInEx.cs 프로젝트: persadewh/xcad
        public bool ConnectToSW(object ThisSW, int cookie)
        {
            m_IsDisposed = false;

            try
            {
                var app = ThisSW as ISldWorks;
                AddInId = cookie;

                if (app.IsVersionNewerOrEqual(Enums.SwVersion_e.Sw2015))
                {
                    app.SetAddinCallbackInfo2(0, this, AddInId);
                }
                else
                {
                    app.SetAddinCallbackInfo(0, this, AddInId);
                }

                m_Application = new SwApplication(app);

                m_Application.FirstStartupCompleted += OnStartupCompleted;

                var svcCollection = GetServicesCollection();

                ConfigureServices?.Invoke(this, svcCollection);
                OnConfigureServices(svcCollection);

                m_SvcProvider = svcCollection.CreateProvider();

                Logger = m_SvcProvider.GetService <IXLogger>();

                m_Application.Init(svcCollection);

                Logger.Log("Loading add-in");

                SwMacroFeatureDefinition.Application = m_Application;

                m_CommandManager = new SwCommandManager(Application, AddInId, m_SvcProvider, this.GetType().GUID);

                Connect?.Invoke(this);
                OnConnect();

                return(true);
            }
            catch (Exception ex)
            {
                Logger.Log(ex);
                return(false);
            }
        }
        /// <summary>
        /// Logs error
        /// </summary>
        /// <param name="logger">Logger</param>
        /// <param name="ex">Exception</param>
        /// <param name="stackTrace">True to log stack trace</param>
        /// <param name="severity">Severity of the message</param>
        public static void Log(this IXLogger logger, Exception ex, bool stackTrace = true, LoggerMessageSeverity_e severity = LoggerMessageSeverity_e.Error)
        {
            var msg           = new StringBuilder();
            var stackTraceMsg = new StringBuilder();

            ParseExceptionLog(ex, msg, stackTraceMsg, stackTrace);

            logger.Log(msg.ToString(), severity);

            if (stackTrace)
            {
                logger.Log(stackTraceMsg.ToString(), LoggerMessageSeverity_e.Debug);
            }
        }
예제 #13
0
        public bool TryRunMacroCommand(Triggers_e trigger, CommandMacroInfo macroInfo, IXDocument targetDoc, string workDir)
        {
            try
            {
                m_Logger.Log($"Invoking '{trigger}' trigger for '{macroInfo.Title}'", LoggerMessageSeverity_e.Debug);

                var eventType = GetEventType(trigger);

                var eventArgs = new MacroRunningArguments(macroInfo, targetDoc)
                {
                    Cancel = false
                };

                m_ToolbarModuleProxy.CallMacroRunning(eventType, eventArgs);

                if (!eventArgs.Cancel)
                {
                    var opts = eventArgs.MacroInfo.UnloadAfterRun ? MacroRunOptions_e.UnloadAfterRun : MacroRunOptions_e.Default;

                    var macroPath = m_FilePathResolver.Resolve(eventArgs.MacroInfo.MacroPath, workDir);

                    m_Logger.Log($"Running macro '{macroPath}' with arguments '{eventArgs.MacroInfo.Arguments}'", LoggerMessageSeverity_e.Debug);

                    var entryPoint = eventArgs.MacroInfo.EntryPoint;

                    if (entryPoint == null)
                    {
                        throw new UserException($"Entry point is not specified for macro '{macroInfo.Title}'");
                    }

                    m_Runner.RunMacro(m_App, macroPath,
                                      new MacroEntryPoint(entryPoint.ModuleName, entryPoint.SubName),
                                      opts, eventArgs.MacroInfo.Arguments, null);

                    return(true);
                }
                else
                {
                    m_Logger.Log($"Trigger '{trigger}' for '{macroInfo.Title}' invoking cancelled", LoggerMessageSeverity_e.Debug);
                    return(false);
                }
            }
            catch (Exception ex)
            {
                m_Logger.Log(ex);
                m_MsgSvc.ShowError(ex, $"Failed to run a macro '{macroInfo.Title}' on trigger '{trigger}'");
                return(false);
            }
        }
예제 #14
0
        public bool Execute()
        {
            var startTime = DateTime.Now;

            try
            {
                m_CurrentCancellationToken = new CancellationTokenSource();
                var cancellationToken = m_CurrentCancellationToken.Token;

                using (var prg = m_App.CreateProgress())
                {
                    LogMessage("Preparing job");

                    var jobItems = PrepareJob();

                    JobSet?.Invoke(jobItems, startTime);

                    for (int i = 0; i < jobItems.Length; i++)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        var jobItem = jobItems[i];

                        prg.SetStatus($"Processing {jobItem.FilePath}");

                        var res = TryProcessFile(jobItem, cancellationToken);

                        ProgressChanged?.Invoke(jobItem, res);
                        prg.Report((double)(i + 1) / (double)jobItems.Length);
                    }
                }

                return(true);
            }
            catch (OperationCanceledException)
            {
                throw new JobCancelledException();
            }
            catch (Exception ex)
            {
                m_Logger.Log(ex);
                return(false);
            }
            finally
            {
                JobCompleted?.Invoke(DateTime.Now - startTime);
            }
        }
예제 #15
0
        private void OnConnect()
        {
            CreateContainer();

            m_Msg    = Resolve <IMessageService>();
            m_Logger = Resolve <IXLogger>();

            m_ToolbarProxy = Resolve <IToolbarModuleProxy>();
            m_ToolbarProxy.RequestMacroRunning += OnRequestMacroRunning;

            m_ToolbarConfMgr = Resolve <IToolbarConfigurationManager>();

            m_Host.RegisterCommands <Commands_e>(OnCommandClick);

            try
            {
                m_ToolbarConfMgr.Load();
                var workDir = Path.GetDirectoryName(m_ToolbarConfMgr.FilePath);
                LoadCommands(m_ToolbarConfMgr.Toolbar, workDir);
            }
            catch (Exception ex)
            {
                m_Logger.Log(ex);
                m_Msg.ShowError(ex, "Failed to load Toolbar+ commands");
            }
        }
예제 #16
0
        private void OnCommandClick(Commands_e spec)
        {
            switch (spec)
            {
            case Commands_e.RunStandAlone:
                try
                {
                    var exportPath = Path.GetFullPath(Path.Combine(
                                                          Path.GetDirectoryName(this.GetType().Assembly.Location), @"..\..\exportplus.exe"));

                    if (File.Exists(exportPath))
                    {
                        System.Diagnostics.Process.Start(exportPath);
                    }
                    else
                    {
                        throw new FileNotFoundException("Failed to find the path to executable");
                    }
                }
                catch (Exception ex)
                {
                    m_Logger.Log(ex);
                    m_Msg.ShowError("Failed to run Batch+");
                }
                break;
            }
        }
예제 #17
0
 public object DeserializeValue(string val)
 {
     try
     {
         if (!string.IsNullOrEmpty(val))
         {
             var feat = (IFeature)((ISwDrawing)m_Draw).Drawing.FeatureByName(val);
             if (feat != null)
             {
                 var skPict = (ISketchPicture)feat.GetSpecificFeature2();
                 return(((ISwDrawing)m_Draw).CreateObjectFromDispatch <ISwObject>(skPict));
             }
             else
             {
                 throw new Exception("Failed to find the picture");
             }
         }
         else
         {
             throw new Exception("Value is empty");
         }
     }
     catch (Exception ex)
     {
         m_Logger.Log(ex);
         return(null);
     }
 }
예제 #18
0
        /// <summary>
        /// Logs error
        /// </summary>
        /// <param name="ex">Exception</param>
        public static void Log(this IXLogger logger, Exception ex, bool stackTrace = true)
        {
            var msg = new StringBuilder();

            ParseExceptionLog(ex, msg, stackTrace);

            logger.Log(msg.ToString());
        }
예제 #19
0
        public void Init()
        {
            try
            {
                if (!m_IsInit)
                {
                    m_JobHandle = CreateJobObject(IntPtr.Zero, null);

                    if (m_JobHandle == IntPtr.Zero)
                    {
                        throw new Exception("Failed to create job handle");
                    }

                    var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION()
                    {
                        BasicLimitInformation = new JOBOBJECT_BASIC_LIMIT_INFORMATION()
                        {
                            LimitFlags = 0x2000
                        }
                    };

                    var length          = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
                    var extendedInfoPtr = Marshal.AllocHGlobal(length);

                    Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

                    if (!SetInformationJobObject(m_JobHandle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length))
                    {
                        throw new Exception(string.Format("Unable to set information.  Error: {0}", Marshal.GetLastWin32Error()));
                    }

                    m_Logger.Log($"Job initiated: {m_JobHandle}", LoggerMessageSeverity_e.Debug);
                    m_IsInit = true;
                }
                else
                {
                    throw new Exception("Job is already initialized");
                }
            }
            catch (Exception ex)
            {
                m_Logger.Log(ex);
                throw;
            }
        }
예제 #20
0
        private string[] TryLoadRecentFiles()
        {
            string[] recentFiles = null;

            try
            {
                if (File.Exists(m_RecentFilesPath))
                {
                    recentFiles = File.ReadAllLines(m_RecentFilesPath);
                }
            }
            catch (Exception ex)
            {
                m_Logger.Log(ex);
            }

            return(recentFiles ?? new string[0]);
        }
예제 #21
0
        public void TryInitHandlers(IXDocument doc)
        {
            var handlers = new List <IDocumentHandler>();

            foreach (var handlerInfo in m_Handlers)
            {
                try
                {
                    CreateHandler(doc, handlerInfo, handlers);
                }
                catch (Exception ex)
                {
                    m_Logger.Log(ex);
                }
            }

            m_DocsMap.Add(doc, handlers);
        }
예제 #22
0
 private void OnInsertQrCodePageClosing(PageCloseReasons_e reason, PageClosingArg arg)
 {
     if (reason == PageCloseReasons_e.Okay)
     {
         try
         {
             if (string.IsNullOrEmpty(m_QrDataProvider.GetData(m_CurDrawing, m_CurInsertQrCodePageData.Source)))
             {
                 throw new UserException("Data for QR code is empty");
             }
         }
         catch (Exception ex)
         {
             m_Logger.Log(ex);
             arg.Cancel       = true;
             arg.ErrorMessage = ex.ParseUserError();
         }
     }
 }
예제 #23
0
        public void TryInitHandlers(IXDocument doc)
        {
            var handlers = new List <IDocumentHandler>();

            foreach (var type in m_Handlers.Keys)
            {
                try
                {
                    var handler = CreateHandler(doc, type);
                    handlers.Add(handler);
                }
                catch (Exception ex)
                {
                    m_Logger.Log(ex);
                }
            }

            m_DocsMap.Add(doc, handlers);
        }
예제 #24
0
        public void CreateCommandGroups(CustomToolbarInfo toolbarInfo, string workDir)
        {
            const string COMMAND_GROUP_TITLE_TEMPLATE = "Toolbar+ Command Group";
            const string COMMAND_TITLE_TEMPLATE       = "Toolbar+ Command";

            m_WorkDir = workDir;

            var usedCommandGroupNames = new List <string>();
            var usedCommandNames      = new List <string>();

            if (toolbarInfo?.Groups != null)
            {
                foreach (var grp in toolbarInfo.Groups
                         .Where(g => g.Commands?.Any(c => c.Triggers.HasFlag(Triggers_e.Button)) == true))
                {
                    var cmdGrp = new CommandGroupInfoSpec(grp, m_IconsProviders, m_PathResolver, m_WorkDir);

                    ResolveEmptyName(cmdGrp.Info, COMMAND_GROUP_TITLE_TEMPLATE, usedCommandGroupNames, out string grpTitle, out string grpTooltip);
                    cmdGrp.Title   = grpTitle;
                    cmdGrp.Tooltip = grpTooltip;

                    foreach (var cmd in cmdGrp.Commands)
                    {
                        ResolveEmptyName(((CommandItemInfoSpec)cmd).Info, COMMAND_TITLE_TEMPLATE, usedCommandNames, out string cmdTitle, out string cmdTooltip);
                        cmd.Title   = cmdTitle;
                        cmd.Tooltip = cmdTooltip;
                    }

                    m_Logger.Log($"Adding command group: {cmdGrp.Title} [{cmdGrp.Id}]. Commands: {string.Join(", ", cmdGrp.Commands.Select(c => $"{c.Title} [{c.UserId}]").ToArray())}", XCad.Base.Enums.LoggerMessageSeverity_e.Debug);

                    var cmdGrpCad = m_AddIn.CommandManager.AddCommandGroup(cmdGrp);

                    cmdGrpCad.CommandClick        += OnCommandClick;
                    cmdGrpCad.CommandStateResolve += OnCommandStateResolve;
                }

                LoadToggleStateResolvers(
                    toolbarInfo.Groups.SelectMany(
                        g => g.Commands ?? Enumerable.Empty <CommandMacroInfo>())
                    .Where(m => m.Triggers.HasFlag(Triggers_e.ToggleButton) && m.ToggleButtonStateCodeType != ToggleButtonStateCode_e.None));
            }
        }
예제 #25
0
 private void TryAddProcessToJob(IXApplication app)
 {
     try
     {
         m_JobMgr.AddProcess(app.Process);
     }
     catch (Exception ex)
     {
         m_Logger.Log(ex);
     }
 }
예제 #26
0
        public IMacroResult Run(object appDisp, string macroPath, string moduleName,
                                string subName, int opts, IMacroParameter param, bool cacheReg = false)
        {
            var app = CastApplication(appDisp);

            var macro = app.OpenMacro(macroPath);

            GetMacroParametersManager(true, out RotRegister newReg, out IMacroParameterManager macroParamsMgr);

            if (newReg != null)
            {
                if (cacheReg)
                {
                    if (m_Register != null)
                    {
                        try
                        {
                            m_Register.Dispose();
                        }
                        catch (Exception ex)
                        {
                            m_Logger.Log(ex);
                        }
                    }

                    m_Register = newReg;
                }
            }

            try
            {
                var sessionId = CreateMacroSessionId(app, macro);
                macroParamsMgr.PushParameter(sessionId, param);

                try
                {
                    macro.Run(new MacroEntryPoint(moduleName, subName), (MacroRunOptions_e)opts);
                }
                finally
                {
                    macroParamsMgr.TryRemoveParameter(sessionId, param);
                }
            }
            finally
            {
                if (newReg != null && !cacheReg)
                {
                    newReg.Dispose();
                }
            }

            return(param.Result);
        }
예제 #27
0
 private IMacroRunner TryCreateMacroRunner()
 {
     try
     {
         return((IMacroRunner)Activator.CreateInstance(Type.GetTypeFromProgID(MacroRunnerProgId)));
     }
     catch (Exception ex)
     {
         m_Logger.Log(ex);
         return(null);
     }
 }
예제 #28
0
        //NOTE: it is not safe to dispatch the pointer to IModelDoc2 as for assembly documents it can cause RPC_E_WRONG_THREAD when retrieved on EndDispatch
        internal void Dispatch(string title, string path)
        {
            lock (m_Lock)
            {
                m_Logger.Log($"Adding '{title}' to the dispatch queue", LoggerMessageSeverity_e.Debug);

                m_ModelsDispatchQueue.Add(new ModelInfo()
                {
                    Title = title,
                    Path  = path
                });

                if (!m_DocsDispatchQueue.Any())
                {
                    DispatchAllModels();
                }
            }
        }
예제 #29
0
        private ObservableCollection <QrCodeInfo> ReadQrCodeData()
        {
            ObservableCollection <QrCodeInfo> data = null;

            try
            {
                using (var stream = m_Drawing.TryOpenStream(STREAM_NAME, AccessType_e.Read))
                {
                    if (stream != null)
                    {
                        m_Logger.Log("Reading QR code data", LoggerMessageSeverity_e.Debug);

                        using (var reader = new StreamReader(stream))
                        {
                            data = m_Serializer.ReadSettings <ObservableCollection <QrCodeInfo> >(
                                reader, new PictureValueSerializer(m_Logger, m_Drawing));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                m_Logger.Log(ex);
            }

            if (data != null)
            {
                var usedPictures = new List <IXObject>();

                for (int i = data.Count - 1; i >= 0; i--)
                {
                    if (data[i].Picture == null)
                    {
                        data.RemoveAt(i);
                        m_Logger.Log($"Removed dangling QR code data at index {i}", LoggerMessageSeverity_e.Debug);
                    }
                    //As we serialize names of the features (removing and readding QR code may cause duplication in the data which is not recognized as dangling)
                    else if (usedPictures.Find(p => p.Equals(data[i].Picture)) != null)
                    {
                        data.RemoveAt(i);
                        m_Logger.Log($"Removed duplicate QR code data at index {i}", LoggerMessageSeverity_e.Debug);
                    }
                    else
                    {
                        usedPictures.Add(data[i].Picture);
                    }
                }
            }
            else
            {
                data = new ObservableCollection <QrCodeInfo>();
            }

            data.CollectionChanged += OnDataCollectionChanged;

            Init(data);

            return(data);
        }
        public override void PostProcessControls(IEnumerable <IPropertyManagerPageControlEx> ctrls)
        {
            var selBoxes = ctrls.OfType <PropertyManagerPageSelectionBoxControl>().ToArray();

            var autoAssignSelMarksCtrls = selBoxes
                                          .Where(s => s.SelectionBox.Mark == -1).ToList();

            var assignedMarks = ctrls.OfType <PropertyManagerPageSelectionBoxControl>()
                                .Except(autoAssignSelMarksCtrls).Select(c => c.SelectionBox.Mark).ToList();

            ValidateMarks(assignedMarks);

            if (selBoxes.Length == 1)
            {
                if (autoAssignSelMarksCtrls.Any())
                {
                    autoAssignSelMarksCtrls[0].SelectionBox.Mark = 0;
                }
            }
            else
            {
                int index = 0;

                autoAssignSelMarksCtrls.ForEach(c =>
                {
                    int mark;
                    do
                    {
                        mark = (int)Math.Pow(2, index);
                        index++;
                    } while (assignedMarks.Contains(mark));

                    c.SelectionBox.Mark = mark;
                });
            }

            m_Logger.Log($"Assigned selection box marks: {string.Join(", ", selBoxes.Select(s => s.SelectionBox.Mark).ToArray())}", LoggerMessageSeverity_e.Debug);
        }