bool IsNotInStore(EditableDebater d) { bool notEqual = true; foreach (object[] row in store) { notEqual = notEqual && !d.Equals(row[0]); } return(notEqual); }
protected virtual void OnBtnDebaterAddClicked(object sender, EventArgs e) { if (newDebaterPath != null) { return; } entryDebatersFilter.Text = ""; EditableDebater d = new EditableDebater(); newDebaterPath = store.GetPath(store.AppendValues(d)); treeDebaters.SetCursor(ConvertStorePathToModelPath(newDebaterPath), treeDebaters.Columns[0], true); }
void RemoveDebaterFromRounds(TreeIter storeIter) { EditableDebater d = (EditableDebater)store.GetValue(storeIter, 0); // removing a judge from existing rounds is easy // but everything else is not (consider non-complete teams...) // so, we rely on the issued warning and hope the user knows // what to do if (!d.Role.IsJudge) { return; } foreach (RoundData round in Tournament.I.Rounds) { RoundDebater rd = round.AllJudges.Find(delegate(RoundDebater obj) { return(obj.Equals(d)); }); // if not found, continue! if (rd == null) { continue; } // d is Judge, so check Chair and Judges in rooms foreach (RoomData room in round.Rooms) { if (rd.Equals(room.Chair)) { room.Chair = null; } else { // if judge isn't there, can't be removed... room.Judges.Remove(rd); } } // remove from all judges round.AllJudges.Remove(rd); } }
int SortDebaters(TreeModel model, TreeIter a, TreeIter b, int col) { EditableDebater d_a = (EditableDebater)model.GetValue(a, 0); EditableDebater d_b = (EditableDebater)model.GetValue(b, 0); if (d_a != null && d_b != null) { ColumnInfo prop = columns[treeDebaters.Columns[col].Title]; IComparable c_a = prop.get(d_a); IComparable c_b = prop.get(d_b); int compare = c_a.CompareTo(c_b); int lastSortCol = editDebatersSettings.lastSortCol; if (lastSortCol != -1 && compare == 0) { ColumnInfo propLast = columns[treeDebaters.Columns[lastSortCol].Title]; IComparable c_a_last = propLast.get(d_a); IComparable c_b_last = propLast.get(d_b); SortType lastSortOrder = editDebatersSettings.lastSortOrder; if (treeDebaters.Columns[col].SortOrder == lastSortOrder) { return(c_a_last.CompareTo(c_b_last)); } else { return(-c_a_last.CompareTo(c_b_last)); } } else { return(compare); } } else { return(0); } }
int SortDebaters(TreeModel model, TreeIter a, TreeIter b, int col) { EditableDebater d_a = (EditableDebater)model.GetValue(a, 0); EditableDebater d_b = (EditableDebater)model.GetValue(b, 0); if (d_a != null && d_b != null) { string prop = treeDebaters.Columns[col].Title; IComparable c_a = (IComparable)d_a.GetType().InvokeMember(prop, BindingFlags.GetProperty, null, d_a, null); IComparable c_b = (IComparable)d_b.GetType().InvokeMember(prop, BindingFlags.GetProperty, null, d_b, null); int compare = c_a.CompareTo(c_b); int lastSortCol = editDebatersSettings.lastSortCol; if (lastSortCol != -1 && compare == 0) { string propLast = treeDebaters.Columns[lastSortCol].Title; IComparable c_a_last = (IComparable)d_a.GetType().InvokeMember(propLast, BindingFlags.GetProperty, null, d_a, null); IComparable c_b_last = (IComparable)d_b.GetType().InvokeMember(propLast, BindingFlags.GetProperty, null, d_b, null); SortType lastSortOrder = editDebatersSettings.lastSortOrder; if (treeDebaters.Columns[col].SortOrder == lastSortOrder) { return(c_a_last.CompareTo(c_b_last)); } else { return(-c_a_last.CompareTo(c_b_last)); } } else { return(compare); } } else { return(0); } }
void DoTheExport(MiscHelpers.TemplateType type) { TreeModel model = treeDebaters.Model; TreeIter iter; if (model.GetIterFirst(out iter)) { try { ITemplate tmpl = MiscHelpers.GetTemplate("debaters", type); ITmplBlock tmplDebaters = tmpl.ParseBlock("DEBATERS"); int n = 0; do { n++; TreeIter storeIter = ConvertModelIterToStoreIter(iter); EditableDebater d = (EditableDebater)store.GetValue(storeIter, 0); tmplDebaters.Assign("NUM", n.ToString()); tmplDebaters.Assign("NAME", d.Name.ToString()); tmplDebaters.Assign("CLUB", d.Club.ToString()); tmplDebaters.Assign("AGE", d.Age.ToString()); tmplDebaters.Assign("ROLE", EscapeString(d.Role.ToString(), type)); tmplDebaters.Assign("BLACKLIST", EscapeString(d.BlackList.ToString(), type)); tmplDebaters.Assign("WHITELIST", EscapeString(d.WhiteList.ToString(), type)); tmplDebaters.Assign("EXTRAINFO", EscapeString(d.ExtraInfo.ToString(), type)); tmplDebaters.Out(); }while(model.IterNext(ref iter)); MiscHelpers.AskShowTemplate(this, "Debaters successfully generated, see " + "pdfs/debaters.(pdf|csv)", MiscHelpers.MakeExportFromTemplate() ); } catch (Exception ex) { MiscHelpers.ShowMessage(this, "Could not export Debaters: " + ex.Message, MessageType.Error); } } }
protected virtual void OnBtnImportCSVClicked(object sender, System.EventArgs e) { if (cbOverwrite.Active) { if (MiscHelpers.AskYesNo(this, "This clears all " + "entered Data for " + "overwritten Debaters. " + "Continue?") == ResponseType.No) { return; } } // make a backup before! Tournament.I.Save(); // start import List <Debater> debaters = Tournament.I.Debaters; int line = 0; try { CsvReader csv = new CsvReader(new StreamReader(labelFile.Text), cbHasHeaders.Active, ',', '"', '\\', '#', ValueTrimmingOptions.All); int dups = 0; int ok = 0; while (csv.ReadNextRecord()) { line++; EditableDebater d = new EditableDebater(); d.Name = new Name(csv[sbFirstName.ValueAsInt], csv[sbLastName.ValueAsInt]); // Club try { if (cbCity.Active) { d.Club = new Club(csv[sbClub.ValueAsInt], csv[sbCity.ValueAsInt]); } else { d.Club = new Club(csv[sbClub.ValueAsInt]); } } catch { d.Club = new Club("None"); d.BlackList.RemoveClub("None"); } // Age or from Birthday try { if (cbAge.Active) { d.Age = uint.Parse(csv [sbAge.ValueAsInt]); } if (cbBirthday.Active) { DateTime bday = DateTime.ParseExact(csv[sbBirthday.ValueAsInt], entryBdayFormat.Text, null); DateTime now = DateTime.Today; int age = now.Year - bday.Year; if (bday > now.AddYears(-age)) { age--; } d.Age = (uint)age; } } catch {} // Role if (cbRole.Active) { if (rbTeamMember.Active) { d.Role = OPDtabData.Role.Parse(csv [sbRole.ValueAsInt]); } else if (rbJudge.Active) { int judgeQuality = 0; try { judgeQuality = (int)uint.Parse(csv[sbRole.ValueAsInt]); } catch {} d.Role.JudgeQuality = judgeQuality; } } // ExtraInfo d.ExtraInfo = entryExtraInfoDefault.Text; if (cbExtraInfo.Active) { d.ExtraInfo = csv[sbExtraInfo.ValueAsInt] == "" ? entryExtraInfoDefault.Text : csv[sbExtraInfo.ValueAsInt]; } // BlackList if (cbBlackList.Active) { d.BlackList = DebaterPattern.Parse(csv[sbBlackList.ValueAsInt]); } // save it int i = debaters.FindLastIndex(delegate(Debater de) { return(de.Equals(d)); }); if (i < 0) { debaters.Add(new Debater(d)); ok++; } else { Console.WriteLine("Duplicate: " + d + ", " + debaters[i]); dups++; if (cbOverwrite.Active) { debaters[i] = new Debater(d); ok++; } } } string action = cbOverwrite.Active ? "overwritten" : "discarded"; MiscHelpers.ShowMessage(this, "Imported " + ok + ", " + action + " " + dups + " duplicates.", MessageType.Info); } catch (Exception ex) { MiscHelpers.ShowMessage(this, "Error encountered in line " + line.ToString() + ": " + ex.Message, MessageType.Error); } }
protected void OnBtnSwapRolesClicked(object sender, EventArgs e) { TreePath[] r = treeDebaters.Selection.GetSelectedRows(); if (r.Length != 2) { MiscHelpers.ShowMessage(this, "Select exactly two Debaters to swap.", MessageType.Error); return; } TreeIter iter1; TreeIter iter2; if (!treeDebaters.Model.GetIter(out iter1, r[0]) || !treeDebaters.Model.GetIter(out iter2, r[1])) { // this should never happen return; } // get the references in the store TreeIter storeIter1 = ConvertModelIterToStoreIter(iter1); TreeIter storeIter2 = ConvertModelIterToStoreIter(iter2); EditableDebater d1 = (EditableDebater) store.GetValue(storeIter1, 0); EditableDebater d2 = (EditableDebater) store.GetValue(storeIter2, 0); // swapping it in the store Role tmp = d2.Role; d2.Role = d1.Role; d1.Role = tmp; // update in existing rounds (this is ugly due to our data model) // this resets the info about available judges... // any other approach wouldn't be future-proof foreach (RoundData round in Tournament.I.Rounds) { // clear all round results of the debaters in the store! d1.SetRoom(round.RoundName, null); d2.SetRoom(round.RoundName, null); // always create new instance for each round RoundDebater rd1 = new RoundDebater(d1); RoundDebater rd2 = new RoundDebater(d2); // search for d1, replace by d2 and vice versa // this should work since d1 and d2 have already swapped roles foreach (RoomData room in round.Rooms) { room.ReplaceRoomMember(rd1, RoundDebater.Dummy()); } foreach (RoomData room in round.Rooms) { room.ReplaceRoomMember(rd2, rd1); } foreach (RoomData room in round.Rooms) { room.ReplaceRoomMember(RoundDebater.Dummy(), rd2); } // update also allArrays, the following UpdateAllArrays // relies on at least consistent arrays round.ReplaceInAllArrays(rd1, RoundDebater.Dummy()); round.ReplaceInAllArrays(rd2, new RoundDebater(rd1)); round.ReplaceInAllArrays(RoundDebater.Dummy(), new RoundDebater(rd2)); // since complicated things can happen above // we make the arrays consistent by brute force // this creates many warnings that round results are cleared, // but the debaters are backed up in store here...complicated, as said round.UpdateAllArrays(); } // overwrite the changes with the changes from the store SaveDebaters(); // and reflect the possible reset of RoundResults ShowRanking.I.UpdateAll(); // tell the treeview to update, don't know why path and iter is necessary store.EmitRowChanged(store.GetPath(storeIter1), storeIter1); store.EmitRowChanged(store.GetPath(storeIter2), storeIter2); }
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); }); } } } }