File Source: FeedbackDialog.java
/*
P/P * Method: com.dmdirc.addons.ui_swing.dialogs.FeedbackDialog__static_init
*/
1 /*
2 * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 package com.dmdirc.addons.ui_swing.dialogs;
24
25 import com.dmdirc.Main;
26 import com.dmdirc.Server;
27 import com.dmdirc.ServerManager;
28 import com.dmdirc.ui.core.util.Info;
29 import com.dmdirc.addons.ui_swing.SwingController;
30 import com.dmdirc.addons.ui_swing.UIUtilities;
31 import com.dmdirc.addons.ui_swing.components.LoggingSwingWorker;
32 import com.dmdirc.addons.ui_swing.components.StandardDialog;
33 import com.dmdirc.addons.ui_swing.components.text.TextLabel;
34 import com.dmdirc.config.IdentityManager;
35 import com.dmdirc.util.Downloader;
36
37 import java.awt.Insets;
38 import java.awt.Window;
39 import java.awt.event.ActionEvent;
40 import java.awt.event.ActionListener;
41 import java.io.IOException;
42 import java.net.MalformedURLException;
43 import java.util.HashMap;
44 import java.util.List;
45 import java.util.Map;
46
47 import javax.swing.BorderFactory;
48 import javax.swing.JButton;
49 import javax.swing.JCheckBox;
50 import javax.swing.JLabel;
51 import javax.swing.JScrollPane;
52 import javax.swing.JTextArea;
53 import javax.swing.JTextField;
54 import javax.swing.event.DocumentEvent;
55 import javax.swing.event.DocumentListener;
56
57 import net.miginfocom.swing.MigLayout;
58
59 /** Feedback form. */
60 public class FeedbackDialog extends StandardDialog implements ActionListener,
61 DocumentListener {
62
63 /**
64 * A version number for this class. It should be changed whenever the class
65 * structure is changed (or anything else that would prevent serialized
66 * objects being unserialized with the new class).
67 */
68 private static final long serialVersionUID = 1;
69 /** A previously created instance of FeedbackDialog. */
70 private static volatile FeedbackDialog me;
71 /** Information label. */
72 private TextLabel info;
73 /** Name field. */
74 private JTextField name;
75 /** Email field. */
76 private JTextField email;
77 /** Feedback area. */
78 private JTextArea feedback;
79 /** Server info checkbox. */
80 private JCheckBox serverCheckbox;
81 /** DMDirc info checkbox. */
82 private JCheckBox DMDircCheckbox;
83
84 /**
85 * Instantiates the feedback dialog.
86 *
87 * @param parentWindow Parent window
88 */
89 private FeedbackDialog(final Window parentWindow) {
/*
P/P * Method: void com.dmdirc.addons.ui_swing.dialogs.FeedbackDialog(Window)
*
* Presumptions:
* init'ed(java.awt.Dialog$ModalityType.MODELESS)
*
* Postconditions:
* this.DMDircCheckbox == &new JCheckBox(initComponents#8)
* this.email == &new JTextField(initComponents#5)
* this.feedback == &new JTextArea(initComponents#6)
* this.info == &new TextLabel(initComponents#3)
* this.name == &new JTextField(initComponents#4)
* this.serverCheckbox == &new JCheckBox(initComponents#7)
* new JCheckBox(initComponents#7) num objects == 1
* new JCheckBox(initComponents#8) num objects == 1
* new JTextArea(initComponents#6) num objects == 1
* new JTextField(initComponents#4) num objects == 1
* ...
*/
90 super(parentWindow, ModalityType.MODELESS);
91
92 initComponents();
93 layoutComponents();
94 addListeners();
95
96 setTitle("DMDirc: Feedback");
97 setResizable(false);
98
99 pack();
100 }
101
102 /**
103 * Creates the new feedback dialog if one doesn't exist, and displays it.
104 *
105 * @param parentWindow Parent window
106 */
107 public static void showFeedbackDialog(final Window parentWindow) {
/*
P/P * Method: void showFeedbackDialog(Window)
*
* Preconditions:
* init'ed(me)
*
* Postconditions:
* me == One-of{old me, &new FeedbackDialog(getFeedbackDialog#1)}
* me != null
* new FeedbackDialog(getFeedbackDialog#1) num objects <= 1
* new JCheckBox(initComponents#7) num objects == new FeedbackDialog(getFeedbackDialog#1) num objects
* new JCheckBox(initComponents#8) num objects == new FeedbackDialog(getFeedbackDialog#1) num objects
* new JTextArea(initComponents#6) num objects == new FeedbackDialog(getFeedbackDialog#1) num objects
* new JTextField(initComponents#4) num objects == new FeedbackDialog(getFeedbackDialog#1) num objects
* new JTextField(initComponents#5) num objects == new FeedbackDialog(getFeedbackDialog#1) num objects
* new SimpleAttributeSet(TextLabel#6) num objects == new FeedbackDialog(getFeedbackDialog#1) num objects
* new TextLabel(initComponents#3) num objects == new FeedbackDialog(getFeedbackDialog#1) num objects
* ...
*/
108 me = getFeedbackDialog(parentWindow);
109
110 me.setLocationRelativeTo(parentWindow);
111 me.setVisible(true);
112 me.requestFocusInWindow();
113 }
114
115 /**
116 * Returns the current instance of the FeedbackDialog.
117 *
118 * @param parentWindow Parent window
119 *
120 * @return The current FeedbackDialog instance
121 */
122 public static FeedbackDialog getFeedbackDialog(final Window parentWindow) {
/*
P/P * Method: FeedbackDialog getFeedbackDialog(Window)
*
* Preconditions:
* init'ed(me)
*
* Presumptions:
* com.dmdirc.ServerManager:getServerManager(...)@126 != null
* me.serverCheckbox != null
*
* Postconditions:
* me == One-of{old me, &new FeedbackDialog(getFeedbackDialog#1)}
* me != null
* return_value == One-of{old me, &new FeedbackDialog(getFeedbackDialog#1)}
* return_value != null
* new FeedbackDialog(getFeedbackDialog#1) num objects <= 1
* new FeedbackDialog(getFeedbackDialog#1).DMDircCheckbox == &new JCheckBox(initComponents#8)
* new FeedbackDialog(getFeedbackDialog#1).email == &new JTextField(initComponents#5)
* new FeedbackDialog(getFeedbackDialog#1).feedback == &new JTextArea(initComponents#6)
* new FeedbackDialog(getFeedbackDialog#1).info == &new TextLabel(initComponents#3)
* new FeedbackDialog(getFeedbackDialog#1).name == &new JTextField(initComponents#4)
* ...
*/
123 synchronized (FeedbackDialog.class) {
124 if (me == null) {
125 me = new FeedbackDialog(parentWindow);
126 me.serverCheckbox.setEnabled(ServerManager.getServerManager().
127 numServers() > 0);
128 }
129 }
130
131 return me;
132 }
133
134 /** Initialises the components. */
135 private void initComponents() {
/*
P/P * Method: void initComponents()
*
* Presumptions:
* com.dmdirc.addons.ui_swing.dialogs.FeedbackDialog:getCancelButton(...)@141 != null
* com.dmdirc.addons.ui_swing.dialogs.FeedbackDialog:getOkButton(...)@138 != null
* com.dmdirc.addons.ui_swing.dialogs.FeedbackDialog:getOkButton(...)@139 != null
* com.dmdirc.addons.ui_swing.dialogs.FeedbackDialog:getOkButton(...)@140 != null
*
* Postconditions:
* this.DMDircCheckbox == &new JCheckBox(initComponents#8)
* this.email == &new JTextField(initComponents#5)
* this.feedback == &new JTextArea(initComponents#6)
* this.info == &new TextLabel(initComponents#3)
* this.name == &new JTextField(initComponents#4)
* this.serverCheckbox == &new JCheckBox(initComponents#7)
* new JCheckBox(initComponents#7) num objects == 1
* new JCheckBox(initComponents#8) num objects == 1
* new JTextArea(initComponents#6) num objects == 1
* new JTextField(initComponents#4) num objects == 1
* ...
*/
136 orderButtons(new JButton(), new JButton());
137
138 getOkButton().setText("Send");
139 getOkButton().setActionCommand("Send");
140 getOkButton().setEnabled(false);
141 getCancelButton().setActionCommand("Close");
142
143 info = new TextLabel("Thank you for using DMDirc. If you have any " +
144 "feedback about the client, such as bug reports or feature " +
145 "requests, please send it to us using the form below. " +
146 "The name and e-mail address fields are optional if you " +
147 "don't want us to contact you about your feedback.\n\n" +
148 "Please note that this is for feedback such as bug reports " +
149 "and suggestions, not for technical support. For " +
150 "technical support, please join #DMDirc using the button " +
151 "in the help menu.");
152 name = new JTextField();
153 email = new JTextField();
154 feedback = new JTextArea();
155 serverCheckbox =
156 new JCheckBox("Include information about connected servers.");
157 DMDircCheckbox = new JCheckBox("Include information about DMDirc.");
158
159 UIUtilities.addUndoManager(name);
160 UIUtilities.addUndoManager(email);
161 UIUtilities.addUndoManager(feedback);
162 }
163
164 /** Lays out the components. */
165 private void layoutComponents() {
/*
P/P * Method: void layoutComponents()
*
* Preconditions:
* this.DMDircCheckbox != null
* init'ed(this.email)
* init'ed(this.feedback)
* init'ed(this.info)
* init'ed(this.name)
* this.serverCheckbox != null
*/
166 serverCheckbox.setMargin(new Insets(0, 0, 0, 0));
167 serverCheckbox.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
168 DMDircCheckbox.setMargin(new Insets(0, 0, 0, 0));
169 DMDircCheckbox.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
170
171 setLayout(new MigLayout("fill, wmin 600, wmax 600, hmin 400, hmax 400"));
172
173 add(info, "span, growx, wrap, gapbottom unrel");
174
175 add(new JLabel("Name: "), "aligny top, shrink");
176 add(name, "growx, pushx, wrap");
177
178 add(new JLabel("Email: "), "aligny top, shrink");
179 add(email, "growx, pushx, wrap");
180
181 add(new JLabel("Feedback: "), "aligny top, shrink");
182 add(new JScrollPane(feedback), "grow, push, wrap");
183 add(serverCheckbox, "skip 1, growx, wrap");
184 add(DMDircCheckbox, "skip 1, growx, wrap");
185
186 add(getCancelButton(), "skip, split 2, right, sg button");
187 add(getOkButton(), "right, sg button");
188 }
189
190 /**
191 * Lays out the components.
192 *
193 * @param error Did the submission error?
194 */
195 protected void layoutComponents2(final StringBuilder error) {
/*
P/P * Method: void layoutComponents2(StringBuilder)
*
* Preconditions:
* error != null
* this.info != null
* (soft) init'ed(this.info.sas)
*
* Presumptions:
* com.dmdirc.addons.ui_swing.dialogs.FeedbackDialog:getContentPane(...)@196 != null
* com.dmdirc.addons.ui_swing.dialogs.FeedbackDialog:getContentPane(...)@197 != null
* com.dmdirc.addons.ui_swing.dialogs.FeedbackDialog:getContentPane(...)@209 != null
* com.dmdirc.addons.ui_swing.dialogs.FeedbackDialog:getOkButton(...)@198 != null
* com.dmdirc.addons.ui_swing.dialogs.FeedbackDialog:getOkButton(...)@199 != null
* ...
*/
196 getContentPane().setVisible(false);
197 getContentPane().removeAll();
198 getOkButton().setEnabled(true);
199 getOkButton().setText("Close");
200 getOkButton().setActionCommand("Close");
201
202 setLayout(new MigLayout("fill, wmin 600, wmax 600, hmin 400, hmax 400"));
203
204 info.setText(error.toString());
205
206 add(info, "span 3, grow, push, wrap");
207
208 add(getOkButton(), "skip, right, tag ok, sg button");
209 getContentPane().setVisible(true);
210 }
211
212 /** Adds listeners to the components. */
213 private void addListeners() {
/*
P/P * Method: void addListeners()
*
* Preconditions:
* this.feedback != null
*
* Presumptions:
* com.dmdirc.addons.ui_swing.dialogs.FeedbackDialog:getCancelButton(...)@215 != null
* com.dmdirc.addons.ui_swing.dialogs.FeedbackDialog:getOkButton(...)@214 != null
* javax.swing.JTextArea:getDocument(...)@216 != null
*/
214 getOkButton().addActionListener(this);
215 getCancelButton().addActionListener(this);
216 feedback.getDocument().addDocumentListener(this);
217 }
218
219 /** Checks and sends the feedback. */
220 private void send() {
/*
P/P * Method: void send()
*
* Preconditions:
* init'ed(me)
* this.DMDircCheckbox != null
* this.email != null
* this.feedback != null
* this.name != null
* this.serverCheckbox != null
*
* Presumptions:
* com.dmdirc.Server:getParser(...)@229 != null
* com.dmdirc.Server:getParser(...)@233 != null
* com.dmdirc.Server:getParser(...)@235 != null
* com.dmdirc.Server:getParser(...)@236 != null
* com.dmdirc.Server:getParser(...)@239 != null
* ...
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@226: {0}, {1}
* javax.swing.JCheckBox:isSelected(...)@225: {0}, {1}
* javax.swing.JCheckBox:isSelected(...)@245: {0}, {1}
*/
221 getOkButton().setEnabled(false);
222 getCancelButton().setEnabled(false);
223 final StringBuilder serverInfo = new StringBuilder();
224 final StringBuilder dmdircInfo = new StringBuilder();
225 if (serverCheckbox.isSelected()) {
226 for (Server server : ServerManager.getServerManager().getServers()) {
227 serverInfo.append("Server name: ").append(server.getName()).
228 append("\n");
229 serverInfo.append("Actual name: ").
230 append(server.getParser().getServerName()).append("\n");
231 serverInfo.append("Network: ").append(server.getNetwork()).
232 append("\n");
233 serverInfo.append("IRCd: ").append(server.getParser().getIRCD(false)).
234 append(" - ");
235 serverInfo.append(server.getParser().getIRCD(true)).append("\n");
236 serverInfo.append("Modes: ").
237 append(server.getParser().getBoolChanModes()).
238 append(" ");
239 serverInfo.append(server.getParser().getListChanModes()).append(" ");
240 serverInfo.append(server.getParser().getSetOnlyChanModes()).
241 append(" ");
242 serverInfo.append(server.getParser().getSetUnsetChanModes());
243 }
244 }
245 if (DMDircCheckbox.isSelected()) {
246 dmdircInfo.append("DMDirc version: " + Info.getDMDircVersion()).
247 append("\n");
248 dmdircInfo.append("Profile directory: " + Main.getConfigDir()).
249 append("\n");
250 dmdircInfo.append("Java version: " + Info.getJavaVersion()).append("\n");
251 dmdircInfo.append("OS Version: " + Info.getOSVersion()).append("\n");
252 dmdircInfo.append("Look & Feel: " + SwingController.getLookAndFeel());
253 }
254 new SendWorker(me, name.getText().trim(),
255 email.getText().trim(), feedback.getText().trim(), serverInfo.toString().
256 trim(), dmdircInfo.toString().trim()).execute();
257 }
258
259 /** Validates the input. */
260 private void validateInput() {
/*
P/P * Method: void validateInput()
*
* Preconditions:
* this.feedback != null
*
* Presumptions:
* com.dmdirc.addons.ui_swing.dialogs.FeedbackDialog:getOkButton(...)@262 != null
* com.dmdirc.addons.ui_swing.dialogs.FeedbackDialog:getOkButton(...)@264 != null
* javax.swing.JTextArea:getDocument(...)@261 != null
*
* Test Vectors:
* javax.swing.text.Document:getLength(...)@261: {-231..0}, {1..232-1}
*/
261 if (feedback.getDocument().getLength() > 0) {
262 getOkButton().setEnabled(true);
263 } else {
264 getOkButton().setEnabled(false);
265 }
266 }
267
268 /**
269 * {@inheritDoc}
270 *
271 * @param e action event
272 */
273 @Override
274 public void actionPerformed(final ActionEvent e) {
/*
P/P * Method: void actionPerformed(ActionEvent)
*
* Preconditions:
* e != null
* (soft) init'ed(me)
* (soft) this.DMDircCheckbox != null
* (soft) this.email != null
* (soft) this.feedback != null
* (soft) this.name != null
* (soft) this.serverCheckbox != null
*
* Presumptions:
* java.awt.event.ActionEvent:getActionCommand(...)@275 != null
* java.awt.event.ActionEvent:getActionCommand(...)@277 != null
*
* Postconditions:
* me == One-of{old me, null}
* init'ed(me)
*
* Test Vectors:
* java.lang.String:equals(...)@275: {0}, {1}
* java.lang.String:equals(...)@277: {0}, {1}
*/
275 if (e.getActionCommand().equals("Send")) {
276 send();
277 } else if (e.getActionCommand().equals("Close")) {
278 dispose();
279 }
280 }
281
282 /** {@inheritDoc} */
283 @Override
284 public void insertUpdate(DocumentEvent e) {
/*
P/P * Method: void insertUpdate(DocumentEvent)
*
* Preconditions:
* this.feedback != null
*/
285 validateInput();
286 }
287
288 /** {@inheritDoc} */
289 @Override
290 public void removeUpdate(DocumentEvent e) {
/*
P/P * Method: void removeUpdate(DocumentEvent)
*
* Preconditions:
* this.feedback != null
*/
291 validateInput();
292 }
293
294 /** {@inheritDoc} */
295 @Override
296 public void changedUpdate(DocumentEvent e) {
297 //Ignore
/*
P/P * Method: void changedUpdate(DocumentEvent)
*/
298 }
299
300 /** {@inheritDoc} */
301 @Override
302 public void dispose() {
/*
P/P * Method: void dispose()
*
* Preconditions:
* init'ed(me)
*
* Postconditions:
* me == null
*
* Test Vectors:
* me: Inverse{null}, Addr_Set{null}
*/
303 if (me == null) {
304 return;
305 }
306 synchronized (me) {
307 super.dispose();
308 me = null;
309 }
310 }
311 }
312
313 /**
314 * Sends feedback worker thread.
315 */
316 class SendWorker extends LoggingSwingWorker {
317
318 /** Parent feedback dialog. */
319 private FeedbackDialog dialog;
320 /** Name. */
321 private String name;
322 /** Email. */
323 private String email;
324 /** Feedback. */
325 private String feedback;
326 /** Server name. */
327 private String serverInfo;
328 /** DMDirc Info. */
329 private String dmdircInfo;
330 /** Error/Success message. */
331 private StringBuilder error;
332
333 /**
334 * Creates a new send worker to send feedback.
335 *
336 * @param dialog Parent feedback dialog
337 * @param name Name
338 * @param email Email
339 * @param feedback Feedback
340 */
341 public SendWorker(FeedbackDialog dialog, String name, String email,
342 String feedback) {
/*
P/P * Method: void com.dmdirc.addons.ui_swing.dialogs.SendWorker(FeedbackDialog, String, String, String)
*
* Postconditions:
* this.dialog == dialog
* init'ed(this.dialog)
* this.dmdircInfo == &""
* this.serverInfo == &""
* this.email == email
* init'ed(this.email)
* this.error == &new StringBuilder(SendWorker#1)
* this.feedback == feedback
* init'ed(this.feedback)
* this.name == name
* ...
*/
343 this(dialog, name, email, feedback, "", "");
344 }
345
346 /**
347 * Creates a new send worker to send feedback.
348 *
349 * @param dialog Parent feedback dialog
350 * @param name Name
351 * @param email Email
352 * @param feedback Feedback
353 * @param serverInfo serverInfo
354 * @param dmdircInfo DMDirc info
355 */
356 public SendWorker(final FeedbackDialog dialog, final String name,
357 final String email, final String feedback,
/*
P/P * Method: void com.dmdirc.addons.ui_swing.dialogs.SendWorker(FeedbackDialog, String, String, String, String, String)
*
* Postconditions:
* this.dialog == dialog
* init'ed(this.dialog)
* this.dmdircInfo == dmdircInfo
* init'ed(this.dmdircInfo)
* this.email == email
* init'ed(this.email)
* this.error == &new StringBuilder(SendWorker#1)
* this.feedback == feedback
* init'ed(this.feedback)
* this.name == name
* ...
*/
358 final String serverInfo, final String dmdircInfo) {
359 this.dialog = dialog;
360 this.name = name;
361 this.email = email;
362 this.feedback = feedback;
363 this.serverInfo = serverInfo;
364 this.dmdircInfo = dmdircInfo;
365
366 error = new StringBuilder();
367 }
368
369 /**
370 * {@inheritDoc}
371 *
372 * @throws java.lang.Exception If unable to return a result
373 */
374 @Override
375 protected Object doInBackground() throws Exception {
/*
P/P * Method: Object doInBackground()
*
* Preconditions:
* this.dmdircInfo != null
* this.email != null
* this.feedback != null
* this.name != null
* this.serverInfo != null
* (soft) this.error != null
*
* Presumptions:
* com.dmdirc.config.IdentityManager:getGlobalConfig(...)@388 != null
* com.dmdirc.util.Downloader:getPage(...)@397 != null
*
* Postconditions:
* return_value == this.error
* return_value != null
* init'ed(this.error._tainted)
*
* Test Vectors:
* java.lang.String:isEmpty(...)@379: {1}, {0}
* java.lang.String:isEmpty(...)@382: {1}, {0}
* java.lang.String:isEmpty(...)@385: {1}, {0}
* java.lang.String:isEmpty(...)@389: {1}, {0}
* java.lang.String:isEmpty(...)@392: {1}, {0}
* java.util.List:size(...)@400: {-231..0}, {1..232-1}
*/
376 final Map<String, String> postData =
377 new HashMap<String, String>();
378
379 if (!name.isEmpty()) {
380 postData.put("name", name);
381 }
382 if (!email.isEmpty()) {
383 postData.put("email", email);
384 }
385 if (!feedback.isEmpty()) {
386 postData.put("feedback", feedback);
387 }
388 postData.put("version", IdentityManager.getGlobalConfig().getOption("version", "version"));
389 if (!serverInfo.isEmpty()) {
390 postData.put("serverInfo", serverInfo);
391 }
392 if (!dmdircInfo.isEmpty()) {
393 postData.put("dmdircInfo", dmdircInfo);
394 }
395
396 try {
397 final List<String> response =
398 Downloader.getPage("http://www.dmdirc.com/feedback.php",
399 postData);
400 if (response.size() >= 1) {
401 for (String responseLine : response) {
402 error.append(responseLine).append("\n");
403 }
404 } else {
405 error.append("Failure: Unknown response from the server.");
406 }
407 } catch (MalformedURLException ex) {
408 error.append("Malformed feedback URL.");
409 } catch (IOException ex) {
410 error.append("Failure: " + ex.getMessage());
411 }
412
413 return error;
414 }
415
416 /** {@inheritDoc} */
417 @Override
418 protected void done() {
/*
P/P * Method: void done()
*
* Preconditions:
* this.dialog != null
* this.dialog.info != null
* this.error != null
* (soft) init'ed(this.dialog.info.sas)
*/
419 super.done();
420 dialog.layoutComponents2(error);
421 }
422 }
SofCheck Inspector Build Version : 2.17854
| FeedbackDialog.java |
2009-Jun-25 01:54:24 |
| FeedbackDialog.class |
2009-Sep-02 17:04:15 |
| SendWorker.class |
2009-Sep-02 17:04:15 |