/// <summary> /// Empties the TreeView and refills it with the contents of jobList. /// Current sorting/filtering remains unchanged. /// </summary> public void UpdateJobTable(List <JobDetails> jobs) { // This entire function is run on the Gtk main loop thread. // This may cause problems if another thread wants to modify a view at the same time, // but is probably better than the alternative, which is concurrent modification of live Gtk elements. Application.Invoke(delegate { // remember which column is being sorted. If the results are not sorted at all, order by start time ascending int sortIndex; SortType order; bool needToResort = sort.GetSortColumnId(out sortIndex, out order); store.Clear(); foreach (JobDetails job in jobs) { string startTimeString = job.StartTime == null ? DateTime.UtcNow.ToLocalTime().ToString() : ((DateTime)job.StartTime).ToLocalTime().ToString(); string endTimeString = job.EndTime == null ? "" : ((DateTime)job.EndTime).ToLocalTime().ToString(); string dispName = myJobsOnly ? job.DisplayName : job.DisplayName + " (" + job.Owner + ")"; string progressString = job.Progress < 0 ? "Work in progress" : Math.Round(job.Progress, 2).ToString() + "%"; string timeStr = job.CpuTime == TimeSpan.Zero ? "" : job.CpuTime.ToString(TimespanFormat); string durationStr = job.Duration() == TimeSpan.Zero ? "" : job.Duration().ToString(TimespanFormat); store.AppendValues(dispName, job.Id, job.State, job.NumSims.ToString(), progressString, startTimeString, endTimeString, durationStr, timeStr); } }); }
private int resultsSortFunc(TreeModel model, TreeIter a, TreeIter b) { SearchResult first = (SearchResult)model.GetValue(a, 0); SearchResult second = (SearchResult)model.GetValue(b, 0); int columnId; SortType order; if (resultsSort.GetSortColumnId(out columnId, out order)) { switch (columnId) { case 0: // File Name return(StringComparer.CurrentCulture.Compare(first.Name, second.Name)); case 7: // Size return(first.Size.CompareTo(second.Size)); case 8: // Sources int numberOfSourcesOne = (first.Type == SearchResultType.File) ? search.AllFileResults[first.InfoHash].Count : -1; int numberOfSourcesTwo = (second.Type == SearchResultType.File) ? search.AllFileResults[second.InfoHash].Count : -1; return(numberOfSourcesOne.CompareTo(numberOfSourcesTwo)); case 9: // Full Path return(StringComparer.CurrentCulture.Compare(first.FullPath, second.FullPath)); } } return(0); }
void SetSortColumn(int colNum) { TreeViewColumn col = treeDebaters.Columns[colNum]; col.SortIndicator = true; int sortCol; SortType sortOrder; TreeModelSort modelSort = treeDebaters.Model as TreeModelSort; modelSort.GetSortColumnId(out sortCol, out sortOrder); if (sortCol == colNum) { if (sortOrder == SortType.Ascending) { col.SortOrder = SortType.Descending; } else { col.SortOrder = SortType.Ascending; } } else { editDebatersSettings.lastSortCol = sortCol; editDebatersSettings.lastSortOrder = treeDebaters.Columns[sortCol].SortOrder; treeDebaters.Columns[sortCol].SortIndicator = false; col.SortOrder = SortType.Descending; } editDebatersSettings.sortCol = colNum; editDebatersSettings.sortOrder = col.SortOrder; modelSort.SetSortColumnId(colNum, col.SortOrder); }
void CellRendererEdited(CellRendererTextAdv sender, string pathStr, string newText, int colNum) { TreeModelSort model = (TreeModelSort)treeDebaters.Model; TreePath path = new TreePath(pathStr); TreeIter iter = TreeIter.Zero; model.GetIter(out iter, path); EditableDebater d = (EditableDebater)model.GetValue(iter, 0); try { ColumnInfo prop = columns[treeDebaters.Columns[colNum].Title]; // This parses the given new string, // and updates the data in store prop.parseAndSet(d, newText); // existing Debater: Update Data in (possibly) existing Rounds // tries to keep data consisting, but there's no guarantee // BlackList/WhiteList and ExtraInfo are not // used in RoundDebater, so skip this by condition colNum<4 if (newDebaterPath == null && colNum < 4) { var rd = new EditableDebater(d); var p = prop.get(d); // Only simple Renaming of Role is possible if Rounds exist if (colNum == 3 && Tournament.I.Rounds.Count > 0 && ((d.Role.IsTeamMember != rd.Role.IsTeamMember) || (d.Role.IsJudge != rd.Role.IsJudge))) { MiscHelpers.ShowMessage(this, "Changing Role from Judge to TeamMember (or vice versa)" + " is not possible since Rounds are already set.", MessageType.Error); // reset to old role... d.Role = rd.Role; return; } // check if new TeamName is already present if (colNum == 3 && d.Role.IsTeamMember) { int n = 0; foreach (object[] row in store) { EditableDebater d_ = (EditableDebater)row[0]; if (!d.Equals(d_) && d_.Role.TeamName == d.Role.TeamName) { n++; } } if (n == 3) { MiscHelpers.ShowMessage(this, "New TeamName is already present in three other Debaters.", MessageType.Error); // reset to old role... d.Role = rd.Role; return; } } // check for duplicate if (colNum < 3) { // need a temporary flag, throwing exceptions in delegates doesnt work... // the following flag stuff isn't elegant, but it should work bool flag = false; model.Foreach((model_, _, iter_) => { if (!iter.Equals(iter_)) { EditableDebater d_ = (EditableDebater)model_.GetValue(iter_, 0); if (d_.Equals(d)) { // reset to old value... prop.get(rd).Set(d); flag = true; return(true); } } return(false); }); if (flag) { throw new TargetInvocationException(new Exception("Debater exists.")); } } // keep data consistent in existing rounds foreach (RoundData round in Tournament.I.Rounds) { foreach (RoomData room in round.Rooms) { foreach (RoundDebater rd_ in room.GetRoomMembers()) { if (rd_ == null) { continue; } if (rd_.Equals(rd)) { p.UnsafeSetRoundDebater(rd_); } if (rd_.Role.TeamName == rd.Role.TeamName) { rd_.Role.TeamName = d.Role.TeamName; } } } if (rd.Role.IsTeamMember) { foreach (TeamData team in round.AllTeams) { foreach (RoundDebater rd_ in team) { if (rd_.Equals(rd)) { p.UnsafeSetRoundDebater(rd_); } if (rd_.Role.TeamName == rd.Role.TeamName) { rd_.Role.TeamName = d.Role.TeamName; } } } } else if (rd.Role.IsJudge) { foreach (RoundDebater rd_ in round.AllJudges) { if (rd_.Equals(rd)) { p.UnsafeSetRoundDebater(rd_); } } } } // Renaming TeamName needs extra Handling if (colNum == 3 && rd.Role.IsTeamMember && d.Role.IsTeamMember) { foreach (object[] row in store) { EditableDebater d_ = (EditableDebater)row[0]; if (d_.Role.TeamName == rd.Role.TeamName) { d_.Role.TeamName = d.Role.TeamName; } } } } // newDebater is entered... else if (newDebaterPath != null && colNum < 3) { // continue with entering data (goto next column) // as idle so that cells are resized GLib.Idle.Add(delegate { treeDebaters.SetCursor(ConvertStorePathToModelPath(newDebaterPath), treeDebaters.Columns[colNum + 1], true); return(false); }); } else if (newDebaterPath != null) { // new Debater entered completely (at least all necessary data) iter = TreeIter.Zero; if (store.GetIter(out iter, newDebaterPath)) { // as idle to prevent gtk critical (no idea why this happens) GLib.Idle.Add(delegate { store.Remove(ref iter); newDebaterPath = null; if (IsNotInStore(d)) { store.AppendValues(d); SaveDebaters(); } else { MiscHelpers.ShowMessage(this, "Debater exists.", MessageType.Error); } UpdateDebatersInfo(); btnDebaterAdd.GrabFocus(); return(false); }); } } // Gui stuff treeDebaters.ColumnsAutosize(); // ugly method of resorting the TreeSortModel... SortType st; int sortColumn; model.GetSortColumnId(out sortColumn, out st); if (st == SortType.Descending) { model.SetSortColumnId(sortColumn, SortType.Ascending); model.SetSortColumnId(sortColumn, SortType.Descending); } else { model.SetSortColumnId(sortColumn, SortType.Descending); model.SetSortColumnId(sortColumn, SortType.Ascending); } // save data from store if not adding new debater if (newDebaterPath == null) { SaveDebaters(); } } catch (TargetInvocationException e) { MessageDialog md = new MessageDialog(this, DialogFlags.Modal, MessageType.Error, ButtonsType.OkCancel, e.InnerException.Message + ". Try again?"); md.DefaultResponse = ResponseType.Ok; ResponseType r = (ResponseType)md.Run(); md.Destroy(); if (r == ResponseType.Ok) { // As Idle otherwise Editable isn't destroyed correctly GLib.Idle.Add(delegate { sender.TempEditString = newText; treeDebaters.SetCursor(path, treeDebaters.Columns[colNum], true); return(false); }); } else { if (newDebaterPath == null) { return; } iter = TreeIter.Zero; if (store.GetIter(out iter, newDebaterPath)) { // remove not finished new debater, // with idle call, // prevents Gtk critical filter model assertion. GLib.Idle.Add(delegate { newDebaterPath = null; store.Remove(ref iter); return(false); }); } } } }