Take the 2-minute tour ×
Stack Apps is a question and answer site for apps, scripts, and development with the Stack Exchange API. It's 100% free, no registration required.

Soapi.FindUser

alt text

About

Soapi.FindUser is a tiny .NET 3.5 application that searches all Stack Exchange sites for users by name with the provided search term.

The results are grouped by site and are sortable by Name or Reputation.

Hover or click an item to view the profile, double click an item to open your default browser to the users profile page.

License

Soapi.FindUser is free to use and is licensed under GPL V2.

Download

You can install Soapi.FindUser via Click-Once here:

http://soapi.info/Code/CSSL/Stable/ScoobySnacks/FindUser/publish.htm

Platform

This application will run on any .NET 3.5sp1 compatible platform.

Contact

Soapi.FindUser was created by code poet.

Code

Soapi.FindUser was written, in 30 minutes, to serve as a sample app for Soapi.CS.

The source for Soapi.FindUser can be found in the answers and is included in the Soapi.CS source code.

share|improve this question
    
If this works on Mono, I'll give it a go. –  Nathan Osman Aug 9 '10 at 22:32
    
@geo - I may have to whip up a GTK+ version. This version uses System.Windows.Forms. Not sure if that is going to work on linux. –  Sky Sanders Aug 9 '10 at 22:37
    
I really don't know... but a GTK+ version would be awesome. Are you thinking .net, C++, or PyGTK? –  Nathan Osman Aug 10 '10 at 1:49
    
@geo - mono. in any case - the silverlight version is up at stackapps.com/questions/1344/… - you should be able to use that. –  Sky Sanders Aug 10 '10 at 13:02
add comment

1 Answer 1

Source Code:

The primary purpose of Soapi.FindUser is to serve as a simple sample application for the Soapi.CS library.

In this spirit, the complete source code for the application is provided here:

//  
//  Project: SOAPI
//  http://soapics.codeplex.com
//  http://stackapps.com/questions/386
//  
//  Copyright 2010, Sky Sanders
//  Licensed under the GPL Version 2 license.
//  http://soapics.codeplex.com/license
//  
//  Date: Aug 08 2010 
//  API ver 1.0 rev 2010.0709.04
//  

#region

using System;
using System.Collections;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading;
using System.Windows.Forms;
using Soapi.Domain;
using Soapi.Parameters;
using SortOrder = System.Windows.Forms.SortOrder;

#endregion

namespace Soapi.Samples
{
    public partial class FindUser : Form
    {
        private const string ApiKey = "qgAq_KfDu0KYzlNG-qaTuw";
        private const string GravatarFormat = "http://www.gravatar.com/avatar/{0}?s=128&d=identicon&r=PG";

        private const string AboutMeFormat =
            "<html><head><link rel='stylesheet' href='http://stackapps.com/content/sa/all.css'></head><body style='background:#eaefef;'>{0}</body></html>";

        private const string HelpPageUrl = "http://stackapps.com/questions/386";
        private static ApiContext _context;
        private readonly UserListViewColumnSorter _sorter;
        private bool _fetchStopFlag;
        private Thread _fetchThread;

        public FindUser()
        {
            InitializeComponent();

            _sorter = new UserListViewColumnSorter();

            UserListView.ListViewItemSorter = _sorter;

            SearchTermTextBox.Enabled = false;
            SearchTermTextBox.Text = "initializing";

            _context = new ApiContext(ApiKey);
            _context.Initialized += (x, y) => BeginInvoke(new MethodInvoker(() =>
                {
                    SearchTermTextBox.Enabled = true;
                    SearchTermTextBox.Text = "";
                    SearchTermTextBox.Focus();
                }));
            _context.Initialize();

        }

        /// <summary>
        /// You can use this form as a selector in your app.
        /// </summary>
        public User User { get; private set; }

        private void SearchButtonClick(object sender, EventArgs e)
        {
            SearchButton.Enabled = false;
            SearchTermTextBox.Enabled = false;

            if (_fetchThread != null)
            {
                if (_fetchThread.IsAlive)
                {
                    _fetchStopFlag = true;
                    _fetchThread.Join();
                    _fetchStopFlag = false;
                }
            }

            UserListView.BeginUpdate();
            UserListView.Items.Clear();
            UserListView.Groups.Clear();
            UserListView.EndUpdate();

            string searchTerm = SearchTermTextBox.Text;

            _fetchThread = new Thread(() =>
                {
                    var sites = _context.Sites.Where(s => s.ApiEndpoint.IndexOf("stackauth") < 0).ToList();

                    foreach (var site in sites)
                    {
                        if (_fetchStopFlag) continue;

                        var group = new ListViewGroup(site.ApiEndpoint, site.Name);

                        BeginInvoke(new MethodInvoker(() =>
                            UserListView.Groups.Add(group)));

                        ThreadPool.QueueUserWorkItem(s =>
                            {
                                var lSite = (Site) s;
                                if (!_fetchStopFlag)
                                {
                                    var possibleMatches = lSite
                                        .Users
                                        .Filter(searchTerm)
                                        .PageCount(-1)
                                        .Sort(UserSort.Name);

                                    foreach (var user in possibleMatches.ToList())
                                    {
                                        if (_fetchStopFlag) continue;

                                        var item = new ListViewItem(new[]
                                            {
                                                user.DisplayName,
                                                user.Reputation.ToString()
                                            }, group) {Tag = user};

                                        BeginInvoke(new MethodInvoker(() =>
                                            UserListView.Items.Add(item)));
                                    }
                                }
                            }, site);
                    }
                });


            _fetchThread.Start();

            SearchButton.Enabled = SearchTermTextBox.Text.Length > 3;
            SearchTermTextBox.Enabled = true;
        }

