You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ServerDialog.cxx 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
  2. * Copyright 2012 Samuel Mannehed <samuel@cendio.se> for Cendio AB
  3. *
  4. * This is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This software 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
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this software; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  17. * USA.
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. #include <config.h>
  21. #endif
  22. #include <FL/Fl.H>
  23. #include <FL/Fl_Input.H>
  24. #include <FL/Fl_Input_Choice.H>
  25. #include <FL/Fl_Button.H>
  26. #include <FL/Fl_Return_Button.H>
  27. #include <FL/fl_draw.H>
  28. #include <FL/fl_ask.H>
  29. #include <FL/Fl_Box.H>
  30. #include <FL/Fl_File_Chooser.H>
  31. #include <algorithm>
  32. #include <iostream>
  33. #include <fstream>
  34. #include <os/os.h>
  35. #include <rfb/Exception.h>
  36. #include "ServerDialog.h"
  37. #include "OptionsDialog.h"
  38. #include "fltk_layout.h"
  39. #include "i18n.h"
  40. #include "vncviewer.h"
  41. #include "parameters.h"
  42. using namespace std;
  43. using namespace rfb;
  44. const char* SERVER_HISTORY="tigervnc.history";
  45. ServerDialog::ServerDialog()
  46. : Fl_Window(450, 160, _("VNC Viewer: Connection Details"))
  47. {
  48. int x, y;
  49. Fl_Button *button;
  50. Fl_Box *divider;
  51. int margin = 20;
  52. int server_label_width = gui_str_len(_("VNC server:"));
  53. x = margin + server_label_width;
  54. y = margin;
  55. serverName = new Fl_Input_Choice(x, y, w() - margin*2 - server_label_width, INPUT_HEIGHT, _("VNC server:"));
  56. loadServerHistory();
  57. for(size_t i=0;i<serverHistory.size();++i) {
  58. serverName->add(serverHistory[i].c_str());
  59. }
  60. int adjust = (w() - 20) / 4;
  61. int button_width = adjust - margin/2;
  62. x = margin;
  63. y = margin + margin/2 + INPUT_HEIGHT;
  64. y += margin/2;
  65. button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("Options..."));
  66. button->callback(this->handleOptions, this);
  67. x += adjust;
  68. button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("Load..."));
  69. button->callback(this->handleLoad, this);
  70. x += adjust;
  71. button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("Save As..."));
  72. button->callback(this->handleSaveAs, this);
  73. x = 0;
  74. y += margin/2 + BUTTON_HEIGHT;
  75. divider = new Fl_Box(x, y, w(), 2);
  76. divider->box(FL_THIN_DOWN_FRAME);
  77. x += margin;
  78. y += margin/2;
  79. button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("About..."));
  80. button->callback(this->handleAbout, this);
  81. x = w() - margin - adjust - button_width - 20;
  82. button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("Cancel"));
  83. button->callback(this->handleCancel, this);
  84. x += adjust;
  85. button = new Fl_Return_Button(x, y, button_width+20, BUTTON_HEIGHT, _("Connect"));
  86. button->callback(this->handleConnect, this);
  87. callback(this->handleCancel, this);
  88. set_modal();
  89. }
  90. ServerDialog::~ServerDialog()
  91. {
  92. }
  93. void ServerDialog::run(const char* servername, char *newservername)
  94. {
  95. ServerDialog dialog;
  96. dialog.serverName->value(servername);
  97. dialog.show();
  98. while (dialog.shown()) Fl::wait();
  99. if (dialog.serverName->value() == NULL) {
  100. newservername[0] = '\0';
  101. return;
  102. }
  103. strncpy(newservername, dialog.serverName->value(), VNCSERVERNAMELEN);
  104. newservername[VNCSERVERNAMELEN - 1] = '\0';
  105. }
  106. void ServerDialog::handleOptions(Fl_Widget *widget, void *data)
  107. {
  108. OptionsDialog::showDialog();
  109. }
  110. void ServerDialog::handleLoad(Fl_Widget *widget, void *data)
  111. {
  112. ServerDialog *dialog = (ServerDialog*)data;
  113. Fl_File_Chooser* file_chooser = new Fl_File_Chooser("", _("TigerVNC configuration (*.tigervnc)"),
  114. 0, _("Select a TigerVNC configuration file"));
  115. file_chooser->preview(0);
  116. file_chooser->previewButton->hide();
  117. file_chooser->show();
  118. // Block until user picks something.
  119. while(file_chooser->shown())
  120. Fl::wait();
  121. // Did the user hit cancel?
  122. if (file_chooser->value() == NULL) {
  123. delete(file_chooser);
  124. return;
  125. }
  126. const char* filename = file_chooser->value();
  127. try {
  128. dialog->serverName->value(loadViewerParameters(filename));
  129. } catch (Exception& e) {
  130. fl_alert("%s", e.str());
  131. }
  132. delete(file_chooser);
  133. }
  134. void ServerDialog::handleSaveAs(Fl_Widget *widget, void *data)
  135. {
  136. ServerDialog *dialog = (ServerDialog*)data;
  137. const char* servername = dialog->serverName->value();
  138. const char* filename;
  139. Fl_File_Chooser* file_chooser = new Fl_File_Chooser("", _("TigerVNC configuration (*.tigervnc)"),
  140. 2, _("Save the TigerVNC configuration to file"));
  141. file_chooser->preview(0);
  142. file_chooser->previewButton->hide();
  143. file_chooser->show();
  144. while(1) {
  145. // Block until user picks something.
  146. while(file_chooser->shown())
  147. Fl::wait();
  148. // Did the user hit cancel?
  149. if (file_chooser->value() == NULL) {
  150. delete(file_chooser);
  151. return;
  152. }
  153. filename = file_chooser->value();
  154. FILE* f = fopen(filename, "r");
  155. if (f) {
  156. // The file already exists.
  157. fclose(f);
  158. int overwrite_choice = fl_choice(_("%s already exists. Do you want to overwrite?"),
  159. _("Overwrite"), _("No"), NULL, filename);
  160. if (overwrite_choice == 1) {
  161. // If the user doesn't want to overwrite:
  162. file_chooser->show();
  163. continue;
  164. }
  165. }
  166. break;
  167. }
  168. try {
  169. saveViewerParameters(filename, servername);
  170. } catch (Exception& e) {
  171. fl_alert("%s", e.str());
  172. }
  173. delete(file_chooser);
  174. }
  175. void ServerDialog::handleAbout(Fl_Widget *widget, void *data)
  176. {
  177. about_vncviewer();
  178. }
  179. void ServerDialog::handleCancel(Fl_Widget *widget, void *data)
  180. {
  181. ServerDialog *dialog = (ServerDialog*)data;
  182. dialog->serverName->value("");
  183. dialog->hide();
  184. }
  185. void ServerDialog::handleConnect(Fl_Widget *widget, void *data)
  186. {
  187. ServerDialog *dialog = (ServerDialog*)data;
  188. const char* servername = dialog->serverName->value();
  189. dialog->hide();
  190. try {
  191. saveViewerParameters(NULL, servername);
  192. vector<string>::iterator elem = std::find(dialog->serverHistory.begin(), dialog->serverHistory.end(), servername);
  193. // avoid duplicates in the history
  194. if(dialog->serverHistory.end() == elem) {
  195. dialog->serverHistory.insert(dialog->serverHistory.begin(), servername);
  196. dialog->saveServerHistory();
  197. }
  198. } catch (Exception& e) {
  199. fl_alert("%s", e.str());
  200. }
  201. }
  202. void ServerDialog::loadServerHistory()
  203. {
  204. #ifdef _WIN32
  205. loadHistoryFromRegKey(serverHistory);
  206. return;
  207. #endif
  208. char* homeDir = NULL;
  209. if (getvnchomedir(&homeDir) == -1) {
  210. throw Exception(_("Failed to read server history file, "
  211. "can't obtain home directory path."));
  212. }
  213. char filepath[PATH_MAX];
  214. snprintf(filepath, sizeof(filepath), "%s%s", homeDir, SERVER_HISTORY);
  215. delete[] homeDir;
  216. /* Read server history from file */
  217. ifstream f (filepath);
  218. if (!f.is_open()) {
  219. // no history file
  220. return;
  221. }
  222. string line;
  223. while(getline(f, line)) {
  224. serverHistory.push_back(line);
  225. }
  226. if (f.bad()) {
  227. throw Exception(_("Failed to read server history file, "
  228. "error while reading file."));
  229. }
  230. f.close();
  231. }
  232. void ServerDialog::saveServerHistory()
  233. {
  234. #ifdef _WIN32
  235. saveHistoryToRegKey(serverHistory);
  236. return;
  237. #endif
  238. char* homeDir = NULL;
  239. if (getvnchomedir(&homeDir) == -1) {
  240. throw Exception(_("Failed to write server history file, "
  241. "can't obtain home directory path."));
  242. }
  243. char filepath[PATH_MAX];
  244. snprintf(filepath, sizeof(filepath), "%s%s", homeDir, SERVER_HISTORY);
  245. delete[] homeDir;
  246. /* Write server history to file */
  247. ofstream f (filepath);
  248. if (!f.is_open()) {
  249. throw Exception(_("Failed to write server history file, "
  250. "can't open file."));
  251. }
  252. // Save the last X elements to the config file.
  253. for(size_t i=0; i < serverHistory.size() && i <= SERVER_HISTORY_SIZE; i++) {
  254. f << serverHistory[i] << endl;
  255. }
  256. if (f.bad()) {
  257. throw Exception(_("Failed to write server history file, "
  258. "error while writing file."));
  259. }
  260. f.close();
  261. }