/* buypeeb - a program to track yahoo jp auctions of peebus. Copyright (C) 2020 lynnesbian This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ using System; using System.Collections.Generic; using System.Text.RegularExpressions; // using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Gtk; namespace Buypeeb { public struct ItemColumns { public static int Name = 0; public static int PriceYen = 1; public static int PriceAUD = 2; public static int Ending = 3; public static int Id = 4; } class MainWindow : Window { private ListStore items; private Settings settings; private TreeView itemTreeView; static SemaphoreSlim tasklimit = new SemaphoreSlim(4); public MainWindow() : this(new Builder("main.glade")) { } private MainWindow(Builder builder) : base(builder.GetObject("wndMain").Handle) { this.settings = new Settings(); this.settings.Save(); this.Title = "Buypeeb"; builder.Autoconnect(this); // bind treeview columns to watchlist instead of needing to manually sync its liststore this.itemTreeView = (TreeView)builder.GetObject("TreeViewItems"); this.items = new ListStore(typeof(Listing)); this.RenderList(); this.itemTreeView.Model = this.items; //TODO: make this less verbose this.itemTreeView.Columns[ItemColumns.Name].SetCellDataFunc(this.itemTreeView.Columns[ItemColumns.Name].Cells[0], new Gtk.TreeCellDataFunc(this.RenderColumnName)); this.itemTreeView.Columns[ItemColumns.PriceYen].SetCellDataFunc(this.itemTreeView.Columns[ItemColumns.PriceYen].Cells[0], new Gtk.TreeCellDataFunc(this.RenderColumnPriceYen)); this.itemTreeView.Columns[ItemColumns.PriceAUD].SetCellDataFunc(this.itemTreeView.Columns[ItemColumns.PriceAUD].Cells[0], new Gtk.TreeCellDataFunc(this.RenderColumnPriceAUD)); this.itemTreeView.Columns[ItemColumns.Ending].SetCellDataFunc(this.itemTreeView.Columns[ItemColumns.Ending].Cells[0], new Gtk.TreeCellDataFunc(this.RenderColumnEnding)); foreach (object[] row in this.items) { Console.WriteLine(row[0]); } DeleteEvent += Window_Shutdown; } private void Window_Shutdown(object sender, DeleteEventArgs args) { Application.Quit(); } // general behaviour private void UpdateThread(string id) { var item = this.settings.watchlist[id]; Console.WriteLine($"Updating {id}..."); item.ready = false; Thread.Sleep(3000); string html = "Heeenlo"; item.name = html; item.ready = true; Console.WriteLine($"{id} updated."); Gtk.Application.Invoke(delegate { //TODO: surely there's a better way to do this TreeIter iter; this.itemTreeView.Model.GetIterFirst(out iter); for (int i = 0; i < this.itemTreeView.Model.IterNChildren(); i++) { var x = (Listing)this.itemTreeView.Model.GetValue(iter, 0); if (x.id == id) { this.items.EmitRowChanged(this.itemTreeView.Model.GetPath(iter), iter); break; } else { this.itemTreeView.Model.IterNext(ref iter); } } }); } private void UpdateItem(string id) { tasklimit.Wait(); var t = Task.Factory.StartNew(() => { this.UpdateThread(id); }).ContinueWith(task => { tasklimit.Release(); }); } private void UpdateItems() { var t = Task.Factory.StartNew(() => { foreach (var item in this.settings.watchlist) { this.UpdateItem(item.Key); } }); } private (Boolean accepted, string response) EntryDialogue(string title = "Buypeeb", string message = "Hi there!") { Dialog ed = new Dialog(title, null, Gtk.DialogFlags.DestroyWithParent, "Cancel", ResponseType.Cancel, "OK", ResponseType.Ok); ed.DefaultResponse = ResponseType.Ok; Label edLabel = new Label(message); Entry edEntry = new Entry(); edEntry.ActivatesDefault = true; ed.ContentArea.PackStart(edLabel, true, true, 2); edLabel.Show(); ed.ContentArea.PackStart(edEntry, true, true, 10); edEntry.Show(); ResponseType accepted = (ResponseType)ed.Run(); string response = edEntry.Text; ed.Dispose(); return (accepted == ResponseType.Ok, response); } private void RenderList() { this.items.Clear(); foreach (var item in this.settings.watchlist) { items.AppendValues(item.Value); } } // button handlers private void ButtonAddClicked(object sender, EventArgs a) { // Console.WriteLine("ButtonAddClicked"); AddItemDialogue aid = new AddItemDialogue(); ResponseType accepted = (ResponseType)aid.Run(); string url = aid.GetURL(); string name = aid.GetName(); aid.Dispose(); // vry simpl url validation for simpol creachers Regex rx = new Regex(@"^http.+yahoo.+"); if (rx.IsMatch(url)) { Console.WriteLine("{0} will be added", url); this.settings.Watch(url, name); this.RenderList(); } else { Console.WriteLine("{0} is an invalid url", url); } } private void ButtonUpdateAllClicked(object sender, EventArgs a) { Console.WriteLine("ButtonUpdateAllClicked"); this.UpdateItems(); } private void ButtonClearEndedClicked(object sender, EventArgs a) { Console.WriteLine("ButtonClearEndedClicked"); } private void ButtonClearAllClicked(object sender, EventArgs a) { Console.WriteLine("ButtonClearAllClicked"); } private void ButtonSaveClicked(object sender, EventArgs a) { Console.WriteLine("ButtonSaveClicked"); } private void ButtonQuitClicked(object sender, EventArgs a) { MessageDialog md = new MessageDialog(null, DialogFlags.DestroyWithParent, MessageType.Question, ButtonsType.OkCancel, "Are you sure you want to quit?"); ResponseType response = (ResponseType)md.Run(); md.Dispose(); if (response == ResponseType.Ok) { Application.Quit(); } } private void tveItemsSelectionChanged(object sender, EventArgs a) { Console.WriteLine("tveItemsSelectionChanged"); } private void ButtonViewBuyeeClicked(object sender, EventArgs a) { Console.WriteLine("ButtonViewBuyeeClicked"); } private void ButtonViewYahooClicked(object sender, EventArgs a) { Console.WriteLine("ButtonViewYahooClicked"); } private void ButtonSelectedRemoveClicked(object sender, EventArgs a) { Console.WriteLine("ButtonSelectedRemoveClicked"); } private void ButtonSelectedRenameClicked(object sender, EventArgs a) { Console.WriteLine("ButtonSelectedRenameClicked"); } // column renderers private void RenderColumnName(Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.ITreeModel model, Gtk.TreeIter iter) { Listing item = (Listing)model.GetValue(iter, 0); (cell as Gtk.CellRendererText).Text = item.name ?? "Loading..."; } private void RenderColumnPriceYen(Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.ITreeModel model, Gtk.TreeIter iter) { Listing item = (Listing)model.GetValue(iter, 0); (cell as Gtk.CellRendererText).Text = item.PriceJPY(); } private void RenderColumnPriceAUD(Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.ITreeModel model, Gtk.TreeIter iter) { Listing item = (Listing)model.GetValue(iter, 0); (cell as Gtk.CellRendererText).Text = item.PriceAUD(); } private void RenderColumnEnding(Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.ITreeModel model, Gtk.TreeIter iter) { Listing item = (Listing)model.GetValue(iter, 0); (cell as Gtk.CellRendererText).Text = "whatever"; } } }