Make it possible to load and save configuration files. Also, when
connecting, the options are saved as default settings. This patch
fixes SF bugs 3481470 and 3499216. 



git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4950 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/vncviewer/ServerDialog.cxx b/vncviewer/ServerDialog.cxx
index 4f21eb1..25a010a 100644
--- a/vncviewer/ServerDialog.cxx
+++ b/vncviewer/ServerDialog.cxx
@@ -1,4 +1,5 @@
 /* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+ * Copyright 2012 Samuel Mannehed <samuel@cendio.se> for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -25,35 +26,75 @@
 #include <FL/Fl_Button.H>
 #include <FL/Fl_Return_Button.H>
 #include <FL/fl_draw.H>
+#include <FL/fl_ask.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_File_Chooser.H>
 
 #include "ServerDialog.h"
 #include "OptionsDialog.h"
 #include "fltk_layout.h"
 #include "i18n.h"
 #include "vncviewer.h"
+#include "parameters.h"
+#include "rfb/Exception.h"
 
 ServerDialog::ServerDialog()
-  : Fl_Window(400, 112, _("VNC Viewer: Connection Details"))
+  : Fl_Window(450, 160, _("VNC Viewer: Connection Details"))
 {
-  int width;
+  int x, y;
   Fl_Button *button;
+  Fl_Box *divider;
 
-  width = gui_str_len(_("VNC server:"));
-  serverName = new Fl_Input(20 + width, 20, w() - 20*2 - width, 25, _("VNC server:"));
+  int margin = 20;
+  int server_label_width = gui_str_len(_("VNC server:"));
 
-  width = (w() - 20) / 4;
+  x = margin + server_label_width;
+  y = margin;
+  
+  serverName = new Fl_Input(x, y, w() - margin*2 - server_label_width, INPUT_HEIGHT, _("VNC server:"));
 
-  button = new Fl_Button(20 + width*0, 20+25+20, width - 20, 27, _("About..."));
+  int adjust = (w() - 20) / 4;
+  int button_width = adjust - margin/2;
+
+  x = margin;
+  y = margin + margin/2 + INPUT_HEIGHT;
+
+  y += margin/2;
+
+  button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("Options..."));
+  button->callback(this->handleOptions, this);
+  
+  x += adjust;
+  
+  button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("Load..."));
+  button->callback(this->handleLoad, this);
+
+  x += adjust;
+
+  button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("Save As..."));
+  button->callback(this->handleSaveAs, this);
+  
+  x = 0;
+  y += margin/2 + BUTTON_HEIGHT;
+
+  divider = new Fl_Box(x, y, w(), 2);
+  divider->box(FL_THIN_DOWN_FRAME);
+  
+  x += margin;
+  y += margin/2;
+
+  button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("About..."));
   button->callback(this->handleAbout, this);
 
-  button = new Fl_Button(20 + width*1, 20+25+20, width - 20, 27, _("Options..."));
-  button->callback(this->handleOptions, this);
+  x = w() - margin - adjust - button_width - 20;
 
-  button = new Fl_Button(20 + width*2, 20+25+20, width - 20, 27, _("Cancel"));
+  button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("Cancel"));
   button->callback(this->handleCancel, this);
 
-  button = new Fl_Return_Button(20 + width*3, 20+25+20, width - 20, 27, _("OK"));
-  button->callback(this->handleOK, this);
+  x += adjust;
+
+  button = new Fl_Return_Button(x, y, button_width+20, BUTTON_HEIGHT, _("Connect"));
+  button->callback(this->handleConnect, this);
 
   callback(this->handleCancel, this);
 
@@ -66,11 +107,13 @@
 }
 
 
-const char *ServerDialog::run()
+const char *ServerDialog::run(const char* servername)
 {
   ServerDialog dialog;
   static char buffer[256];
 
+  dialog.serverName->value(servername);
+  
   dialog.show();
   while (dialog.shown()) Fl::wait();
 
@@ -83,6 +126,97 @@
   return buffer;
 }
 
+void ServerDialog::handleOptions(Fl_Widget *widget, void *data)
+{
+  OptionsDialog::showDialog();
+}
+
+
+void ServerDialog::handleLoad(Fl_Widget *widget, void *data)
+{
+  ServerDialog *dialog = (ServerDialog*)data;
+  Fl_File_Chooser* file_chooser = new Fl_File_Chooser("", "TigerVNC configuration (*.tigervnc)", 
+						      0, "Select a TigerVNC configuration file");
+  file_chooser->preview(0);
+  file_chooser->previewButton->hide();
+  file_chooser->show();
+  
+  // Block until user picks something.
+  while(file_chooser->shown())
+    Fl::wait();
+  
+  // Did the user hit cancel?
+  if (file_chooser->value() == NULL) {
+    delete(file_chooser);
+    return;
+  }
+  
+  const char* filename = strdup(file_chooser->value());
+
+  try {
+    dialog->serverName->value(loadViewerParameters(filename));
+  } catch (rfb::Exception& e) {
+    fl_alert("%s", e.str());
+  }
+
+  delete(file_chooser);
+}
+
+
+void ServerDialog::handleSaveAs(Fl_Widget *widget, void *data)
+{ 
+  ServerDialog *dialog = (ServerDialog*)data;
+  const char* servername = strdup(dialog->serverName->value());
+  char* filename;
+
+  Fl_File_Chooser* file_chooser = new Fl_File_Chooser("", "TigerVNC configuration (*.tigervnc)", 
+						      2, "Save the TigerVNC configuration to file");
+  
+  file_chooser->preview(0);
+  file_chooser->previewButton->hide();
+  file_chooser->show();
+  
+  while(1) {
+    
+    // Block until user picks something.
+    while(file_chooser->shown())
+      Fl::wait();
+    
+    // Did the user hit cancel?
+    if (file_chooser->value() == NULL) {
+      delete(file_chooser);
+      return;
+    }
+    
+    filename = strdup(file_chooser->value());
+    
+    FILE* f = fopen(filename, "r");
+    if (f) {
+
+      // The file already exists.
+      fclose(f);
+      int overwrite_choice = fl_choice("%s already exists. Do you want to overwrite?", 
+				       "Overwrite", "No", NULL, filename);
+      if (overwrite_choice == 1) {
+
+	// If the user doesn't want to overwrite:
+	file_chooser->show();
+	continue;
+      }
+    }
+
+    break;
+  }
+  
+  try {
+    saveViewerParameters(filename, servername);
+  } catch (rfb::Exception& e) {
+    fl_alert("%s", e.str());
+  }
+  
+  delete(file_chooser);
+}
+
 
 void ServerDialog::handleAbout(Fl_Widget *widget, void *data)
 {
@@ -90,12 +224,6 @@
 }
 
 
-void ServerDialog::handleOptions(Fl_Widget *widget, void *data)
-{
-  OptionsDialog::showDialog();
-}
-
-
 void ServerDialog::handleCancel(Fl_Widget *widget, void *data)
 {
   ServerDialog *dialog = (ServerDialog*)data;
@@ -105,9 +233,16 @@
 }
 
 
-void ServerDialog::handleOK(Fl_Widget *widget, void *data)
+void ServerDialog::handleConnect(Fl_Widget *widget, void *data)
 {
   ServerDialog *dialog = (ServerDialog*)data;
+  const char* servername = strdup(dialog->serverName->value());
 
   dialog->hide();
+  
+  try {
+    saveViewerParameters(NULL, servername);
+  } catch (rfb::Exception& e) {
+    fl_alert("%s", e.str());
+  }
 }