public DesignMainViewModel() { var now = TimeMerge.Utils.Calculations.NowTime; var mainViewModel = this; mainViewModel.Year = now.Year; mainViewModel.Month = now.Month; mainViewModel.SettingsPanelVM.UserID = "D0C22AC4-B7BE-4B5E-B0CC-B99419E822B4"; mainViewModel.UserName = "******"; MonthData = new TimeMerge.Model.SingleMonthData(); MonthData.YearMonth = now; var webDavConnection = new WebDavConnection(); webDavConnection.Init(SettingsPanelVM.UserID, "dummyLogin", "001122", "dummyWebDavUrl"); mainViewModel.MonthViewModel = new SingleMonthViewModel(mainViewModel, new NoActionOnWebRequest(), webDavConnection); mainViewModel.MonthViewModel.SetMonthData(MonthData); DayData = new TimeMerge.Model.SingleDayData(); DayData.Day = 1; DayData.IsNoWorkDay = false; DayData.WorkInterruptions[0].StartTime = now - TimeSpan.FromHours(1); DayData.WorkInterruptions[0].EndTime = now + TimeSpan.FromHours(7.5); DayData.WorkInterruptions[0].CorrectionEndTime = now + TimeSpan.FromHours(8); DayData.WorkInterruptions[0].Type = TimeMerge.Model.WorkInterruption.WorkInterruptionType.OBED; SingleDayViewModel dayVM = new SingleDayViewModel(); dayVM.ReInit(DayData, mainViewModel.MonthViewModel, MonthData.Days); mainViewModel.MonthViewModel.Days.Add(dayVM); var holidayData = new TimeMerge.Model.SingleDayData(); holidayData.Day = 2; holidayData.IsNoWorkDay = true; SingleDayViewModel dayVM2 = new SingleDayViewModel(); dayVM2.ReInit(holidayData, mainViewModel.MonthViewModel, MonthData.Days); mainViewModel.MonthViewModel.Days.Add(dayVM2); }
private void removeSingleDayVM_onGuiThread(SingleDayViewModel dayVM) { App.Current.Dispatcher.Invoke(new Action(() => this.Days.Remove(dayVM))); }
public bool LoadData() { // Load settings this.IsBalanceASummaryThroughAllMonths = Properties.Settings.Default.IsBalanceASummaryThroughAllMonths; // Load data bool loadFromFileWentOK = false; object monthDataRaw = null; XmlSerializer serializer = new XmlSerializer(typeof(SingleMonthData), new Type[] { typeof(SingleMonthData) }); using (XmlTextReader xmlReader = new XmlTextReader(getThisMonthLocalDataFilename())) { try { monthDataRaw = serializer.Deserialize(xmlReader); } catch (InvalidOperationException) { // OK, this month's local cache doesn't need to exist yet } finally { xmlReader.Close(); } } if (monthDataRaw is SingleMonthData) { SingleMonthData monthData = monthDataRaw as SingleMonthData; // Copy over the loaded SingleMonthData instance to our own, local instance of SingleMonthData. // Try recycling each ViewModel if possible, it will improve performance. foreach (SingleDayData dayData in monthData.Days) { var vmToUpdate = from SingleDayViewModel selectedDayVM in this.Days where selectedDayVM.Day == dayData.Day select selectedDayVM; SingleDayViewModel dayVM = vmToUpdate.SingleOrDefault(); if (dayVM != null) { // can recycle dayVM.ReInit(dayData, this, this._monthData.Days); } else { // can't recycle dayVM = new SingleDayViewModel(); dayVM.ReInit(dayData, this, this._monthData.Days); addSingleDayVM_onGuiThread(dayVM); // always access 'this.Days' collection on the Dispatcher thread } } // Get rid of any superfluous single day ViewModels (e.g. if previously shown month had 31 days, // but the month we're going to shown now has only 30 or even less days. if (monthData.Days.Count > 0) { List <SingleDayViewModel> viewmodelsToDelete = new List <SingleDayViewModel>(); for (int dayToDelete = monthData.Days.Count + 1; dayToDelete <= this.Days.Count; dayToDelete++) { var toDelete = from SingleDayViewModel selectedDayVM in this.Days where selectedDayVM.Day == dayToDelete select selectedDayVM; SingleDayViewModel vmToDelete = toDelete.SingleOrDefault(); if (vmToDelete != null) { viewmodelsToDelete.Add(vmToDelete); } } // Delete all collected day VMs at once, since this deletion directly alters elements of 'this.Days.Count' foreach (var vmToDelete in viewmodelsToDelete) { removeSingleDayVM_onGuiThread(vmToDelete); // always access 'this.Days' collection on the Dispatcher thread } } this.TransferFromPrevMonth = monthData.TransferFromPrevMonth; loadFromFileWentOK = true; } return(loadFromFileWentOK); }
private void extractTimesTable(string tableContent) { int year = _monthData.YearMonth.Year; int month = _monthData.YearMonth.Month; var daysCreatedList = new List <SingleDayViewModel>(); int lastDayNumberNeeded = 1; Regex exTableRows = new Regex("<tr>.*?<td class=\"r\">(.*?)</td>(.*?)</tr>"); var matches = exTableRows.Matches(tableContent); foreach (Match oneRowMatch in matches) { int dayNumber = 0; bool isNoWorkDay = false; if (oneRowMatch.Groups.Count > 1 && oneRowMatch.Groups[1].Captures.Count > 0) { var dayNumberString = oneRowMatch.Groups[1].Captures[0].Value; if (dayNumberString.Contains(">") && dayNumberString.Contains("<")) { isNoWorkDay = true; dayNumberString = dayNumberString.Replace(">", ""); dayNumberString = dayNumberString.Replace("<", ""); } else if (dayNumberString.StartsWith("=") && dayNumberString.EndsWith("=")) { isNoWorkDay = true; dayNumberString = dayNumberString.Replace("=", ""); } if (!Int32.TryParse(dayNumberString, out dayNumber)) { continue; // cannot parse day number! } lastDayNumberNeeded = dayNumber; } if (oneRowMatch.Groups.Count > 2 && oneRowMatch.Groups[2].Captures.Count > 0) { string oneDayData = oneRowMatch.Groups[2].Captures[0].Value; oneDayData = oneDayData.Replace(" ", " "); Regex exFourthToNinethCell = new Regex("(<td.*?>(.*?)</td>.*?){47}"); var tdMatches = exFourthToNinethCell.Matches(oneDayData); foreach (Match oneTdMatch in tdMatches) { if (oneTdMatch.Groups.Count > 1 && oneTdMatch.Groups[2].Captures.Count > 46) { bool isNewDayVMToBeAdded = false; IEnumerable <SingleDayViewModel> dayVMsMatchingThisDay = from oneDayVM in _days where oneDayVM.Day == dayNumber select oneDayVM; var dayVM = dayVMsMatchingThisDay.FirstOrDefault(); if (dayVM == null) { isNewDayVMToBeAdded = true; dayVM = new SingleDayViewModel(); } TimeMerge.Model.SingleDayData dayData = getOrCreateSingleDayData(dayNumber); dayVM.ReInit(dayData, this, this._monthData.Days); dayVM.IsNoWorkDay = isNoWorkDay; dayVM.IsChangeByUserAllowed = false; dayVM.WorkSpan0Start = oneTdMatch.Groups[2].Captures[3].Value; dayVM.WorkSpan0End = oneTdMatch.Groups[2].Captures[4].Value; dayVM.WorkSpan1Start = oneTdMatch.Groups[2].Captures[5].Value; dayVM.WorkSpan1End = oneTdMatch.Groups[2].Captures[6].Value; dayVM.WorkSpan2Start = oneTdMatch.Groups[2].Captures[7].Value; dayVM.WorkSpan2End = oneTdMatch.Groups[2].Captures[8].Value; dayVM.WorkSpan3Start = oneTdMatch.Groups[2].Captures[9].Value; dayVM.WorkSpan3End = oneTdMatch.Groups[2].Captures[10].Value; dayVM.WorkSpan4Start = oneTdMatch.Groups[2].Captures[11].Value; dayVM.WorkSpan4End = oneTdMatch.Groups[2].Captures[12].Value; dayVM.WorkSpan5Start = oneTdMatch.Groups[2].Captures[13].Value; dayVM.WorkSpan5End = oneTdMatch.Groups[2].Captures[14].Value; dayVM.WorkSpan6Start = oneTdMatch.Groups[2].Captures[15].Value; dayVM.WorkSpan6End = oneTdMatch.Groups[2].Captures[16].Value; dayVM.WorkSpan7Start = oneTdMatch.Groups[2].Captures[17].Value; dayVM.WorkSpan7End = oneTdMatch.Groups[2].Captures[18].Value; dayVM.WorkSpan8Start = oneTdMatch.Groups[2].Captures[19].Value; dayVM.WorkSpan8End = oneTdMatch.Groups[2].Captures[20].Value; dayVM.WorkSpan9Start = oneTdMatch.Groups[2].Captures[21].Value; dayVM.WorkSpan9End = oneTdMatch.Groups[2].Captures[22].Value; dayVM.Interrupt0Start = oneTdMatch.Groups[2].Captures[23].Value; dayVM.Interrupt0End = oneTdMatch.Groups[2].Captures[24].Value; dayVM.Interrupt0Type = WorkInterruption.ParseInterruptionType(oneTdMatch.Groups[2].Captures[25].Value); dayVM.Interrupt1Start = oneTdMatch.Groups[2].Captures[26].Value; dayVM.Interrupt1End = oneTdMatch.Groups[2].Captures[27].Value; dayVM.Interrupt1Type = WorkInterruption.ParseInterruptionType(oneTdMatch.Groups[2].Captures[28].Value); dayVM.Interrupt2Start = oneTdMatch.Groups[2].Captures[29].Value; dayVM.Interrupt2End = oneTdMatch.Groups[2].Captures[30].Value; dayVM.Interrupt2Type = WorkInterruption.ParseInterruptionType(oneTdMatch.Groups[2].Captures[31].Value); dayVM.Interrupt3Start = oneTdMatch.Groups[2].Captures[32].Value; dayVM.Interrupt3End = oneTdMatch.Groups[2].Captures[33].Value; dayVM.Interrupt3Type = WorkInterruption.ParseInterruptionType(oneTdMatch.Groups[2].Captures[34].Value); dayVM.Interrupt4Start = oneTdMatch.Groups[2].Captures[35].Value; dayVM.Interrupt4End = oneTdMatch.Groups[2].Captures[36].Value; dayVM.Interrupt4Type = WorkInterruption.ParseInterruptionType(oneTdMatch.Groups[2].Captures[37].Value); dayVM.Interrupt5Start = oneTdMatch.Groups[2].Captures[38].Value; dayVM.Interrupt5End = oneTdMatch.Groups[2].Captures[39].Value; dayVM.Interrupt5Type = WorkInterruption.ParseInterruptionType(oneTdMatch.Groups[2].Captures[40].Value); dayVM.Interrupt6Start = oneTdMatch.Groups[2].Captures[41].Value; dayVM.Interrupt6End = oneTdMatch.Groups[2].Captures[42].Value; dayVM.Interrupt6Type = WorkInterruption.ParseInterruptionType(oneTdMatch.Groups[2].Captures[43].Value); dayVM.Interrupt7Start = oneTdMatch.Groups[2].Captures[44].Value; dayVM.Interrupt7End = oneTdMatch.Groups[2].Captures[45].Value; dayVM.Interrupt7Type = WorkInterruption.ParseInterruptionType(oneTdMatch.Groups[2].Captures[46].Value); dayVM.IsChangeByUserAllowed = true; if (isNewDayVMToBeAdded) { daysCreatedList.Add(dayVM); } } } } } IEnumerable <SingleDayViewModel> daysDeleted = from oneDayVM in _days where oneDayVM.Day > lastDayNumberNeeded select oneDayVM; var daysDeletedList = daysDeleted.ToList(); // make the enumeration of IEnumerable<> happen right now, so that '_days' collection changes won't affect the 'Remove()' calls below App.Current.Dispatcher.BeginInvoke(new Action(() => { foreach (SingleDayViewModel singleDayVM in daysCreatedList) { _days.Add(singleDayVM); } foreach (SingleDayViewModel singleDayVM in daysDeletedList) { _days.Remove(singleDayVM); } })); }
private string getWorkSpanToolTip(int workSpanIndex, bool isInterruption = false) { var now = TimeMerge.Utils.Calculations.NowTime; DateTime startWithCorrections, endWithCorrections; TimeSpan workSpanDuration; string hintZeroTimeHit = string.Empty; bool hasCorrections = false; if (isInterruption) { hasCorrections = _dayData.WorkInterruptions[workSpanIndex].HasCorrectionData; startWithCorrections = _dayData.WorkInterruptions[workSpanIndex].GetStartTimeIncludingCorrections(); endWithCorrections = _dayData.WorkInterruptions[workSpanIndex].GetEndTimeIncludingCorrections(); workSpanDuration = _dayData.WorkInterruptions[workSpanIndex].Duration; } else { hasCorrections = _dayData.WorkSpans[workSpanIndex].HasCorrectionData; startWithCorrections = _dayData.WorkSpans[workSpanIndex].GetStartTimeIncludingCorrections(); endWithCorrections = _dayData.WorkSpans[workSpanIndex].GetEndTimeIncludingCorrections(); workSpanDuration = _dayData.WorkSpans[workSpanIndex].Duration; } string virtualTimeEnding = getWorkSpanVirtualTimeEnding(workSpanIndex, isInterruption); string tooltip = null; if (hasCorrections) { DateTime start, end; if (isInterruption) { start = _dayData.WorkInterruptions[workSpanIndex].StartTime; end = _dayData.WorkInterruptions[workSpanIndex].EndTime; } else { start = _dayData.WorkSpans[workSpanIndex].StartTime; end = _dayData.WorkSpans[workSpanIndex].EndTime; } tooltip = string.Format(CultureInfo.InvariantCulture, "Korekcia z {0:t} - {1:t}", start, end); if (isInterruption && _dayData.WorkInterruptions[workSpanIndex].CorrectedType.HasValue) { tooltip += string.Format(", z typu {0}", _dayData.WorkInterruptions[workSpanIndex].CorrectedType.GetValueOrDefault()); } } // When "virtual time ending" is in effect, show some additional info about how long to be in work yet today if (!string.IsNullOrEmpty(virtualTimeEnding)) { // Get current time, ignoring the seconds part var nowWithNoSeconds = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0); DateTime calculationBaseTime; if (workSpanDuration.TotalMinutes > 0) { calculationBaseTime = nowWithNoSeconds; // current whole-month balance was calculated based on current time } else { calculationBaseTime = startWithCorrections; // current whole-month balance was calculated based on WorkSpan start time } // Calculate when the current minuses will be get rid of, at what time of today DateTime timeWhenZeroIsHit = calculationBaseTime.AddMinutes(-this._parentMonthVM.BalanceWholeMonth.TotalMinutes); TimeSpan lunchDuration = this.GetLunchDuration(); // If the +0:00 zero balance cannot be achieved today (e.g. too much minuses), then show no info about it if (timeWhenZeroIsHit.DayOfYear == calculationBaseTime.DayOfYear) { // The +0:00 zero balance can be achieved today, when user will be at work until 'timeWhenZeroIsHit' if (!string.IsNullOrEmpty(tooltip)) { tooltip += System.Environment.NewLine; } if (this._parentMonthVM.BalanceWholeMonth.TotalMinutes < 0) { hintZeroTimeHit += String.Format("+0:00 sa dosiahne o {1:t}", System.Environment.NewLine, timeWhenZeroIsHit); if (lunchDuration.Ticks == 0) { DateTime timeWhenZeroIsHitWithLunch = timeWhenZeroIsHit + TimeSpan.FromMinutes(SingleDayData.LunchTimeMinimalTime); if (timeWhenZeroIsHitWithLunch.DayOfYear == calculationBaseTime.DayOfYear) { hintZeroTimeHit += string.Format(" (s obedom o {0:t})", timeWhenZeroIsHitWithLunch); } } } else { hintZeroTimeHit += String.Format("+0:00 bol dosiahnutý o {1:t}", System.Environment.NewLine, timeWhenZeroIsHit); if (lunchDuration.Ticks == 0) { DateTime timeWhenZeroIsHitWithLunch = timeWhenZeroIsHit + TimeSpan.FromMinutes(SingleDayData.LunchTimeMinimalTime); if (timeWhenZeroIsHitWithLunch.DayOfYear == calculationBaseTime.DayOfYear) { hintZeroTimeHit += string.Format(" (s obedom o {0:t})", timeWhenZeroIsHitWithLunch); } } } tooltip += hintZeroTimeHit; } } // Notes for the day string notes = Utils.NotesContentFormatter.NotesWithIndent(0, NotesContent); if (!string.IsNullOrWhiteSpace(notes)) { if (!string.IsNullOrWhiteSpace(tooltip)) { tooltip += "\r\n"; } tooltip += notes; } _parentMonthVM.SetTimeSpanHintForZeroHit(SingleDayViewModel.GetSpanGlobalID(this.Day, workSpanIndex, isInterruption), hintZeroTimeHit); return(tooltip); }