Add to git.
[monolith.git] / discussion / ml_discussion_panel.c
1 /* Monolith discussion panel widget.
2  * - by Richard W.M. Jones <rich@annexia.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *
18  * $Id: ml_discussion_panel.c,v 1.4 2003/02/22 15:34:29 rich Exp $
19  */
20
21 #include "config.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 #ifdef HAVE_ASSERT_H
27 #include <assert.h>
28 #endif
29
30 #ifdef HAVE_STRING_H
31 #include <string.h>
32 #endif
33
34 #include <pool.h>
35 #include <pstring.h>
36
37 #include <pthr_dbi.h>
38
39 #include <monolith.h>
40 #include <ml_window.h>
41 #include <ml_widget.h>
42 #include <ml_select_layout.h>
43 #include <ml_multicol_layout.h>
44 #include <ml_button.h>
45
46 #include "ml_discussion.h"
47 #include "ml_discussion_panel.h"
48
49 static void repaint (void *, ml_session, const char *, io_handle);
50
51 struct ml_widget_operations discussion_panel_ops =
52   {
53     repaint: repaint
54   };
55
56 struct ml_discussion_panel
57 {
58   struct ml_widget_operations *ops;
59   pool pool;                    /* Pool for allocations. */
60   ml_session session;           /* Current session. */
61   const char *conninfo;         /* Database connection. */
62   ml_select_layout w;           /* The actual select layout. */
63 };
64
65 static void do_refresh (ml_session, void *vw);
66
67 ml_discussion_panel
68 new_ml_discussion_panel (pool pool, ml_session session, const char *conninfo)
69 {
70   ml_discussion_panel w = pmalloc (pool, sizeof *w);
71   ml_multicol_layout tbl;
72   ml_button refresh_button;
73
74   w->ops = &discussion_panel_ops;
75   w->pool = pool;
76   w->session = session;
77   w->conninfo = conninfo;
78
79   /* Create the layout. */
80   w->w = new_ml_select_layout (pool, session);
81   ml_widget_set_property (w->w, "class", "ml_discussion_panel");
82
83   /* Create the action buttons. */
84   tbl = new_ml_multicol_layout (pool, 1);
85   ml_widget_set_property (tbl, "class", "ml_discussion_panel_actions");
86   refresh_button = new_ml_button (pool, "Refresh");
87   ml_button_set_callback (refresh_button, do_refresh, session, w);
88   ml_multicol_layout_pack (tbl, refresh_button);
89
90   /* Put the action buttons into the layout. */
91   ml_widget_set_property (w->w, "select_layout.top", tbl);
92
93   /* Refresh selected newsgroups. */
94   do_refresh (session, w);
95
96   return w;
97 }
98
99 /* XXX When called from new_ml_discussion_panel, this is OK, but when called
100  * from the button, it's a bit brutal, because it creates new copies of
101  * every widget. This is not necessary, and we could definitely be more
102  * clever here.
103  */
104 static void
105 do_refresh (ml_session session, void *vw)
106 {
107   ml_discussion_panel w = (ml_discussion_panel) vw;
108   db_handle dbh;
109   st_handle sth;
110   int resid, unread;
111   const char *resname;
112
113   ml_select_layout_clear (w->w);
114
115   /* Pull out the list of newsgroups. */
116   /* XXX Access control. */
117   dbh = get_db_handle (w->conninfo, DBI_THROW_ERRORS);
118
119   sth = st_prepare_cached
120     (dbh,
121      "select g.resid, r.name, ml_discussion_unread (?, g.resid) "
122      "  from ml_discussion_group g, ml_resources r "
123      " where g.resid = r.resid "
124      " order by 2", DBI_INT);
125   st_execute (sth, ml_session_userid (session));
126
127   st_bind (sth, 0, resid, DBI_INT);
128   st_bind (sth, 1, resname, DBI_STRING);
129   st_bind (sth, 2, unread, DBI_INT);
130
131   while (st_fetch (sth))
132     {
133       char *name;
134       ml_widget ng;
135
136       /* Create the name of this group. */
137       name = psprintf (w->pool, "%s (%d)", resname, unread);
138
139       /* Create the newsgroup widget. */
140       /* XXX Avoid the extra DB query somehow? */
141       ng = new_ml_discussion (w->pool, session, w->conninfo, resname);
142
143       /* Pack into the layout. */
144       ml_select_layout_pack (w->w, name, ng);
145     }
146
147   put_db_handle (dbh);
148 }
149
150 static void
151 repaint (void *vw, ml_session session, const char *windowid, io_handle io)
152 {
153   ml_discussion_panel w = (ml_discussion_panel) vw;
154
155   if (w->w)
156     ml_widget_repaint (w->w, session, windowid, io);
157 }