public bool GetTaskDetailsByTask(DateTime existingTaskTime, out DateTime?taskEndDate, out string taskDescription, out string taskCategory, out bool taskTimeBillable) { DataRow[] candidateRows = logTable.Select("StartDateTime = #" + Utils.FormatDateFullTimeStamp(existingTaskTime) + "#"); if (candidateRows.Length == 1) { if (DBNull.Value.Equals(candidateRows[0]["EndDateTime"])) { taskEndDate = null; } else { taskEndDate = (DateTime?)candidateRows[0]["EndDateTime"]; } taskCategory = (string)candidateRows[0]["TaskCategory"]; taskDescription = (string)candidateRows[0]["TaskName"]; taskTimeBillable = (bool)candidateRows[0]["BillableFlag"]; return(true); } else { taskEndDate = null; taskCategory = ""; taskDescription = ""; taskTimeBillable = false; return(false); } }
public void ReadAutoCompletionDataFromDB() { DataRow[] recentRows = logTable.Select("StartDateTime > #" + Utils.FormatDateFullTimeStamp(DateTime.Now.AddDays(-30)) + "#"); foreach (DataRow recentRow in recentRows) { _autoCompletionCache.Feed((string)recentRow["TaskName"].ToString(), (string)recentRow["TaskCategory"], (bool)recentRow["BillableFlag"]); } }
private DataRow GetTaskRow(DateTime existingTaskTime) { DataRow[] candidateRows = logTable.Select("StartDateTime = #" + Utils.FormatDateFullTimeStamp(existingTaskTime) + "#"); if (candidateRows.Length == 1) { return(candidateRows[0]); } else { return(null); } }
private DataRow FindExistingInProgressTask(DateTime taskStartTime) { DataRow targetRow = null; DataRow[] candidateRows = logTable.Select("StartDateTime = #" + Utils.FormatDateFullTimeStamp(taskStartTime) + "# And EndDateTime Is Null"); if (candidateRows.Length == 0) { candidateRows = logTable.Select("StartDateTime Is Not Null And EndDateTime Is Null", "StartDateTime Desc"); } if (candidateRows.Length > 0) { DateTime matchStartTime = (DateTime)candidateRows[0]["StartDateTime"]; if (candidateRows.Length > 1) { MessageBox.Show(string.Format("More than one unfinished task found. Using more recent one, with original start date {0:yyyy-MM-dd HH:mm:ss}.", matchStartTime), "Multiple log entries", MessageBoxButtons.OK); } targetRow = candidateRows[0]; } return(targetRow); }
internal void Import(string sourceFileName) { /* * TODO: Add characterset auto-detection * AND TEST FOR "Bush hid the facts" BUG IN AUTO-DETECTION ROUTINE! * AND ADD REFERENCE TO THIS IN AUTO-DETECTION ROUTINE DESCRIPTION */ using (System.IO.StreamReader textReader = System.IO.File.OpenText(sourceFileName)) using (CsvReader importReader = new CsvReader(textReader, true, ',', '"', '"', '#', ValueTrimmingOptions.All, 0x1000)) { //other defaults for our accepted format: importReader.SupportsMultiline = true; importReader.SkipEmptyLines = true; importReader.DefaultParseErrorAction = ParseErrorAction.ThrowException; importReader.MissingFieldAction = MissingFieldAction.ReplaceByEmpty; string[] headers = importReader.GetFieldHeaders(); Dictionary <string, int> importColumnIDs = new Dictionary <string, int>(StringComparer.InvariantCultureIgnoreCase); bool abort = false; for (int i = 0; i < headers.Length && !abort; i++) { if (importColumnIDs.ContainsKey(headers[i])) { if (MessageBox.Show(string.Format("Duplicate column detected, name \"{0}\"! Ignore new column?", headers[i]), "Duplicate Column Name", MessageBoxButtons.OKCancel) == DialogResult.Cancel) { abort = true; } } else { if (headers[i].Equals("StartDateTime", StringComparison.InvariantCultureIgnoreCase) || headers[i].Equals("EndDateTime", StringComparison.InvariantCultureIgnoreCase) || headers[i].Equals("TaskCategory", StringComparison.InvariantCultureIgnoreCase) || headers[i].Equals("TaskName", StringComparison.InvariantCultureIgnoreCase) || headers[i].Equals("BillableFlag", StringComparison.InvariantCultureIgnoreCase) || headers[i].Equals("TimeTaken", StringComparison.InvariantCultureIgnoreCase) ) { importColumnIDs.Add(headers[i], i); } else if (MessageBox.Show(string.Format("Unsupported column detected, name \"{0}\"! Ignore new column?", headers[i]), "Unknown Column Name", MessageBoxButtons.OKCancel) == DialogResult.Cancel) { abort = true; } } } if (!abort && !importColumnIDs.ContainsKey("StartDateTime")) { MessageBox.Show("Required column \"StartDateTime\" not found in import file. Aborting.", "Missing column", MessageBoxButtons.OK); abort = true; } if (!abort && !importColumnIDs.ContainsKey("TaskName")) { MessageBox.Show("Required column \"TaskName\" not found in import file. Aborting.", "Missing column", MessageBoxButtons.OK); abort = true; } if (!abort && !importColumnIDs.ContainsKey("EndDateTime") && !importColumnIDs.ContainsKey("TimeTaken") ) { MessageBox.Show("Neither \"EndDateTime\" nor \"TimeTaken\" was found in import file; one or the other must be provided. Aborting.", "Missing column", MessageBoxButtons.OK); abort = true; } bool alwaysOverwriteOnMismatch = false; //main record import loop... while (!abort && importReader.ReadNextRecord()) { DateTime startTime; DateTime endTime = DateTime.MinValue; string taskCategory = null; string taskName; bool? taskBillable = null; double? providedTimeTaken = null; double? calculatedTimeTaken = null; long currentRowNumber = importReader.CurrentRecordIndex + 1; if (!DateTime.TryParse(importReader[importColumnIDs["StartDateTime"]], out startTime)) { MessageBox.Show(string.Format("Invalid \"StartDateTime\" value found, record number {0} in import file. Aborting.", currentRowNumber), "Invalid Value Found", MessageBoxButtons.OK); abort = true; } if (!abort && importColumnIDs.ContainsKey("EndDateTime")) { if (DateTime.TryParse(importReader[importColumnIDs["EndDateTime"]], out endTime)) { calculatedTimeTaken = (endTime - startTime).TotalHours; } else { MessageBox.Show(string.Format("Invalid \"EndDateTime\" value found, record number {0} in import file. Aborting.", currentRowNumber), "Invalid Value Found", MessageBoxButtons.OK); abort = true; } } if (importColumnIDs.ContainsKey("TaskCategory")) { taskCategory = importReader[importColumnIDs["TaskCategory"]]; } taskName = importReader[importColumnIDs["TaskName"]]; bool parsedBillable; if (bool.TryParse(importReader[importColumnIDs["BillableFlag"]], out parsedBillable)) { taskBillable = parsedBillable; } else { MessageBox.Show(string.Format("Invalid \"BillableFlag\" value found, record number {0} in import file. Aborting.", currentRowNumber), "Invalid Value Found", MessageBoxButtons.OK); abort = true; } if (!abort && importColumnIDs.ContainsKey("TimeTaken")) { double parsedTimeTaken = 0; if (double.TryParse(importReader[importColumnIDs["TimeTaken"]], out parsedTimeTaken)) { providedTimeTaken = parsedTimeTaken; endTime = startTime.AddHours(providedTimeTaken.Value); } else { MessageBox.Show(string.Format("Invalid \"TimeTaken\" value found, record number {0} in import file. Aborting.", currentRowNumber), "Invalid Value Found", MessageBoxButtons.OK); abort = true; } } if (calculatedTimeTaken != null && providedTimeTaken != null && Math.Abs(calculatedTimeTaken.Value - providedTimeTaken.Value) > 0.01 ) { MessageBox.Show(string.Format("Inconsistent \"EndDateTime\" and \"TimeTaken\" values found, record number {0} in import file. Aborting.", currentRowNumber), "Inconsistent Values Found", MessageBoxButtons.OK); abort = true; } if (!abort) { DataRow[] possibleMatch = logTable.Select("StartDateTime = #" + Utils.FormatDateFullTimeStamp(startTime) + "#"); if (possibleMatch.Length > 0) { if (possibleMatch[0]["EndDateTime"].ToString() == endTime.ToString() && (taskCategory == null || possibleMatch[0]["TaskCategory"].ToString() == taskCategory) && possibleMatch[0]["TaskName"].ToString() == taskName && (taskBillable == null || possibleMatch[0]["BillableFlag"].ToString() == taskBillable.Value.ToString()) ) { //Nothing to do, the import data exactly matches the existing data. } else { bool overWriteRecord = false; if (alwaysOverwriteOnMismatch) { overWriteRecord = true; } else { if (Dialogs.DismissableConfirmationWindow.ShowMessage("Overwrite Entry?", string.Format("Existing entry found matching import data for row {0}; click OK to overwrite the existing entry, or Cancel to abort the import.", currentRowNumber), out alwaysOverwriteOnMismatch) == DialogResult.OK) { overWriteRecord = true; } else { abort = true; } } if (overWriteRecord) { possibleMatch[0]["EndDateTime"] = endTime; possibleMatch[0]["TaskCategory"] = taskCategory; possibleMatch[0]["TaskName"] = taskName; if (taskBillable != null) { possibleMatch[0]["BillableFlag"] = taskBillable.Value; } possibleMatch[0]["TimeTaken"] = providedTimeTaken ?? calculatedTimeTaken; possibleMatch[0].AcceptChanges(); } } } else { DataRow newRow = logTable.NewRow(); newRow["StartDateTime"] = startTime; newRow["EndDateTime"] = endTime; newRow["TaskCategory"] = taskCategory; newRow["TaskName"] = taskName; if (taskBillable == null) { newRow["BillableFlag"] = true; } else { newRow["BillableFlag"] = taskBillable.Value; } newRow["TimeTaken"] = providedTimeTaken ?? calculatedTimeTaken; logTable.Rows.Add(newRow); } //TODO: Add consistency checks here like in UI edit. } } //everything went OK, save updated DB...? //TODO: consider reloading instead of saving, if we ended up aborting. SaveTimeTrackingDB(false); if (!abort) { MessageBox.Show("File imported successfully!", "Success", MessageBoxButtons.OK); } } }
internal void Export(string destinationFileName, DateTime fromDate, DateTime toDate, bool billableEntriesOnly) { string filterString = string.Format("StartDateTime >= #{0}# And StartDateTime < #{1}#", Utils.FormatDateFullTimeStamp(fromDate), Utils.FormatDateFullTimeStamp(toDate.AddDays(1))); if (billableEntriesOnly) { filterString += " And BillableFlag = True"; } Utils.ExportFilteredDataTableToCsv(logTable, destinationFileName, filterString); }
public double GetHoursTotals(DateTime fromDate, DateTime toDate, bool billableOnly) { string filterString = string.Format("StartDateTime >= #{0}# And StartDateTime < #{1}#", Utils.FormatDateFullTimeStamp(fromDate.Date), Utils.FormatDateFullTimeStamp(toDate.Date.AddDays(1))); if (billableOnly) { filterString += " And BillableFlag = True"; } return(GetComputedDouble("Sum(TimeTaken)", filterString)); }
private void UpdateControlDisplayConsistency() { //"Open Log Window" context strip option display if (this.Visible && openLogWindowToolStripMenuItem.Enabled) { openLogWindowToolStripMenuItem.Enabled = false; } if (!this.Visible && !_displayingDialog && !openLogWindowToolStripMenuItem.Enabled) { openLogWindowToolStripMenuItem.Enabled = true; } if (_displayingDialog && openLogWindowToolStripMenuItem.Enabled) { openLogWindowToolStripMenuItem.Enabled = false; } //buttons if (_taskInProgress && btn_Start.Enabled) { btn_Start.Enabled = false; } else if (!_taskInProgress && !btn_Start.Enabled) { btn_Start.Enabled = true; } if (!_taskInProgress && btn_Stop.Enabled) { btn_Stop.Enabled = false; } else if (_taskInProgress && !btn_Stop.Enabled) { btn_Stop.Enabled = true; } //systray context strip if (_taskInProgress && startTaskToolStripMenuItem.Enabled) { startTaskToolStripMenuItem.Enabled = false; } else if (!_taskInProgress && !startTaskToolStripMenuItem.Enabled) { startTaskToolStripMenuItem.Enabled = true; } if (!_taskInProgress && stopEditTaskToolStripMenuItem.Enabled) { stopEditTaskToolStripMenuItem.Enabled = false; } else if (_taskInProgress && !stopEditTaskToolStripMenuItem.Enabled) { stopEditTaskToolStripMenuItem.Enabled = true; } //datagridview context strip if (_taskInProgress && resumeTaskNowToolStripMenuItem.Enabled) { resumeTaskNowToolStripMenuItem.Enabled = false; } else if (!_taskInProgress && !resumeTaskNowToolStripMenuItem.Enabled) { resumeTaskNowToolStripMenuItem.Enabled = true; } if (!_taskInProgress && stopEditTaskToolStripMenuItem.Enabled) { stopEditTaskToolStripMenuItem.Enabled = false; } else if (_taskInProgress && !stopEditTaskToolStripMenuItem.Enabled) { stopEditTaskToolStripMenuItem.Enabled = true; } //icons if (_taskInProgress && notifyIcon1.Icon != TaskInProgressIcon) { notifyIcon1.Icon = TaskInProgressIcon; } else if (!_taskInProgress && notifyIcon1.Icon != NoTaskActiveIcon) { notifyIcon1.Icon = NoTaskActiveIcon; } if (_taskInProgress && this.Icon != TaskInProgressIcon) { this.Icon = TaskInProgressIcon; } else if (!_taskInProgress && this.Icon != NoTaskActiveIcon) { this.Icon = NoTaskActiveIcon; } //SysTray Balloon if (!_taskInProgress && !notifyIcon1.Text.Equals("Nano TimeLogger - no active task")) { notifyIcon1.Text = "Nano TimeLogger - no active task"; } //timer if (_taskInProgress && !timer_StatusUpdate.Enabled) { timer_StatusUpdate.Start(); } else if (!_taskInProgress && timer_StatusUpdate.Enabled) { timer_StatusUpdate.Stop(); } //datePicker if (!dateNavigator_LogFilter.MaxDate.Equals(DateTime.Today)) { dateNavigator_LogFilter.MaxDate = DateTime.Today; } //dataGridView filtering DateTime currentFilterDate = dateNavigator_LogFilter.DateValue; string currentFilterString = string.Format("StartDateTime >= #{0}# And StartDateTime < #{1}#", Utils.FormatDateFullTimeStamp(currentFilterDate), Utils.FormatDateFullTimeStamp(currentFilterDate.AddDays(1))); if ((dataSet1BindingSource.Filter == null || !dataSet1BindingSource.Filter.Equals(currentFilterString)) && dataSet1BindingSource.SupportsFiltering) { dataSet1BindingSource.Filter = currentFilterString; _displayedDayTotalHours = _databaseManager.GetHoursTotals(dateNavigator_LogFilter.DateValue, dateNavigator_LogFilter.DateValue, false); _displayedDayBillableHours = _databaseManager.GetHoursTotals(dateNavigator_LogFilter.DateValue, dateNavigator_LogFilter.DateValue, true); UpdateStatusDisplay(); } }