public static void RunCheck() { if (Checker == null) { return; } if (RestartPending) { return; } UpdateInfo update = null; if (Program.UIInvoker != null && Program.UIInvoker.InvokeRequired) { update = Checker.FindUpdate(); } else //If we're running on the UI thread { ProgressWorker.Execute(ui => { ui.Caption = "Searching for updates..."; update = Checker.FindUpdate(); }, false); } if (update == null || !UIInvoke(() => ApplyUpdate(update))) { timer.Start(); //If we didn't find an update, or if the update wasn't applied, check again later } }
public bool Publish() { using (var rsa = GetRSA()) { if (rsa == null) { return(false); } bool succeeded = false; ProgressWorker.Execute(ui => { ui.Caption = "Creating directory..."; FtpClient.Default.CreateDirectory(remoteBaseFolder); GatherFiles(ui, rsa); xml.Add(new XElement("Files", allFiles.Select(uf => uf.ToXml()))); DeleteOldFiles(ui); UploadFiles(ui); UploadXml(ui); succeeded = true; }, false); return(succeeded); } }
private void uploadAdBlank_ItemClick(object sender, ItemClickEventArgs e) { var row = gridView.GetFocusedRow() as MelaveMalkaInfo; string filePath; using (var dialog = new OpenFileDialog { Filter = "PDF Files (*.pdf)|*.pdf|All Files|*.*", Title = "Select " + row.Year + " Ad Blank" }) { if (dialog.ShowDialog(this) == DialogResult.Cancel) { return; } filePath = dialog.FileName; } if (!filePath.Contains(row.Year.ToString(CultureInfo.InvariantCulture))) { if (!Dialog.Warn("Are you sure that " + filePath + " is the " + row.Year + " ad blank?")) { return; } } ProgressWorker.Execute(progress => { progress.Caption = "Uploading " + Path.GetFileName(filePath); FtpClient.Default.UploadFile(row.AdBlankPath, filePath, progress); }, cancellable: false); }
private void importSources_ListItemClick(object sender, ListItemClickEventArgs e) { var source = importers[e.Index]; using (var openDialog = new OpenFileDialog { Filter = source.Filter, Title = "Load " + source.Name }) { if (openDialog.ShowDialog(MdiParent) == DialogResult.Cancel) { return; } SynchronizationContext uiThread = SynchronizationContext.Current; try { using (AppFramework.Current.DataContext.BeginLoadData(uiThread)) ProgressWorker.Execute( MdiParent, progress => source.Import(openDialog.FileName, uiThread, progress), cancellable: true ); } catch (Exception ex) { Dialog.ShowError("An error occurred while importing payments.\r\n" + ex.GetBaseException().Message); } peopleView.BestFitColumns(); } }
///<summary>Saves any changes made to the Singularity DataContext.</summary> public void SaveDatabase() { Debug.Assert(SyncContext.Tables.Any(), "There aren't any TableSynchronizers!"); if (!HasDataChanged) { return; } ProgressWorker.Execute(SyncContext.WriteData, cancellable: true); }
private void emailTemplateList_ListItemClick(object sender, ListItemClickEventArgs e) { var actualCallers = ConfirmSendEmailTemplate(); if (actualCallers == null) { return; } Program.LoadTables(MelaveMalkaInfo.Schema, MelaveMalkaSeat.Schema, MelaveMalkaInvitation.Schema); //Used by the templates var template = emailTemplateList.Strings[e.Index]; ProgressWorker.Execute(progress => { progress.Maximum = actualCallers.Count * 2; //Two steps per caller foreach (var caller in actualCallers) { if (progress.WasCanceled) { return; } progress.Caption = "Creating spreadsheet for " + caller.Name; string attachmentPath; do { attachmentPath = Path.GetTempFileName(); File.Delete(attachmentPath); attachmentPath = Path.ChangeExtension(attachmentPath, ".xls"); //OleDB cannot write XLS with other extensions } while (File.Exists(attachmentPath)); try { caller.CreateCallList(attachmentPath); if (progress.WasCanceled) { return; } progress.Progress++; progress.Caption = "Emailing " + caller.Name; using (var message = razor.CreateMessage(caller, template)) { message.From = Email.JournalAddress; message.To.Add(caller.EmailAddresses); //Comma-separated string message.Attachments.Add(new Attachment(attachmentPath, new ContentType { MediaType = "application/vnd.ms-excel", Name = "Call List for " + caller.Name + ".xls" })); Email.Default.Send(message); } } finally { File.Delete(attachmentPath); } progress.Progress++; } }, true); }
private void pushData_ItemClick(object sender, ItemClickEventArgs e) { var syncContext = CreateServerContext(); DBManager.PushData(Program.Current.DataContext, syncContext.DataContext); if (syncContext.Tables.Any(t => t.Changes.Any())) { ProgressWorker.Execute(syncContext.WriteData, cancellable: false); } }
private void doImport_ItemClick(object sender, ItemClickEventArgs e) { using (AppFramework.Current.DataContext.BeginLoadData()) ProgressWorker.Execute(MdiParent, progress => { progress.Maximum = AppFramework.Table <StagedPerson>().Rows.Count; foreach (var source in AppFramework.Table <StagedPerson>().Rows) { Person target; progress.Progress++; if (source.Person != null) { target = source.Person; progress.Caption = $"Importing {source.FullName} to {target.FullName}"; } else { progress.Caption = $"Importing {source.FullName} as new person"; target = new Person { Address = source.Address, City = source.City, FullName = source.FullName, HerName = source.HerName, HisName = source.HisName, LastName = source.LastName, Phone = source.Phone, State = source.State, Zip = source.Zip, Salutation = "", Source = "Migration", }; AppFramework.Table <Person>().Rows.Add(target); } foreach (var payment in source.StagedPayments) { AppFramework.Table <Payment>().Rows.Add(new Payment { Account = payment.Account, Amount = payment.Amount, CheckNumber = payment.CheckNumber, Comments = payment.Comments, Company = payment.Company, Date = payment.Date, Method = payment.Method, Person = target, Modifier = "Migration", // TODO: Change ExternalId to string and always set it. ExternalSource = "Migration", ExternalId = int.TryParse(payment.ExternalId, out var id) ? id : new int?() }); }
///<summary>Reads any changes from the database server.</summary> public void RefreshDatabase() { Debug.Assert(SyncContext.Tables.Any(), "There aren't any TableSynchronizers!"); var threadContext = SynchronizationContext.Current; ProgressWorker.Execute(progress => { if (HasDataChanged) { SyncContext.WriteData(progress); } progress.Caption = "Reading database"; progress.Maximum = -1; SyncContext.ReadData(threadContext); }, cancellable: false); }
void SendBills() { var exceptions = new List <KeyValuePair <Person, SmtpException> >(); var successes = new List <StatementMessage>(people.Length); PageBuilder.Prepare(emailTemplate.Text, startDate.DateTime); ProgressWorker.Execute(ui => { ui.Maximum = people.Length; foreach (var person in people) { ui.Caption = "Emailing " + person.VeryFullName; ui.Progress++; if (ui.WasCanceled) { return; } using (var message = PageBuilder.CreateMessage(person, emailTemplate.Text, startDate.DateTime)) { if (message == null) { continue; } message.To.AddRange(person.EmailAddresses.Select(e => e.MailAddress)); try { Email.Hosted.Send(message); successes.Add(message); } catch (SmtpException ex) { exceptions.Add(new KeyValuePair <Person, SmtpException>(person, ex)); } } } }, true); foreach (var info in successes) //The table can only be modified on the UI thread. { info.LogStatement(); } if (exceptions.Any()) { XtraMessageBox.Show("The following errors occurred while sending the emails:\r\n\r\n • " + exceptions.Join("\r\n\r\n • ", kvp => kvp.Key.FullName + ": " + kvp.Value.Message), "Shomrei Torah Billing", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
DataSyncContext CreateServerContext() { var context = new DataContext(); var syncContext = new DataSyncContext(context, new SqlServerSqlProvider(databases.SelectedConnector)); //Add all of the tables that we actually use. foreach (var ts in Program.Current.SyncContext.Tables.SortDependencies(ts => ts.Table.Schema)) { var table = ts.Table.Schema.CreateTable(); context.Tables.AddTable(table); syncContext.Tables.AddMapping(ts.Mapping); } ProgressWorker.Execute(ui => { ui.Caption = "Reading " + databases.SelectedItem.Caption; syncContext.ReadData(); }, cancellable: false); return(syncContext); }
private void sendSelected_ItemClick(object sender, ItemClickEventArgs args) { bindingSource.EndEdit(); //Commit any changes in the editor. (Very important; otherwise, any changes made since the last time it lost focus will not be sent) #region Validation var recipient = SelectedInvitee; if (recipient == null) { return; } if (recipient.AdAmount > 0) { Dialog.ShowError(recipient.Person.FullName + " already gave an ad."); return; } if (String.IsNullOrWhiteSpace(recipient.EmailSubject) || String.IsNullOrWhiteSpace(recipient.EmailSource)) { Dialog.ShowError("Please enter an email to send."); return; } if (recipient.ReminderEmails.Any(e => e.Date.Date == DateTime.Today)) { if (!Dialog.Warn(recipient.Person.FullName + " have already been emailed today.\r\nAre you sure you want to send another email?")) { return; } } else { if (!Dialog.Confirm("Would you like to email " + recipient.Person.FullName + "?")) { return; } } #endregion ProgressWorker.Execute(progress => { progress.Maximum = -1; progress.Caption = "Emailing " + recipient.Person.FullName; SendEmail(recipient); }, false); }
///<summary>Ensures that a set of tables are loaded in the DataContext.</summary> public static void LoadTables(IEnumerable <TableSchema> schemas) { var allSchemas = new HashSet <TableSchema>(); foreach (var schema in schemas.Where(s => Current.DataContext.Tables[s] == null)) { allSchemas.Add(schema); allSchemas.UnionWith(schema.GetDependencies()); } if (allSchemas.Count == 0) { return; //All of the tables are already loaded } var tables = allSchemas .SortDependencies() .Except(Current.DataContext.Tables.Select(t => t.Schema)) //Must be called after SortDependencies, since sorting requires all dependencies .Select(ts => ts.CreateTable()) .ToList(); //Calculated columns can use child rows. I must add the //tables in reverse order to allow the RowDependencies //to register handlers for the child tables. tables.Reverse(); tables.ForEach(Current.DataContext.Tables.AddTable); var syncers = tables.ConvertAll(t => new TableSynchronizer(t, SchemaMapping.GetPrimaryMapping(t.Schema), Current.SyncContext.SqlProvider)); syncers.ForEach(Current.SyncContext.Tables.Add); var threadContext = SynchronizationContext.Current; ProgressWorker.Execute(ui => { if (Current.HasDataChanged) { Current.SyncContext.WriteData(ui); //I must save before loading in case a parent row was deleted. (The DB is expected to cascade) } ui.Maximum = -1; ui.Caption = "Loading " + tables.Join(", ", t => t.Schema.Name); Current.SyncContext.ReadData(threadContext); //I must refresh everything to pick up potential changes in parent rows }, false); }
void createDoc_Click(object sender, EventArgs e) { DefaultDuplexMode = duplexMode.Checked; var stmts = SelectedStatements; StatementGenerator.Prepare(stmts); ProgressWorker.Execute(ui => StatementGenerator.CreateBills(stmts, ui, duplexMode.Checked), true); if (DialogResult.Yes == XtraMessageBox.Show("Would you like to log these statements?", "Shomrei Torah Billing", MessageBoxButtons.YesNo, MessageBoxIcon.Question)) { foreach (var statement in stmts) { statement.LogStatement(); } } if (cancel.Text != "Close" && mailingDocuments.ItemLinks.Any()) { XtraMessageBox.Show("To create mailing labels or envelopes, click the down arrow next to Create Documents.", "Shomrei Torah Billing", MessageBoxButtons.OK, MessageBoxIcon.Information); } cancel.Text = "Close"; }
private void sendAll_ItemClick(object sender, ItemClickEventArgs args) { bindingSource.EndEdit(); //Commit any changes in the editor. (Very important; otherwise, any changes made since the last time it lost focus will not be sent) var allRecipients = ConfirmSendAll(); if (allRecipients == null) { return; } ProgressWorker.Execute(progress => { progress.Maximum = allRecipients.Count; foreach (var recipient in allRecipients) { progress.Caption = "Emailing " + recipient.Person.FullName; progress.Progress++; SendEmail(recipient); if (progress.WasCanceled) { return; } } }, true); }
public static void Execute() { //Before deleting people, we need to check that //they aren't used by any child tables, to avoid //violating foreign key constraints. Therefore, //I load all child tables here. var missingTables = Person.Schema.ChildRelations.Select(cr => cr.ChildSchema); if (missingTables.Any()) { Program.LoadTables(missingTables); } else { Program.Current.RefreshDatabase(); } using (var fileDialog = new OpenFileDialog { Filter = "Excel Files (*.xls, *.xlsx)|*.xls;*.xlsx|All Files|*.*", Title = "Open YK Directory" }) { if (fileDialog.ShowDialog() == DialogResult.Cancel) { return; } bool workerSucceeded = false; DataTable ykData; var processedRows = CreateProcessedTable(); try { ProgressWorker.Execute(ui => { ui.Caption = "Opening " + Path.GetFileName(fileDialog.FileName); ykData = OpenFile(fileDialog.FileName); ui.Caption = "Processing " + ykData.TableName; var masterDirectory = Program.Current.DataContext.Table <Person>(); ui.Maximum = ykData.Rows.Count; for (int i = 0; i < ykData.Rows.Count; i++) { if (ui.WasCanceled) { return; } ui.Progress = i; var ykRow = ykData.Rows[i]; var ykid = Convert.ToInt32(ykRow["IDNUM"], CultureInfo.InvariantCulture); var ykPerson = ImportRow(ykRow); var mdRow = FindPerson(masterDirectory, ykData, ykPerson, ykid); Guid?personId; MatchState state; if (mdRow == null) { personId = null; state = MatchState.Added; //TODO: Match manually added people. } else if (ykPerson.IsUnequal(mdRow)) { personId = mdRow.Id; state = MatchState.Updated; } else { personId = mdRow.Id; state = MatchState.Identical; } var row = processedRows.Rows.Add( (object)personId ?? DBNull.Value, ykid, ykPerson.FullName, ykPerson.HisName, ykPerson.HerName, ykPerson.LastName, ykPerson.Address, ykPerson.City, ykPerson.State, ykPerson.Zip, ykPerson.Phone, mdRow == null ? null : mdRow["TotalPledged"], DefaultActions[state], state ); if (mdRow != null && mdRow.LastName != ykPerson.LastName) { row["Action"] = ImportAction.Add; } } ui.Caption = "Scanning for deleted people"; ui.Maximum = masterDirectory.Rows.Count; for (int i = 0; i < masterDirectory.Rows.Count; i++) { if (ui.WasCanceled) { return; } ui.Progress = i; var mdRow = masterDirectory.Rows[i]; if (processedRows.Select("PersonId = '" + mdRow.Id + "'").Length > 0) { continue; //Skip people we've already added. } var state = mdRow.YKID.HasValue ? MatchState.Deleted : MatchState.NonYK; var action = DefaultActions[state]; //Don't delete people who have any kind of child records if (action == ImportAction.Delete && Person.Schema.ChildRelations.Any( cr => Program.Current.DataContext.Tables[cr.ChildSchema] != null && //Skip tables that haven't been loaded mdRow.ChildRows(cr).Any() )) { action = ImportAction.Ignore; } //TODO: Try to match custom people processedRows.Rows.Add( mdRow.Id, null, //YKID here is new YKID; there isn't any mdRow.FullName, mdRow.HisName, mdRow.HerName, mdRow.LastName, mdRow.Address, mdRow.City, mdRow.State, mdRow.Zip, mdRow.Phone, mdRow["TotalPledged"], action, state ); } ui.Caption = "Displaying grid"; workerSucceeded = !ui.WasCanceled; }, true); } catch (TargetInvocationException ex) { XtraMessageBox.Show("Couldn't open " + Path.GetFileName(fileDialog.FileName) + ".\r\n" + ex.InnerException, "Shomrei Torah Billing", MessageBoxButtons.OK, MessageBoxIcon.Error); } if (!workerSucceeded) { return; } new YKImporter(processedRows).ShowDisposingDialog(); } }
public static void Export(int hebrewYear, bool includeנקודות) { ProgressWorker.Execute(ui => { MSWord.Visible = true; var document = MSWord.Documents.Add(); ui.Caption = "Creating document"; Range range; try { MSWord.ScreenUpdating = false; document.PageSetup.TopMargin = 13; document.PageSetup.BottomMargin = 10; range = document.Range(); range.Font.Name = "Calibri"; range.Font.NameBi = "David"; range.Font.Size = 12; range.Font.SizeBi = 13; range.ParagraphFormat.Space1(); var bracha = document.Range(); bracha.InsertAfter("\n"); if (includeנקודות) { bracha.Text = "בָּרוּךְ אַתָּה ה' אֱלֹקינוּ מֶלֶךְ הָעוֹלָם אֲשֶׁר קִדְּשָׁנוּ בְּמִצְוֹתָיו וְצִוָּנוּ עַל סְפִירַת הָעוֹמֶר"; } else { bracha.Text = "ברוך אתה ה' אלקינו מלך העולם אשר קדשנו במצותיו וציונו על ספירת העומר"; } bracha.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphCenter; bracha.ParagraphFormat.SpaceAfter = 2; range = document.Range(); range.Collapse(WdCollapseDirection.wdCollapseEnd); var table = document.Tables.Add(range, 49, 3); table.Range.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphLeft; table.Range.ParagraphFormat.SpaceAfter = 0; table.Columns[1].Width = MSWord.InchesToPoints(.32f); table.Columns[2].Width = MSWord.InchesToPoints(2.15f); table.Columns[3].Width = MSWord.InchesToPoints(4.5f); var border = table.Borders[WdBorderType.wdBorderHorizontal]; border.LineStyle = WdLineStyle.wdLineStyleSingle; border.LineWidth = WdLineWidth.wdLineWidth025pt; border.Color = WdColor.wdColorDarkBlue; foreach (var side in new[] { WdBorderType.wdBorderTop, WdBorderType.wdBorderRight, WdBorderType.wdBorderBottom, WdBorderType.wdBorderLeft }) { border = table.Borders[side]; border.LineStyle = WdLineStyle.wdLineStyleThickThinMedGap; border.LineWidth = WdLineWidth.wdLineWidth150pt; border.Color = WdColor.wdColorBlack; } MSWord.ScreenRefresh(); ui.Maximum = 49; ui.Caption = "Writing chart"; for (var date = Program.OmerStart(hebrewYear); date.Info.OmerDay != -1; date++) { var index = date.Info.OmerDay; var text = includeנקודות ? date.Info.OmerTextנקוד : date.Info.OmerText; if (ui.WasCanceled) { return; } ui.Progress = index; table.Rows[index].Range.Font.Color = (WdColor)ColorTranslator.ToOle(Program.GetColor(index)); table.Cell(index, 1).Range.Text = index.ToString(CultureInfo.CurrentCulture); table.Cell(index, 2).Range.Text = date.EnglishDate.AddDays(-1).ToString("dddd \"night\", MMMM d", CultureInfo.CurrentCulture); table.Cell(index, 3).Range.Text = text; } } finally { MSWord.ScreenUpdating = true; } range = document.Range(); range.Collapse(WdCollapseDirection.wdCollapseEnd); //range.Text = String.Format(CultureInfo.CurrentUICulture, // "ספירת העומר for {0} ({1}) | By Schabse S. Laks", // (hebrewYear - 5000).ToHebrewString(HebrewNumberFormat.LetterQuoted), // Program.OmerStart(hebrewYear).EnglishDate.Year); WriteFooter(range, hebrewYear); MSWord.Activate(); }, cancellable: true); }
///<summary>Called on the UI thread to download and apply an update.</summary> ///<returns>True if the update was downloaded and applied.</returns> public static bool ApplyUpdate(UpdateInfo update) { if (Updater.RestartPending) { if (DialogResult.Yes == XtraMessageBox.Show("An update has already been downloaded.\r\nDo you want to restart the program and apply the update?", "Shomrei Torah Billing", MessageBoxButtons.YesNo, MessageBoxIcon.Question)) { Application.Exit(); } return(true); } UserLookAndFeel.Default.SkinName = "Office 2010 Blue"; //This must be set here in case we're on the splash thread at launch time. SkinManager.EnableFormSkins(); var parent = (IWin32Window)Program.UIInvoker; //For some reason, I must set the parent to MainForm or it won't be properly modal. var description = update.GetChanges(Checker.CurrentVersion); if (DialogResult.No == XtraMessageBox.Show(parent, "An update is available. Do you want to install it?\r\n\r\nThis update provides the following features:\r\n" + description, "Shomrei Torah Billing", MessageBoxButtons.YesNo, MessageBoxIcon.Question)) { return(false); } string updatePath = null; try { if (!ProgressWorker.Execute(parent, ui => { ui.Caption = "Downloading update..."; updatePath = update.DownloadFiles(existingFiles: Program.AppDirectory, organizationId: Config.ReadAttribute("Updates", "OrganizationId"), ui: ui); if (!ui.WasCanceled) { ui.Caption = "Applying update"; } }, true)) { return(false); } } catch (TargetInvocationException tex) { Exception ex = tex.GetBaseException(); if (!Debugger.IsAttached) { Email.Warn("Billing Update Error", "New Version: " + update.NewVersion + "\r\nDescription: \r\n" + description + "\r\n\r\n" + ex); } XtraMessageBox.Show(parent, "An error occurred while downloading the update.\r\n" + ex, "Shomrei Torah Billing", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } if (updatePath == null) { return(false); } //Updates will (usually) include a billing config file, //but I don't want a billing config file at home. if (!File.Exists(Path.Combine(Program.AppDirectory, "ShomreiTorah.Billing.Config.xml"))) { File.Delete(Path.Combine(updatePath, "ShomreiTorah.Billing.Config.xml")); //File.Delete doesn't throw FileNotFound } if (Program.Current.SyncContext != null) //If an update was applied at launch, the database will not have been loaded yet. { Program.Current.SaveDatabase(); } UpdateChecker.ApplyUpdate(updatePath, Program.AppDirectory); try { Email.Default.Send(Email.AlertsAddress, Email.AdminAddress, Environment.UserName + " updated ShomreiTorah.Billing on " + Environment.MachineName, "Old version: " + Checker.CurrentVersion + "\r\n" + "New version: " + update.NewVersion + " (Published on " + update.PublishDate.ToString("F", CultureInfo.InvariantCulture) + ")\r\n\r\nPath: " + Program.AppDirectory + "\r\n\r\nChanges:\r\n" + description + "\r\n\r\nUpdated files:\r\n • " + update.Files.Where(f => !f.Matches(Program.AppDirectory)).Join("\r\n • ", f => f.RelativePath) + "\r\n\r\nPre-update files:\r\n • " + String.Join("\r\n • ", Directory.GetFiles(Program.AppDirectory, "*.*", SearchOption.AllDirectories)) , false); } catch (SmtpException) { } timer.Stop(); //In case we were called by the Update button in MainForm RestartPending = true; var cea = new CancelEventArgs(); Application.Exit(cea); if (cea.Cancel) { XtraMessageBox.Show(parent, "The update will be applied after you exit the program.", "Shomrei Torah Billing"); } return(true); }
private void MailingExport_ItemClick(object sender, ItemClickEventArgs e) { ProgressWorker.Execute(ui => MailingGenerator.CreateMailing(SelectedStatements, e.Item.Caption + ".docx", ui), true); cancel.Text = "Close"; }