        private void UserListViewColumnClick(object sender, ColumnClickEventArgs e)
        {
            if (e.Column == _sorter.SortColumn)
            {
                _sorter.Order = _sorter.Order == SortOrder.Ascending
                                    ? SortOrder.Descending
                                    : SortOrder.Ascending;
            }
            else
            {
                _sorter.SortColumn = e.Column;
                _sorter.Order = SortOrder.Ascending;
            }
            UserListView.Sort();
        }

        private void SearchTermTextBoxChanged(object sender, EventArgs e)
        {
            SearchButton.Enabled = SearchTermTextBox.Text.Length > 3;
        }

        private void UserListViewSelectedIndexChanged(object sender, EventArgs e)
        {
            if (UserListView.SelectedItems.Count > 0)
            {
                var user = UserListView.SelectedItems[0].Tag as User;
                if (user != null)
                {
                    User = user;
                    userBindingSource.DataSource = User;
                }
            }
        }

        private void FindUserLoad(object sender, EventArgs e)
        {
            HelpButtonClicked += (x, y) => Process.Start(HelpPageUrl);
        }

        private void UserBindingSourceCurrentChanged(object sender, EventArgs e)
        {
            var current = (User) userBindingSource.Current;
            LoadGravatar(current.EmailHash);
            RenderAboutMe(string.Format(AboutMeFormat, current.AboutMe ?? ""));
        }

        private void RenderAboutMe(string html)
        {
            AboutMeHtmlControl.LoadDocument(html);
        }

        private void LoadGravatar(string emailHash)
        {
            try
            {
                WebRequest r = WebRequest.Create(string.Format(GravatarFormat, emailHash));

                using (WebResponse response = r.GetResponse())
                {
                    if (response != null)
                    {
                        using (Stream stream = response.GetResponseStream())
                        {
                            if (stream != null)
                            {
                                GravatarPictureBox.Image = Image.FromStream(stream);
                            }
                        }
                    }
                }
            }
// ReSharper disable EmptyGeneralCatchClause
            catch
// ReSharper restore EmptyGeneralCatchClause
            {
            }
        }

        private void WebSiteLinkClick(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Process.Start(websiteUrlLinkLabel.Text);
        }

        private void UserListDoubleClick(object sender, EventArgs e)
        {
            Process.Start(string.Format("{0}/users/{1}", User.Site.SiteUrl, User.UserId));
        }

        #region Nested type: UserListViewColumnSorter

        private class UserListViewColumnSorter : IComparer
        {
            #region Fields

            private readonly CaseInsensitiveComparer _objectCompare;
            private int _columnToSort;

            private SortOrder _orderOfSort;

            #endregion

            #region Constructors

            public UserListViewColumnSorter()
            {
                _columnToSort = 0;
                _orderOfSort = SortOrder.None;
                _objectCompare = new CaseInsensitiveComparer();
            }

            #endregion

            #region Properties

            public SortOrder Order
            {
                set { _orderOfSort = value; }
                get { return _orderOfSort; }
            }

            public int SortColumn
            {
                set { _columnToSort = value; }
                get { return _columnToSort; }
            }

            #endregion

            #region Public Methods

            public int Compare(object x, object y)
            {
                int compareResult;

                var listviewX = (ListViewItem) x;
                var listviewY = (ListViewItem) y;

                if (_columnToSort == 0)
                {
                    compareResult = _objectCompare.Compare(listviewX.SubItems[_columnToSort].Text,
                                                           listviewY.SubItems[_columnToSort].Text);
                }
                else
                {
                    compareResult = _objectCompare.Compare(Convert.ToInt32(listviewX.SubItems[_columnToSort].Text),
                                                           Convert.ToInt32(listviewY.SubItems[_columnToSort].Text));
                }

                if (_orderOfSort == SortOrder.Ascending)
                {
                    return compareResult;
                }
                if (_orderOfSort == SortOrder.Descending)
                {
                    return (-compareResult);
                }
                return 0;
            }

            #endregion
        }

        #endregion
    }
}
share|improve this answer
add comment

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .