Vidalia  0.3.1
TorrcDialog.cpp
Go to the documentation of this file.
1 /*
2 ** This file is part of Vidalia, and is subject to the license terms in the
3 ** LICENSE file, found in the top level directory of this distribution. If you
4 ** did not receive the LICENSE file with this file, you may obtain it from the
5 ** Vidalia source package distributed by the Vidalia Project at
6 ** http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
7 ** including this file, may be copied, modified, propagated, or distributed
8 ** except according to the terms described in the LICENSE file.
9 */
10 
11 /*
12 ** \file TorrcDialog.cpp
13 ** \brief Torrc Dialog, contains the dialog for displaying and editing the torrc
14 **
15 ** Implements the dialog for editing the torrc file inside Vidalia
16 */
17 
18 #include "TorrcDialog.h"
19 #include "Vidalia.h"
20 
21 #include <QMessageBox>
22 #include <QToolBar>
23 
24 void
25 TorHighlighter::highlightBlock(const QString &text)
26 {
27  bool firstFormatted = false;
28 
29  for (int i = 0; i < text.length(); ++i) {
30  if(text.mid(i, 1) == " " and !firstFormatted) {
31  setFormat(0, i, QColor(2,71,105));
32  setFormat(i, text.length() - 1, Qt::gray);
33  firstFormatted = true;
34  } else if (text.mid(i, 1) == "#") {
35  setFormat(i, text.length() - i, QColor(112,144,128));
36  break;
37  }
38  }
39 }
40 
41 /** Constructor */
42 TorrcDialog::TorrcDialog(QWidget *parent)
43 : QDialog(parent)
44 {
45  /* Invoke the Qt Designer generated object setup routine */
46  ui.setupUi(this);
47  loadToolBar();
48 
49  TorHighlighter *highlighter = new TorHighlighter(ui.teditTorrc);
50 
51  /* Retrieve the global TorControl instance */
53  /* Load the torrc file to the TextEdit */
54  loadTorrc();
55 
56  /* Connect the accepted event from the dialog with the parsing and saving
57  * routine */
58  connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(saveTorrc()));
59 }
60 
61 /** Destructor */
63 {
64 
65 }
66 
67 void
69 {
70  QToolBar *tb = new QToolBar(this);
71  tb->addAction(ui.actionCut);
72  tb->addAction(ui.actionCopy);
73  tb->addAction(ui.actionPaste);
74  tb->addAction(ui.actionUndo);
75  tb->addAction(ui.actionRedo);
76  tb->addAction(ui.actionSelect_All);
77 
78  tb->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
79  ui.verticalLayout->insertWidget(0, tb);
80 }
81 
82 /** Gives a shallow parse phase to the settings to catch most errors
83  * and passes on the error messages from Tor if the setting's value isn't
84  * valid. It returns false if something went wrong.
85  * If there's a problem in the setting stage, changes to that point will
86  * remaind but won't be saved. */
87 bool
88 TorrcDialog::parseAndSet(QString *errmsg)
89 {
90  if(!errmsg) errmsg = new QString("");
91  if(!tc || !tc->isConnected()) {
92  *errmsg = tr("Error connecting to Tor");
93  return false;
94  }
95 
96  QString key, val;
97  QStringList parts, lines;
98 
99  if(ui.rdoAll->isChecked())
100  lines = ui.teditTorrc->toPlainText().split('\n', QString::SkipEmptyParts);
101  else {
102  QString tmp = ui.teditTorrc->toPlainText();
103  QTextCursor tcursor = ui.teditTorrc->textCursor();
104  int start = tcursor.selectionStart();
105  int end = tcursor.selectionEnd();
106  tmp = tmp.mid(start, end - start).trimmed();
107  if(tmp.isEmpty()) {
108  *errmsg = tr("Selection is empty. Please select some text, or check \"Apply all\"");
109  return false;
110  }
111 
112  lines = tmp.split('\n', QString::SkipEmptyParts);
113  }
114  /* First pass: parsing */
115  int i = 0;
116  foreach(QString line, lines) {
117  i++;
118  line = line.trimmed();
119  if(line.startsWith("#")) continue; // Skip commentaries
120  parts = line.split(" ", QString::SkipEmptyParts);
121  if(parts.count() < 2) {
122  *errmsg = tr("Error at line %1: \"%2\"").arg(i).arg(line);
123  return false;
124  }
125  }
126  /* Second pass: setting */
127  QHash<QString,QString> settings;
128  foreach(QString line, lines) {
129  line = line.trimmed();
130  parts = line.split(" ", QString::SkipEmptyParts);
131  key = parts[0];
132  parts.removeFirst();
133  val = parts.join(" ");
134  settings.insert(key, val);
135  }
136 
137  if(!tc->setConf(settings, errmsg)) return false;
138 
139  return true;
140 }
141 
142 /** Loads the saved torrc file that Tor's using to the TextEdit widget for
143  * editing */
144 void
146 {
147  if(tc && tc->isConnected()) {
148  QString text = "";
149  QFile file(tc->getInfo("config-file").toString());
150  if(file.open(QFile::ReadOnly)) {
151  QTextStream in(&file);
152  QString line = "";
153  do {
154  line = in.readLine();
155  text += line + "\n";
156  } while(!line.isNull());
157  ui.teditTorrc->setText(text);
158  } else {
159  QMessageBox::critical(this, tr("Error"), tr("An error ocurred while opening torrc file"));
160  }
161  }
162 }
163 
164 /** Calls the parsing and setting routine, and if everything went right
165  * it saves the configuration to the torrc file through the SAVECONF control */
166 void
168 {
169  QString errmsg = "";
170  if(tc && tc->isConnected()) {
171  if(!parseAndSet(&errmsg)) {
172  QMessageBox::critical(this, tr("Error"), errmsg);
173  return;
174  }
175  if(ui.chkSave->isChecked()) {
176  if(!tc->saveConf(&errmsg)) {
177  QMessageBox::critical(this, tr("Error"), errmsg);
178  return;
179  }
180  }
181  }
182  accept();
183 }