Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #include <dlfcn.h> |
michael@0 | 7 | #include <fcntl.h> |
michael@0 | 8 | #include <glib.h> |
michael@0 | 9 | #include <gtk/gtk.h> |
michael@0 | 10 | #include <string.h> |
michael@0 | 11 | |
michael@0 | 12 | #include <cctype> |
michael@0 | 13 | |
michael@0 | 14 | #include "mozilla/NullPtr.h" |
michael@0 | 15 | #include "crashreporter.h" |
michael@0 | 16 | #include "crashreporter_gtk_common.h" |
michael@0 | 17 | |
michael@0 | 18 | using std::string; |
michael@0 | 19 | using std::vector; |
michael@0 | 20 | |
michael@0 | 21 | using namespace CrashReporter; |
michael@0 | 22 | |
michael@0 | 23 | static GtkWidget* gViewReportButton = 0; |
michael@0 | 24 | static GtkWidget* gCommentTextLabel = 0; |
michael@0 | 25 | static GtkWidget* gCommentText = 0; |
michael@0 | 26 | static GtkWidget* gEmailMeCheck = 0; |
michael@0 | 27 | static GtkWidget* gEmailEntryLabel = 0; |
michael@0 | 28 | static GtkWidget* gEmailEntry = 0; |
michael@0 | 29 | |
michael@0 | 30 | static bool gEmailFieldHint = true; |
michael@0 | 31 | static bool gCommentFieldHint = true; |
michael@0 | 32 | |
michael@0 | 33 | // handle from dlopen'ing libgnome |
michael@0 | 34 | static void* gnomeLib = nullptr; |
michael@0 | 35 | // handle from dlopen'ing libgnomeui |
michael@0 | 36 | static void* gnomeuiLib = nullptr; |
michael@0 | 37 | |
michael@0 | 38 | static void LoadSettings() |
michael@0 | 39 | { |
michael@0 | 40 | /* |
michael@0 | 41 | * NOTE! This code needs to stay in sync with the preference checking |
michael@0 | 42 | * code in in nsExceptionHandler.cpp. |
michael@0 | 43 | */ |
michael@0 | 44 | |
michael@0 | 45 | StringTable settings; |
michael@0 | 46 | if (ReadStringsFromFile(gSettingsPath + "/" + kIniFile, settings, true)) { |
michael@0 | 47 | if (settings.find("Email") != settings.end()) { |
michael@0 | 48 | gtk_entry_set_text(GTK_ENTRY(gEmailEntry), settings["Email"].c_str()); |
michael@0 | 49 | gEmailFieldHint = false; |
michael@0 | 50 | } |
michael@0 | 51 | if (settings.find("EmailMe") != settings.end()) { |
michael@0 | 52 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gEmailMeCheck), |
michael@0 | 53 | settings["EmailMe"][0] != '0'); |
michael@0 | 54 | } |
michael@0 | 55 | if (settings.find("IncludeURL") != settings.end() && |
michael@0 | 56 | gIncludeURLCheck != 0) { |
michael@0 | 57 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gIncludeURLCheck), |
michael@0 | 58 | settings["IncludeURL"][0] != '0'); |
michael@0 | 59 | } |
michael@0 | 60 | bool enabled; |
michael@0 | 61 | if (settings.find("SubmitReport") != settings.end()) |
michael@0 | 62 | enabled = settings["SubmitReport"][0] != '0'; |
michael@0 | 63 | else |
michael@0 | 64 | enabled = ShouldEnableSending(); |
michael@0 | 65 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gSubmitReportCheck), |
michael@0 | 66 | enabled); |
michael@0 | 67 | } |
michael@0 | 68 | } |
michael@0 | 69 | |
michael@0 | 70 | void SaveSettings() |
michael@0 | 71 | { |
michael@0 | 72 | /* |
michael@0 | 73 | * NOTE! This code needs to stay in sync with the preference setting |
michael@0 | 74 | * code in in nsExceptionHandler.cpp. |
michael@0 | 75 | */ |
michael@0 | 76 | |
michael@0 | 77 | StringTable settings; |
michael@0 | 78 | |
michael@0 | 79 | ReadStringsFromFile(gSettingsPath + "/" + kIniFile, settings, true); |
michael@0 | 80 | if (!gEmailFieldHint) |
michael@0 | 81 | settings["Email"] = gtk_entry_get_text(GTK_ENTRY(gEmailEntry)); |
michael@0 | 82 | else |
michael@0 | 83 | settings.erase("Email"); |
michael@0 | 84 | |
michael@0 | 85 | settings["EmailMe"] = |
michael@0 | 86 | gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gEmailMeCheck)) ? "1" : "0"; |
michael@0 | 87 | if (gIncludeURLCheck != 0) |
michael@0 | 88 | settings["IncludeURL"] = |
michael@0 | 89 | gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gIncludeURLCheck)) |
michael@0 | 90 | ? "1" : "0"; |
michael@0 | 91 | settings["SubmitReport"] = |
michael@0 | 92 | gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gSubmitReportCheck)) |
michael@0 | 93 | ? "1" : "0"; |
michael@0 | 94 | |
michael@0 | 95 | WriteStringsToFile(gSettingsPath + "/" + kIniFile, |
michael@0 | 96 | "Crash Reporter", settings, true); |
michael@0 | 97 | } |
michael@0 | 98 | |
michael@0 | 99 | void SendReport() |
michael@0 | 100 | { |
michael@0 | 101 | // disable all our gui controls, show the throbber + change the progress text |
michael@0 | 102 | gtk_widget_set_sensitive(gSubmitReportCheck, FALSE); |
michael@0 | 103 | gtk_widget_set_sensitive(gViewReportButton, FALSE); |
michael@0 | 104 | gtk_widget_set_sensitive(gCommentText, FALSE); |
michael@0 | 105 | if (gIncludeURLCheck) |
michael@0 | 106 | gtk_widget_set_sensitive(gIncludeURLCheck, FALSE); |
michael@0 | 107 | gtk_widget_set_sensitive(gEmailMeCheck, FALSE); |
michael@0 | 108 | gtk_widget_set_sensitive(gEmailEntry, FALSE); |
michael@0 | 109 | gtk_widget_set_sensitive(gCloseButton, FALSE); |
michael@0 | 110 | if (gRestartButton) |
michael@0 | 111 | gtk_widget_set_sensitive(gRestartButton, FALSE); |
michael@0 | 112 | gtk_widget_show_all(gThrobber); |
michael@0 | 113 | gtk_label_set_text(GTK_LABEL(gProgressLabel), |
michael@0 | 114 | gStrings[ST_REPORTDURINGSUBMIT].c_str()); |
michael@0 | 115 | |
michael@0 | 116 | #ifdef MOZ_ENABLE_GCONF |
michael@0 | 117 | LoadProxyinfo(); |
michael@0 | 118 | #endif |
michael@0 | 119 | |
michael@0 | 120 | // and spawn a thread to do the sending |
michael@0 | 121 | GError* err; |
michael@0 | 122 | gSendThreadID = g_thread_create(SendThread, nullptr, TRUE, &err); |
michael@0 | 123 | } |
michael@0 | 124 | |
michael@0 | 125 | static void ShowReportInfo(GtkTextView* viewReportTextView) |
michael@0 | 126 | { |
michael@0 | 127 | GtkTextBuffer* buffer = |
michael@0 | 128 | gtk_text_view_get_buffer(viewReportTextView); |
michael@0 | 129 | |
michael@0 | 130 | GtkTextIter start, end; |
michael@0 | 131 | gtk_text_buffer_get_start_iter(buffer, &start); |
michael@0 | 132 | gtk_text_buffer_get_end_iter(buffer, &end); |
michael@0 | 133 | |
michael@0 | 134 | gtk_text_buffer_delete(buffer, &start, &end); |
michael@0 | 135 | |
michael@0 | 136 | for (StringTable::iterator iter = gQueryParameters.begin(); |
michael@0 | 137 | iter != gQueryParameters.end(); |
michael@0 | 138 | iter++) { |
michael@0 | 139 | gtk_text_buffer_insert(buffer, &end, iter->first.c_str(), -1); |
michael@0 | 140 | gtk_text_buffer_insert(buffer, &end, ": ", -1); |
michael@0 | 141 | gtk_text_buffer_insert(buffer, &end, iter->second.c_str(), -1); |
michael@0 | 142 | gtk_text_buffer_insert(buffer, &end, "\n", -1); |
michael@0 | 143 | } |
michael@0 | 144 | |
michael@0 | 145 | gtk_text_buffer_insert(buffer, &end, "\n", -1); |
michael@0 | 146 | gtk_text_buffer_insert(buffer, &end, |
michael@0 | 147 | gStrings[ST_EXTRAREPORTINFO].c_str(), -1); |
michael@0 | 148 | } |
michael@0 | 149 | |
michael@0 | 150 | void UpdateSubmit() |
michael@0 | 151 | { |
michael@0 | 152 | if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gSubmitReportCheck))) { |
michael@0 | 153 | gtk_widget_set_sensitive(gViewReportButton, TRUE); |
michael@0 | 154 | gtk_widget_set_sensitive(gCommentText, TRUE); |
michael@0 | 155 | if (gIncludeURLCheck) |
michael@0 | 156 | gtk_widget_set_sensitive(gIncludeURLCheck, TRUE); |
michael@0 | 157 | gtk_widget_set_sensitive(gEmailMeCheck, TRUE); |
michael@0 | 158 | gtk_widget_set_sensitive(gEmailEntry, |
michael@0 | 159 | gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gEmailMeCheck))); |
michael@0 | 160 | gtk_label_set_text(GTK_LABEL(gProgressLabel), |
michael@0 | 161 | gStrings[ST_REPORTPRESUBMIT].c_str()); |
michael@0 | 162 | } else { |
michael@0 | 163 | gtk_widget_set_sensitive(gViewReportButton, FALSE); |
michael@0 | 164 | gtk_widget_set_sensitive(gCommentText, FALSE); |
michael@0 | 165 | if (gIncludeURLCheck) |
michael@0 | 166 | gtk_widget_set_sensitive(gIncludeURLCheck, FALSE); |
michael@0 | 167 | gtk_widget_set_sensitive(gEmailMeCheck, FALSE); |
michael@0 | 168 | gtk_widget_set_sensitive(gEmailEntry, FALSE); |
michael@0 | 169 | gtk_label_set_text(GTK_LABEL(gProgressLabel), ""); |
michael@0 | 170 | } |
michael@0 | 171 | } |
michael@0 | 172 | |
michael@0 | 173 | static void ViewReportClicked(GtkButton* button, |
michael@0 | 174 | gpointer userData) |
michael@0 | 175 | { |
michael@0 | 176 | GtkDialog* dialog = |
michael@0 | 177 | GTK_DIALOG(gtk_dialog_new_with_buttons(gStrings[ST_VIEWREPORTTITLE].c_str(), |
michael@0 | 178 | GTK_WINDOW(gWindow), |
michael@0 | 179 | GTK_DIALOG_MODAL, |
michael@0 | 180 | GTK_STOCK_OK, |
michael@0 | 181 | GTK_RESPONSE_OK, |
michael@0 | 182 | nullptr)); |
michael@0 | 183 | |
michael@0 | 184 | GtkWidget* scrolled = gtk_scrolled_window_new(0, 0); |
michael@0 | 185 | gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(dialog)), scrolled); |
michael@0 | 186 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), |
michael@0 | 187 | GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); |
michael@0 | 188 | gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), |
michael@0 | 189 | GTK_SHADOW_IN); |
michael@0 | 190 | |
michael@0 | 191 | GtkWidget* viewReportTextView = gtk_text_view_new(); |
michael@0 | 192 | gtk_container_add(GTK_CONTAINER(scrolled), viewReportTextView); |
michael@0 | 193 | gtk_text_view_set_editable(GTK_TEXT_VIEW(viewReportTextView), FALSE); |
michael@0 | 194 | gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(viewReportTextView), |
michael@0 | 195 | GTK_WRAP_WORD); |
michael@0 | 196 | gtk_widget_set_size_request(GTK_WIDGET(viewReportTextView), -1, 100); |
michael@0 | 197 | |
michael@0 | 198 | ShowReportInfo(GTK_TEXT_VIEW(viewReportTextView)); |
michael@0 | 199 | |
michael@0 | 200 | gtk_dialog_set_default_response(dialog, GTK_RESPONSE_OK); |
michael@0 | 201 | gtk_widget_set_size_request(GTK_WIDGET(dialog), 400, 200); |
michael@0 | 202 | gtk_widget_show_all(GTK_WIDGET(dialog)); |
michael@0 | 203 | gtk_dialog_run(dialog); |
michael@0 | 204 | gtk_widget_destroy(GTK_WIDGET(dialog)); |
michael@0 | 205 | } |
michael@0 | 206 | |
michael@0 | 207 | static void CommentChanged(GtkTextBuffer* buffer, gpointer userData) |
michael@0 | 208 | { |
michael@0 | 209 | GtkTextIter start, end; |
michael@0 | 210 | gtk_text_buffer_get_start_iter(buffer, &start); |
michael@0 | 211 | gtk_text_buffer_get_end_iter(buffer, &end); |
michael@0 | 212 | const char* comment = gtk_text_buffer_get_text(buffer, &start, &end, TRUE); |
michael@0 | 213 | if (comment[0] == '\0' || gCommentFieldHint) |
michael@0 | 214 | gQueryParameters.erase("Comments"); |
michael@0 | 215 | else |
michael@0 | 216 | gQueryParameters["Comments"] = comment; |
michael@0 | 217 | } |
michael@0 | 218 | |
michael@0 | 219 | static void CommentInsert(GtkTextBuffer* buffer, |
michael@0 | 220 | GtkTextIter* location, |
michael@0 | 221 | gchar* text, |
michael@0 | 222 | gint len, |
michael@0 | 223 | gpointer userData) |
michael@0 | 224 | { |
michael@0 | 225 | GtkTextIter start, end; |
michael@0 | 226 | gtk_text_buffer_get_start_iter(buffer, &start); |
michael@0 | 227 | gtk_text_buffer_get_end_iter(buffer, &end); |
michael@0 | 228 | const char* comment = gtk_text_buffer_get_text(buffer, &start, &end, TRUE); |
michael@0 | 229 | |
michael@0 | 230 | // limit to 500 bytes in utf-8 |
michael@0 | 231 | if (strlen(comment) + len > MAX_COMMENT_LENGTH) { |
michael@0 | 232 | g_signal_stop_emission_by_name(buffer, "insert-text"); |
michael@0 | 233 | } |
michael@0 | 234 | } |
michael@0 | 235 | |
michael@0 | 236 | static void UpdateHintText(GtkWidget* widget, gboolean gainedFocus, |
michael@0 | 237 | bool* hintShowing, const char* hintText) |
michael@0 | 238 | { |
michael@0 | 239 | GtkTextBuffer* buffer = nullptr; |
michael@0 | 240 | if (GTK_IS_TEXT_VIEW(widget)) |
michael@0 | 241 | buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget)); |
michael@0 | 242 | |
michael@0 | 243 | if (gainedFocus) { |
michael@0 | 244 | if (*hintShowing) { |
michael@0 | 245 | if (buffer == nullptr) { // sort of cheating |
michael@0 | 246 | gtk_entry_set_text(GTK_ENTRY(widget), ""); |
michael@0 | 247 | } |
michael@0 | 248 | else { // GtkTextView |
michael@0 | 249 | gtk_text_buffer_set_text(buffer, "", 0); |
michael@0 | 250 | } |
michael@0 | 251 | gtk_widget_modify_text(widget, GTK_STATE_NORMAL, nullptr); |
michael@0 | 252 | *hintShowing = false; |
michael@0 | 253 | } |
michael@0 | 254 | } |
michael@0 | 255 | else { |
michael@0 | 256 | // lost focus |
michael@0 | 257 | const char* text = nullptr; |
michael@0 | 258 | if (buffer == nullptr) { |
michael@0 | 259 | text = gtk_entry_get_text(GTK_ENTRY(widget)); |
michael@0 | 260 | } |
michael@0 | 261 | else { |
michael@0 | 262 | GtkTextIter start, end; |
michael@0 | 263 | gtk_text_buffer_get_start_iter(buffer, &start); |
michael@0 | 264 | gtk_text_buffer_get_end_iter(buffer, &end); |
michael@0 | 265 | text = gtk_text_buffer_get_text(buffer, &start, &end, TRUE); |
michael@0 | 266 | } |
michael@0 | 267 | |
michael@0 | 268 | if (text == nullptr || text[0] == '\0') { |
michael@0 | 269 | *hintShowing = true; |
michael@0 | 270 | |
michael@0 | 271 | if (buffer == nullptr) { |
michael@0 | 272 | gtk_entry_set_text(GTK_ENTRY(widget), hintText); |
michael@0 | 273 | } |
michael@0 | 274 | else { |
michael@0 | 275 | gtk_text_buffer_set_text(buffer, hintText, -1); |
michael@0 | 276 | } |
michael@0 | 277 | |
michael@0 | 278 | gtk_widget_modify_text(widget, GTK_STATE_NORMAL, |
michael@0 | 279 | >k_widget_get_style(widget)->text[GTK_STATE_INSENSITIVE]); |
michael@0 | 280 | } |
michael@0 | 281 | } |
michael@0 | 282 | } |
michael@0 | 283 | |
michael@0 | 284 | static gboolean CommentFocusChange(GtkWidget* widget, GdkEventFocus* event, |
michael@0 | 285 | gpointer userData) |
michael@0 | 286 | { |
michael@0 | 287 | UpdateHintText(widget, event->in, &gCommentFieldHint, |
michael@0 | 288 | gStrings[ST_COMMENTGRAYTEXT].c_str()); |
michael@0 | 289 | |
michael@0 | 290 | return FALSE; |
michael@0 | 291 | } |
michael@0 | 292 | |
michael@0 | 293 | static void UpdateEmail() |
michael@0 | 294 | { |
michael@0 | 295 | const char* email = gtk_entry_get_text(GTK_ENTRY(gEmailEntry)); |
michael@0 | 296 | if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gEmailMeCheck))) { |
michael@0 | 297 | gtk_widget_set_sensitive(gEmailEntry, TRUE); |
michael@0 | 298 | } else { |
michael@0 | 299 | email = ""; |
michael@0 | 300 | gtk_widget_set_sensitive(gEmailEntry, FALSE); |
michael@0 | 301 | } |
michael@0 | 302 | if (email[0] == '\0' || gEmailFieldHint) |
michael@0 | 303 | gQueryParameters.erase("Email"); |
michael@0 | 304 | else |
michael@0 | 305 | gQueryParameters["Email"] = email; |
michael@0 | 306 | } |
michael@0 | 307 | |
michael@0 | 308 | static void EmailMeClicked(GtkButton* sender, gpointer userData) |
michael@0 | 309 | { |
michael@0 | 310 | UpdateEmail(); |
michael@0 | 311 | } |
michael@0 | 312 | |
michael@0 | 313 | static void EmailChanged(GtkEditable* editable, gpointer userData) |
michael@0 | 314 | { |
michael@0 | 315 | UpdateEmail(); |
michael@0 | 316 | } |
michael@0 | 317 | |
michael@0 | 318 | static gboolean EmailFocusChange(GtkWidget* widget, GdkEventFocus* event, |
michael@0 | 319 | gpointer userData) |
michael@0 | 320 | { |
michael@0 | 321 | UpdateHintText(widget, event->in, &gEmailFieldHint, |
michael@0 | 322 | gStrings[ST_EMAILGRAYTEXT].c_str()); |
michael@0 | 323 | |
michael@0 | 324 | return FALSE; |
michael@0 | 325 | } |
michael@0 | 326 | |
michael@0 | 327 | typedef struct _GnomeProgram GnomeProgram; |
michael@0 | 328 | typedef struct _GnomeModuleInfo GnomeModuleInfo; |
michael@0 | 329 | typedef GnomeProgram * (*_gnome_program_init_fn)(const char *, const char *, |
michael@0 | 330 | const GnomeModuleInfo *, int, |
michael@0 | 331 | char **, const char *, ...); |
michael@0 | 332 | typedef const GnomeModuleInfo * (*_libgnomeui_module_info_get_fn)(); |
michael@0 | 333 | |
michael@0 | 334 | void TryInitGnome() |
michael@0 | 335 | { |
michael@0 | 336 | gnomeLib = dlopen("libgnome-2.so.0", RTLD_LAZY); |
michael@0 | 337 | if (!gnomeLib) |
michael@0 | 338 | return; |
michael@0 | 339 | |
michael@0 | 340 | gnomeuiLib = dlopen("libgnomeui-2.so.0", RTLD_LAZY); |
michael@0 | 341 | if (!gnomeuiLib) |
michael@0 | 342 | return; |
michael@0 | 343 | |
michael@0 | 344 | _gnome_program_init_fn gnome_program_init = |
michael@0 | 345 | (_gnome_program_init_fn)(dlsym(gnomeLib, "gnome_program_init")); |
michael@0 | 346 | _libgnomeui_module_info_get_fn libgnomeui_module_info_get = |
michael@0 | 347 | (_libgnomeui_module_info_get_fn)(dlsym(gnomeuiLib, "libgnomeui_module_info_get")); |
michael@0 | 348 | |
michael@0 | 349 | if (gnome_program_init && libgnomeui_module_info_get) { |
michael@0 | 350 | gnome_program_init("crashreporter", "1.0", libgnomeui_module_info_get(), |
michael@0 | 351 | gArgc, gArgv, nullptr); |
michael@0 | 352 | } |
michael@0 | 353 | |
michael@0 | 354 | } |
michael@0 | 355 | |
michael@0 | 356 | /* === Crashreporter UI Functions === */ |
michael@0 | 357 | |
michael@0 | 358 | /* |
michael@0 | 359 | * Anything not listed here is in crashreporter_gtk_common.cpp: |
michael@0 | 360 | * UIInit |
michael@0 | 361 | * UIShowDefaultUI |
michael@0 | 362 | * UIError_impl |
michael@0 | 363 | * UIGetIniPath |
michael@0 | 364 | * UIGetSettingsPath |
michael@0 | 365 | * UIEnsurePathExists |
michael@0 | 366 | * UIFileExists |
michael@0 | 367 | * UIMoveFile |
michael@0 | 368 | * UIDeleteFile |
michael@0 | 369 | * UIOpenRead |
michael@0 | 370 | * UIOpenWrite |
michael@0 | 371 | */ |
michael@0 | 372 | |
michael@0 | 373 | void UIShutdown() |
michael@0 | 374 | { |
michael@0 | 375 | if (gnomeuiLib) |
michael@0 | 376 | dlclose(gnomeuiLib); |
michael@0 | 377 | // Don't dlclose gnomeLib as libgnomevfs and libORBit-2 use atexit(). |
michael@0 | 378 | } |
michael@0 | 379 | |
michael@0 | 380 | bool UIShowCrashUI(const string& dumpfile, |
michael@0 | 381 | const StringTable& queryParameters, |
michael@0 | 382 | const string& sendURL, |
michael@0 | 383 | const vector<string>& restartArgs) |
michael@0 | 384 | { |
michael@0 | 385 | gDumpFile = dumpfile; |
michael@0 | 386 | gQueryParameters = queryParameters; |
michael@0 | 387 | gSendURL = sendURL; |
michael@0 | 388 | gRestartArgs = restartArgs; |
michael@0 | 389 | if (gQueryParameters.find("URL") != gQueryParameters.end()) |
michael@0 | 390 | gURLParameter = gQueryParameters["URL"]; |
michael@0 | 391 | |
michael@0 | 392 | gWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
michael@0 | 393 | gtk_window_set_title(GTK_WINDOW(gWindow), |
michael@0 | 394 | gStrings[ST_CRASHREPORTERTITLE].c_str()); |
michael@0 | 395 | gtk_window_set_resizable(GTK_WINDOW(gWindow), FALSE); |
michael@0 | 396 | gtk_window_set_position(GTK_WINDOW(gWindow), GTK_WIN_POS_CENTER); |
michael@0 | 397 | gtk_container_set_border_width(GTK_CONTAINER(gWindow), 12); |
michael@0 | 398 | g_signal_connect(gWindow, "delete-event", G_CALLBACK(WindowDeleted), 0); |
michael@0 | 399 | g_signal_connect(gWindow, "key_press_event", G_CALLBACK(check_escape), nullptr); |
michael@0 | 400 | |
michael@0 | 401 | GtkWidget* vbox = gtk_vbox_new(FALSE, 6); |
michael@0 | 402 | gtk_container_add(GTK_CONTAINER(gWindow), vbox); |
michael@0 | 403 | |
michael@0 | 404 | GtkWidget* titleLabel = gtk_label_new(""); |
michael@0 | 405 | gtk_box_pack_start(GTK_BOX(vbox), titleLabel, FALSE, FALSE, 0); |
michael@0 | 406 | gtk_misc_set_alignment(GTK_MISC(titleLabel), 0, 0.5); |
michael@0 | 407 | char* markup = g_strdup_printf("<b>%s</b>", |
michael@0 | 408 | gStrings[ST_CRASHREPORTERHEADER].c_str()); |
michael@0 | 409 | gtk_label_set_markup(GTK_LABEL(titleLabel), markup); |
michael@0 | 410 | g_free(markup); |
michael@0 | 411 | |
michael@0 | 412 | GtkWidget* descriptionLabel = |
michael@0 | 413 | gtk_label_new(gStrings[ST_CRASHREPORTERDESCRIPTION].c_str()); |
michael@0 | 414 | gtk_box_pack_start(GTK_BOX(vbox), descriptionLabel, TRUE, TRUE, 0); |
michael@0 | 415 | // force the label to line wrap |
michael@0 | 416 | gtk_widget_set_size_request(descriptionLabel, 400, -1); |
michael@0 | 417 | gtk_label_set_line_wrap(GTK_LABEL(descriptionLabel), TRUE); |
michael@0 | 418 | gtk_label_set_selectable(GTK_LABEL(descriptionLabel), TRUE); |
michael@0 | 419 | gtk_misc_set_alignment(GTK_MISC(descriptionLabel), 0, 0.5); |
michael@0 | 420 | |
michael@0 | 421 | // this is honestly how they suggest you indent a section |
michael@0 | 422 | GtkWidget* indentBox = gtk_hbox_new(FALSE, 0); |
michael@0 | 423 | gtk_box_pack_start(GTK_BOX(vbox), indentBox, FALSE, FALSE, 0); |
michael@0 | 424 | gtk_box_pack_start(GTK_BOX(indentBox), gtk_label_new(""), FALSE, FALSE, 6); |
michael@0 | 425 | |
michael@0 | 426 | GtkWidget* innerVBox1 = gtk_vbox_new(FALSE, 0); |
michael@0 | 427 | gtk_box_pack_start(GTK_BOX(indentBox), innerVBox1, TRUE, TRUE, 0); |
michael@0 | 428 | |
michael@0 | 429 | gSubmitReportCheck = |
michael@0 | 430 | gtk_check_button_new_with_label(gStrings[ST_CHECKSUBMIT].c_str()); |
michael@0 | 431 | gtk_box_pack_start(GTK_BOX(innerVBox1), gSubmitReportCheck, FALSE, FALSE, 0); |
michael@0 | 432 | g_signal_connect(gSubmitReportCheck, "clicked", |
michael@0 | 433 | G_CALLBACK(SubmitReportChecked), 0); |
michael@0 | 434 | |
michael@0 | 435 | // indent again, below the "submit report" checkbox |
michael@0 | 436 | GtkWidget* indentBox2 = gtk_hbox_new(FALSE, 0); |
michael@0 | 437 | gtk_box_pack_start(GTK_BOX(innerVBox1), indentBox2, FALSE, FALSE, 0); |
michael@0 | 438 | gtk_box_pack_start(GTK_BOX(indentBox2), gtk_label_new(""), FALSE, FALSE, 6); |
michael@0 | 439 | |
michael@0 | 440 | GtkWidget* innerVBox = gtk_vbox_new(FALSE, 0); |
michael@0 | 441 | gtk_box_pack_start(GTK_BOX(indentBox2), innerVBox, TRUE, TRUE, 0); |
michael@0 | 442 | gtk_box_set_spacing(GTK_BOX(innerVBox), 6); |
michael@0 | 443 | |
michael@0 | 444 | GtkWidget* viewReportButtonBox = gtk_hbutton_box_new(); |
michael@0 | 445 | gtk_box_pack_start(GTK_BOX(innerVBox), viewReportButtonBox, FALSE, FALSE, 0); |
michael@0 | 446 | gtk_box_set_spacing(GTK_BOX(viewReportButtonBox), 6); |
michael@0 | 447 | gtk_button_box_set_layout(GTK_BUTTON_BOX(viewReportButtonBox), GTK_BUTTONBOX_START); |
michael@0 | 448 | |
michael@0 | 449 | gViewReportButton = |
michael@0 | 450 | gtk_button_new_with_label(gStrings[ST_VIEWREPORT].c_str()); |
michael@0 | 451 | gtk_box_pack_start(GTK_BOX(viewReportButtonBox), gViewReportButton, FALSE, FALSE, 0); |
michael@0 | 452 | g_signal_connect(gViewReportButton, "clicked", G_CALLBACK(ViewReportClicked), 0); |
michael@0 | 453 | |
michael@0 | 454 | GtkWidget* scrolled = gtk_scrolled_window_new(0, 0); |
michael@0 | 455 | gtk_container_add(GTK_CONTAINER(innerVBox), scrolled); |
michael@0 | 456 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), |
michael@0 | 457 | GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); |
michael@0 | 458 | gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), |
michael@0 | 459 | GTK_SHADOW_IN); |
michael@0 | 460 | |
michael@0 | 461 | gCommentTextLabel = gtk_label_new(gStrings[ST_COMMENTGRAYTEXT].c_str()); |
michael@0 | 462 | gCommentText = gtk_text_view_new(); |
michael@0 | 463 | gtk_label_set_mnemonic_widget(GTK_LABEL(gCommentTextLabel), gCommentText); |
michael@0 | 464 | gtk_text_view_set_accepts_tab(GTK_TEXT_VIEW(gCommentText), FALSE); |
michael@0 | 465 | g_signal_connect(gCommentText, "focus-in-event", G_CALLBACK(CommentFocusChange), 0); |
michael@0 | 466 | g_signal_connect(gCommentText, "focus-out-event", G_CALLBACK(CommentFocusChange), 0); |
michael@0 | 467 | |
michael@0 | 468 | GtkTextBuffer* commentBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gCommentText)); |
michael@0 | 469 | g_signal_connect(commentBuffer, "changed", G_CALLBACK(CommentChanged), 0); |
michael@0 | 470 | g_signal_connect(commentBuffer, "insert-text", G_CALLBACK(CommentInsert), 0); |
michael@0 | 471 | |
michael@0 | 472 | gtk_container_add(GTK_CONTAINER(scrolled), gCommentText); |
michael@0 | 473 | gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(gCommentText), |
michael@0 | 474 | GTK_WRAP_WORD); |
michael@0 | 475 | gtk_widget_set_size_request(GTK_WIDGET(gCommentText), -1, 100); |
michael@0 | 476 | |
michael@0 | 477 | if (gQueryParameters.find("URL") != gQueryParameters.end()) { |
michael@0 | 478 | gIncludeURLCheck = |
michael@0 | 479 | gtk_check_button_new_with_label(gStrings[ST_CHECKURL].c_str()); |
michael@0 | 480 | gtk_box_pack_start(GTK_BOX(innerVBox), gIncludeURLCheck, FALSE, FALSE, 0); |
michael@0 | 481 | g_signal_connect(gIncludeURLCheck, "clicked", G_CALLBACK(IncludeURLClicked), 0); |
michael@0 | 482 | // on by default |
michael@0 | 483 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gIncludeURLCheck), TRUE); |
michael@0 | 484 | } |
michael@0 | 485 | |
michael@0 | 486 | gEmailMeCheck = |
michael@0 | 487 | gtk_check_button_new_with_label(gStrings[ST_CHECKEMAIL].c_str()); |
michael@0 | 488 | gtk_box_pack_start(GTK_BOX(innerVBox), gEmailMeCheck, FALSE, FALSE, 0); |
michael@0 | 489 | g_signal_connect(gEmailMeCheck, "clicked", G_CALLBACK(EmailMeClicked), 0); |
michael@0 | 490 | |
michael@0 | 491 | GtkWidget* emailIndentBox = gtk_hbox_new(FALSE, 0); |
michael@0 | 492 | gtk_box_pack_start(GTK_BOX(innerVBox), emailIndentBox, FALSE, FALSE, 0); |
michael@0 | 493 | gtk_box_pack_start(GTK_BOX(emailIndentBox), gtk_label_new(""), |
michael@0 | 494 | FALSE, FALSE, 9); |
michael@0 | 495 | |
michael@0 | 496 | gEmailEntryLabel = gtk_label_new(gStrings[ST_EMAILGRAYTEXT].c_str()); |
michael@0 | 497 | gEmailEntry = gtk_entry_new(); |
michael@0 | 498 | gtk_label_set_mnemonic_widget(GTK_LABEL(gEmailEntryLabel), gEmailEntry); |
michael@0 | 499 | gtk_box_pack_start(GTK_BOX(emailIndentBox), gEmailEntry, TRUE, TRUE, 0); |
michael@0 | 500 | g_signal_connect(gEmailEntry, "changed", G_CALLBACK(EmailChanged), 0); |
michael@0 | 501 | g_signal_connect(gEmailEntry, "focus-in-event", G_CALLBACK(EmailFocusChange), 0); |
michael@0 | 502 | g_signal_connect(gEmailEntry, "focus-out-event", G_CALLBACK(EmailFocusChange), 0); |
michael@0 | 503 | |
michael@0 | 504 | GtkWidget* progressBox = gtk_hbox_new(FALSE, 6); |
michael@0 | 505 | gtk_box_pack_start(GTK_BOX(vbox), progressBox, TRUE, TRUE, 0); |
michael@0 | 506 | |
michael@0 | 507 | // Get the throbber image from alongside the executable |
michael@0 | 508 | char* dir = g_path_get_dirname(gArgv[0]); |
michael@0 | 509 | char* path = g_build_filename(dir, "Throbber-small.gif", nullptr); |
michael@0 | 510 | g_free(dir); |
michael@0 | 511 | gThrobber = gtk_image_new_from_file(path); |
michael@0 | 512 | gtk_box_pack_start(GTK_BOX(progressBox), gThrobber, FALSE, FALSE, 0); |
michael@0 | 513 | |
michael@0 | 514 | gProgressLabel = |
michael@0 | 515 | gtk_label_new(gStrings[ST_REPORTPRESUBMIT].c_str()); |
michael@0 | 516 | gtk_box_pack_start(GTK_BOX(progressBox), gProgressLabel, TRUE, TRUE, 0); |
michael@0 | 517 | // force the label to line wrap |
michael@0 | 518 | gtk_widget_set_size_request(gProgressLabel, 400, -1); |
michael@0 | 519 | gtk_label_set_line_wrap(GTK_LABEL(gProgressLabel), TRUE); |
michael@0 | 520 | |
michael@0 | 521 | GtkWidget* buttonBox = gtk_hbutton_box_new(); |
michael@0 | 522 | gtk_box_pack_end(GTK_BOX(vbox), buttonBox, FALSE, FALSE, 0); |
michael@0 | 523 | gtk_box_set_spacing(GTK_BOX(buttonBox), 6); |
michael@0 | 524 | gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonBox), GTK_BUTTONBOX_END); |
michael@0 | 525 | |
michael@0 | 526 | gCloseButton = |
michael@0 | 527 | gtk_button_new_with_label(gStrings[ST_QUIT].c_str()); |
michael@0 | 528 | gtk_box_pack_start(GTK_BOX(buttonBox), gCloseButton, FALSE, FALSE, 0); |
michael@0 | 529 | gtk_widget_set_can_default(gCloseButton, TRUE); |
michael@0 | 530 | g_signal_connect(gCloseButton, "clicked", G_CALLBACK(CloseClicked), 0); |
michael@0 | 531 | |
michael@0 | 532 | gRestartButton = 0; |
michael@0 | 533 | if (restartArgs.size() > 0) { |
michael@0 | 534 | gRestartButton = gtk_button_new_with_label(gStrings[ST_RESTART].c_str()); |
michael@0 | 535 | gtk_box_pack_start(GTK_BOX(buttonBox), gRestartButton, FALSE, FALSE, 0); |
michael@0 | 536 | gtk_widget_set_can_default(gRestartButton, TRUE); |
michael@0 | 537 | g_signal_connect(gRestartButton, "clicked", G_CALLBACK(RestartClicked), 0); |
michael@0 | 538 | } |
michael@0 | 539 | |
michael@0 | 540 | gtk_widget_grab_focus(gSubmitReportCheck); |
michael@0 | 541 | |
michael@0 | 542 | gtk_widget_grab_default(gRestartButton ? gRestartButton : gCloseButton); |
michael@0 | 543 | |
michael@0 | 544 | LoadSettings(); |
michael@0 | 545 | |
michael@0 | 546 | UpdateEmail(); |
michael@0 | 547 | UpdateSubmit(); |
michael@0 | 548 | |
michael@0 | 549 | UpdateHintText(gCommentText, FALSE, &gCommentFieldHint, |
michael@0 | 550 | gStrings[ST_COMMENTGRAYTEXT].c_str()); |
michael@0 | 551 | UpdateHintText(gEmailEntry, FALSE, &gEmailFieldHint, |
michael@0 | 552 | gStrings[ST_EMAILGRAYTEXT].c_str()); |
michael@0 | 553 | |
michael@0 | 554 | gtk_widget_show_all(gWindow); |
michael@0 | 555 | // stick this here to avoid the show_all above... |
michael@0 | 556 | gtk_widget_hide(gThrobber); |
michael@0 | 557 | |
michael@0 | 558 | gtk_main(); |
michael@0 | 559 | |
michael@0 | 560 | return gDidTrySend; |
michael@0 | 561 | } |