From 605c34a9f59ac16a1504e91e7f1cd9282652777d Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 5 Sep 2020 16:51:28 +1000 Subject: [PATCH] i implemented the filter and i never want to think about Gtk.TreeIter again --- MainWindow.cs | 74 +++++++++- YahooAuctionsItem.cs | 37 ++--- ui/main.glade | 327 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 355 insertions(+), 83 deletions(-) diff --git a/MainWindow.cs b/MainWindow.cs index 83b6f4d..8aa05e2 100755 --- a/MainWindow.cs +++ b/MainWindow.cs @@ -47,11 +47,13 @@ namespace Buypeeb { private Box selectionViewBox; private Label endingLabel; private bool queueActive; + private Dictionary filterChecks = new Dictionary(); // ...to here. static SemaphoreSlim taskLimit = new SemaphoreSlim(6); private Queue updateQueue = new Queue(); + private IEnumerable filterQuery; private YahooAuctionsItem selectedItem { get { @@ -106,13 +108,33 @@ namespace Buypeeb { this.selectionViewBox = (Box)builder.GetObject("SelectionViewBox"); this.endingLabel = (Label)builder.GetObject("LabelSelectedEnding"); + foreach (var name in new List { "Favourites", "NonFavourites", "Active", "Ended", "EndingToday", "EndingAfterToday", "WithWinPrice", "WithNoWinPrice" }) { + this.filterChecks.Add(name, (CheckButton)builder.GetObject($"CheckButtonFilter{name}")); + this.filterChecks[name].Active = false; + } + + // father forgive me for i have lynned + this.filterQuery = + from item in this.settings.watchlist.Values.ToList() + where (item.favourite != this.filterChecks["Favourites"].Active || + item.favourite == this.filterChecks["NonFavourites"].Active) && + (item.available != this.filterChecks["Active"].Active || + item.available == this.filterChecks["Ended"].Active) && + (item.endingToday != this.filterChecks["EndingToday"].Active || + item.endingToday == this.filterChecks["EndingAfterToday"].Active) && + (item.hasWinPrice != this.filterChecks["WithWinPrice"].Active || + item.hasWinPrice == this.filterChecks["WithNoWinPrice"].Active) + select item; + + Console.WriteLine(this.filterChecks["Favourites"].Active); // bind treeview columns to watchlist instead of needing to manually sync its liststore this.itemTreeView = (TreeView)builder.GetObject("TreeViewItems"); this.items = new ListStore(typeof(YahooAuctionsItem)); - this.RenderList(); + var filteredItems = new TreeModelFilter(this.items, null); + filteredItems.VisibleFunc = this.ItemFilter; - this.itemTreeView.Model = this.items; + this.itemTreeView.Model = filteredItems; TreeCellDataFunc[] funcs = { new TreeCellDataFunc(this.RenderColumnFavourite), new TreeCellDataFunc(this.RenderColumnName), @@ -127,6 +149,7 @@ namespace Buypeeb { c.SetCellDataFunc(c.Cells[0], funcs[i]); } + this.RenderList(); this.UpdateItems(); GLib.Timeout.Add(1000, new GLib.TimeoutHandler(UpdateSelectionEndTime)); @@ -144,11 +167,13 @@ namespace Buypeeb { // TODO: surely there's a better way to do this TreeIter iter; this.itemTreeView.Model.GetIterFirst(out iter); + var m = (TreeModelFilter)this.itemTreeView.Model; for (int i = 0; i < this.itemTreeView.Model.IterNChildren(); i++) { var x = (YahooAuctionsItem)this.itemTreeView.Model.GetValue(iter, 0); + Console.WriteLine(x); if (x.id == id) { - return (this.itemTreeView.Model.GetPath(iter), iter); + return (m.ConvertPathToChildPath(m.GetPath(iter)), m.ConvertIterToChildIter(iter)); } else { this.itemTreeView.Model.IterNext(ref iter); @@ -183,7 +208,9 @@ namespace Buypeeb { Gtk.Application.Invoke(delegate { // TODO: find a way to not have to do this. i think we need to avoid actually modifying the items outside of the main thread :/ var pathAndIter = this.GetRow(id); - this.items.EmitRowChanged(pathAndIter.path, pathAndIter.iter); + if (pathAndIter.path != null) { + this.items.EmitRowChanged(pathAndIter.path, pathAndIter.iter); + } }); using (WebClient client = new WebClient()) { @@ -195,7 +222,9 @@ namespace Buypeeb { Gtk.Application.Invoke(delegate { var pathAndIter = this.GetRow(id); - this.items.EmitRowChanged(pathAndIter.path, pathAndIter.iter); + if (pathAndIter.path != null) { + this.items.EmitRowChanged(pathAndIter.path, pathAndIter.iter); + } if (item == this.selectedItem) { // if the user has this item selected and it just became ready, enable the selection box this.selectionViewBox.Sensitive = true; @@ -370,6 +399,8 @@ namespace Buypeeb { foreach (var item in this.settings.watchlist.Values) { items.AppendValues(item); } + var m = (TreeModelFilter)this.itemTreeView.Model; + m.Refilter(); } // event handlers @@ -598,7 +629,9 @@ namespace Buypeeb { // i don't know why this is necessary var pathAndIter = this.GetRow(this.selectedItem.id); - this.items.EmitRowChanged(pathAndIter.path, pathAndIter.iter); + if (pathAndIter.path != null) { + this.items.EmitRowChanged(pathAndIter.path, pathAndIter.iter); + } } // timers @@ -681,5 +714,34 @@ namespace Buypeeb { } (cell as Gtk.CellRendererText).Text = item.ready ? ending : "..."; } + + // tree filter + + private bool ItemFilter(ITreeModel model, TreeIter iter) { + var item = (YahooAuctionsItem)model.GetValue(iter, 0); + + bool Filtered(string name) { + return this.filterChecks[name].Active; + } + + // first, check to see if any filters are set that would exclude everything, such as hiding both active and ended auctions + // if so, there's no need to run the more expensive linq query + if ( + (Filtered("Favourites") && Filtered("NonFavourites")) || + (Filtered("Active") && Filtered("Ended")) || + (Filtered("EndingToday") && Filtered("EndingAfterToday")) || + (Filtered("WithWinPrice") && Filtered("WithNoWinPrice")) + ) { + return false; + } + + // this.filterQuery.ToList().ForEach(Console.WriteLine); + return this.filterQuery.Contains(item); + } + + private void RunFilter(object sender, EventArgs a) { + var m = (TreeModelFilter)this.itemTreeView.Model; + m.Refilter(); + } } } diff --git a/YahooAuctionsItem.cs b/YahooAuctionsItem.cs index 008b28d..5fd7031 100644 --- a/YahooAuctionsItem.cs +++ b/YahooAuctionsItem.cs @@ -45,32 +45,13 @@ namespace Buypeeb { } } - public string priceJPY { - get { - return $"¥{this.price}"; - } - } - - public string winPriceJPY { - get { - return $"¥{this.winPrice}"; - } - } - - public string priceAUD { - get { - double aud = this.price / 75.0; - return $"${aud:f2}"; - } - } - - public string winPriceAUD { - get { - double aud = this.winPrice / 75.0; - return $"${aud:f2}"; - } - } - + // TODO: don't serialise this stuff + public string priceJPY { get { return $"¥{this.price}"; } } + public string winPriceJPY { get { return $"¥{this.winPrice}"; } } + public string priceAUD { get { return $"${(this.price / 75.0):f2}"; } } + public string winPriceAUD { get { return $"${(this.winPrice / 75.0):f2}"; } } + public bool endingToday { get { return this.endDate.DayOfYear == DateTime.UtcNow.DayOfYear; } } + public bool hasWinPrice { get { return this.winPrice != 0; } } private bool success { get; set; } // TODO: custom setter that throws an exception if set to false or something idk public YahooAuctionsItem(string id, string name) { @@ -129,5 +110,9 @@ namespace Buypeeb { this.autoExtension = (m.Groups[1].Value == "あり"); } } + + public override string ToString() { + return $"{this.id}: {this.name}"; + } } } diff --git a/ui/main.glade b/ui/main.glade index 8195dcd..e2017a6 100644 --- a/ui/main.glade +++ b/ui/main.glade @@ -3,6 +3,171 @@ + + False + + + True + False + 5 + 5 + 5 + 5 + vertical + 3 + + + True + False + 5 + 5 + Items to hide: + + + + + + False + True + 0 + + + + + Favourites + True + True + False + True + + + + False + True + 1 + + + + + Non-favourites + True + True + False + True + + + + False + True + 2 + + + + + Active + True + True + False + True + + + + False + True + 3 + + + + + Ended + True + True + False + True + + + + False + True + 4 + + + + + Ending today + True + True + False + True + + + + False + True + 5 + + + + + Ending after today + True + True + False + True + + + + False + True + 6 + + + + + With win price + True + True + False + True + + + + False + True + 7 + + + + + With no win price + True + True + False + True + + + + False + True + 8 + + + + + Show all + True + True + True + + + False + True + 9 + + + + + False 810 @@ -279,75 +444,135 @@ - + True - True + False True - True - in - 200 + vertical - + + True + False + 3 + 3 + 3 + + + True + True + True + edit-find-symbolic + False + False + + + False + True + 0 + + + + + True + True + False + True + popover1 + + + + + + False + True + 1 + + + + + False + True + 0 + + + + True True - True - 1 - True - - - - - + True + True + in + 200 - - - - + + True + True + True + False + 1 + True + + + + - - - - - True - fixed - 100 - Name - True - True - + + + + + + - - - - - True - Price (¥) - + + True + fixed + 100 + Name + True + True + + + + - - - - - True - Price (AUD) - + + True + Price (¥) + + + + - - - - - True - Ending at - True - + + True + Price (AUD) + + + + + + + + True + Ending at + True + + + + + + False + True + 1 +