2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation plus additions
11 that are listed in the file LICENSE.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
34 * Kern Sibbald, January MMVI
38 #include <QAbstractEventDispatcher>
42 Console::Console(QStackedWidget *parent)
45 QTreeWidgetItem *item, *topItem;
46 QTreeWidget *treeWidget = mainWin->treeWidget;
49 parent->addWidget(this);
52 m_textEdit = textEdit; /* our console screen */
53 m_cursor = new QTextCursor(m_textEdit->document());
54 mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
56 bRestore *brestore = new bRestore(parent);
57 brestore->setupUi(brestore);
58 parent->addWidget(brestore);
60 /* Just take the first Director */
62 m_dir = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
65 /* ***FIXME*** Dummy setup of treeWidget */
67 treeWidget->setColumnCount(1);
68 treeWidget->setHeaderLabel("Selection");
69 topItem = new QTreeWidgetItem(treeWidget);
70 topItem->setText(0, m_dir->name());
71 topItem->setIcon(0, QIcon(QString::fromUtf8("images/server.png")));
72 item = new QTreeWidgetItem(topItem);
74 item->setText(0, "Console");
75 item->setText(1, "0");
76 QBrush redBrush(Qt::red);
77 item->setForeground(0, redBrush);
78 item = new QTreeWidgetItem(topItem);
79 item->setText(0, "brestore");
80 item->setText(1, "1");
81 treeWidget->expandItem(topItem);
87 /* Terminate any open socket */
88 void Console::terminate()
97 * Connect to Director. If there are more than one, put up
98 * a modal dialog so that the user chooses one.
100 void Console::connect()
104 m_textEdit = textEdit; /* our console screen */
107 mainWin->set_status(" No Director found.");
111 mainWin->set_status(" Already connected.");
115 memset(&jcr, 0, sizeof(jcr));
117 mainWin->set_statusf(_(" Connecting to Director %s:%d"), m_dir->address, m_dir->DIRport);
118 display_textf(_("Connecting to Director %s:%d\n\n"), m_dir->address, m_dir->DIRport);
120 /* Give GUI a chance */
121 app->processEvents();
124 /* If cons==NULL, default console will be used */
125 CONRES *cons = (CONRES *)GetNextRes(R_CONSOLE, (RES *)NULL);
128 m_sock = bnet_connect(NULL, 5, 15, _("Director daemon"), m_dir->address,
129 NULL, m_dir->DIRport, 0);
130 if (m_sock == NULL) {
131 mainWin->set_status("Connection failed");
134 /* Update page selector to green to indicate that Console is connected */
135 mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/connected.png")));
136 QBrush greenBrush(Qt::green);
137 m_consoleItem->setForeground(0, greenBrush);
140 jcr.dir_bsock = m_sock;
142 if (!authenticate_director(&jcr, m_dir, cons)) {
143 display_text(m_sock->msg);
147 /* Give GUI a chance */
148 app->processEvents();
150 mainWin->set_status(_(" Initializing ..."));
152 /* Set up input notifier */
153 m_notifier = new QSocketNotifier(m_sock->fd, QSocketNotifier::Read, 0);
154 QObject::connect(m_notifier, SIGNAL(activated(int)), this, SLOT(read_dir(int)));
156 job_list = get_list(".jobs");
157 client_list = get_list(".clients");
158 fileset_list = get_list(".filesets");
159 messages_list = get_list(".messages");
160 pool_list = get_list(".pools");
161 storage_list = get_list(".storage");
162 type_list = get_list(".types");
163 level_list = get_list(".levels");
165 mainWin->set_status(_(" Connected"));
171 * Send a command to the director, and read all the resulting
172 * output into a list.
174 QStringList Console::get_list(char *cmd)
181 while ((stat = read()) > 0) {
182 strip_trailing_junk(msg());
191 * Send a job name to the director, and read all the resulting
194 bool Console::get_job_defaults(struct job_defaults &job_defs)
201 bsnprintf(cmd, sizeof(cmd), ".defaults job=\"%s\"", job_defs.job_name.toUtf8().data());
203 while ((stat = read()) > 0) {
204 def = strchr(msg(), '=');
208 /* Pointer to default value */
210 strip_trailing_junk(def);
212 if (strcmp(msg(), "job") == 0) {
213 if (strcmp(def, job_defs.job_name.toUtf8().data()) != 0) {
218 if (strcmp(msg(), "pool") == 0) {
219 job_defs.pool_name = def;
222 if (strcmp(msg(), "messages") == 0) {
223 job_defs.messages_name = def;
226 if (strcmp(msg(), "client") == 0) {
227 job_defs.client_name = def;
230 if (strcmp(msg(), "storage") == 0) {
231 job_defs.store_name = def;
234 if (strcmp(msg(), "where") == 0) {
235 job_defs.where = def;
238 if (strcmp(msg(), "level") == 0) {
239 job_defs.level = def;
242 if (strcmp(msg(), "type") == 0) {
246 if (strcmp(msg(), "fileset") == 0) {
247 job_defs.fileset_name = def;
250 if (strcmp(msg(), "catalog") == 0) {
251 job_defs.catalog_name = def;
254 if (strcmp(msg(), "enabled") == 0) {
255 job_defs.enabled = *def == '1' ? true : false;
259 bsnprintf(cmd, sizeof(cmd), "job=%s pool=%s client=%s storage=%s where=%s\n"
260 "level=%s type=%s fileset=%s catalog=%s enabled=%d\n",
261 job_defs.job_name.toUtf8().data(), job_defs.pool_name.toUtf8().data(),
262 job_defs.client_name.toUtf8().data(),
263 job_defs.pool_name.toUtf8().data(), job_defs.messages_name.toUtf8().data(),
264 job_defs.store_name.toUtf8().data(),
265 job_defs.where.toUtf8().data(), job_defs.level.toUtf8().data(),
266 job_defs.type.toUtf8().data(), job_defs.fileset_name.toUtf8().data(),
267 job_defs.catalog_name.toUtf8().data(), job_defs.enabled);
279 * Save user settings associated with this console
281 void Console::writeSettings()
283 QFont font = get_font();
285 QSettings settings("bacula.org", "bat");
286 /* ***FIXME*** make console name unique */
287 settings.beginGroup("Console");
288 settings.setValue("consoleFont", font.family());
289 settings.setValue("consolePointSize", font.pointSize());
290 settings.setValue("consoleFixedPitch", font.fixedPitch());
295 * Read and restore user settings associated with this console
297 void Console::readSettings()
299 QFont font = get_font();
301 QSettings settings("bacula.org", "bat");
302 settings.beginGroup("Console");
303 font.setFamily(settings.value("consoleFont", "Courier").value<QString>());
304 font.setPointSize(settings.value("consolePointSize", 10).toInt());
305 font.setFixedPitch(settings.value("consoleFixedPitch", true).toBool());
307 m_textEdit->setFont(font);
311 * Set the console textEdit font
313 void Console::set_font()
316 QFont font = QFontDialog::getFont(&ok, QFont(m_textEdit->font()), this);
318 m_textEdit->setFont(font);
323 * Get the console text edit font
325 const QFont Console::get_font()
327 return m_textEdit->font();
331 void Console::status_dir()
333 write_dir("status dir\n");
337 * Put text into the console window
339 void Console::display_textf(const char *fmt, ...)
344 va_start(arg_ptr, fmt);
345 len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
350 void Console::display_text(const QString buf)
352 m_cursor->movePosition(QTextCursor::End);
353 m_cursor->insertText(buf);
357 void Console::display_text(const char *buf)
359 m_cursor->movePosition(QTextCursor::End);
360 m_cursor->insertText(buf);
363 /* Position cursor to end of screen */
364 void Console::update_cursor()
366 QApplication::restoreOverrideCursor();
367 m_textEdit->moveCursor(QTextCursor::End);
368 m_textEdit->ensureCursorVisible();
372 * This should be moved into a bSocket class
382 /* Send a command to the Director */
383 void Console::write_dir(const char *msg)
387 mainWin->set_status(_(" Processing command ..."));
388 QApplication::setOverrideCursor(Qt::WaitCursor);
389 m_sock->msglen = strlen(msg);
390 pm_strcpy(&m_sock->msg, msg);
393 mainWin->set_status(" Director not connected. Click on connect button.");
394 mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
395 QBrush redBrush(Qt::red);
396 m_consoleItem->setForeground(0, redBrush);
400 int Console::write(const char *msg)
402 m_sock->msglen = strlen(msg);
403 pm_strcpy(&m_sock->msg, msg);
404 return bnet_send(m_sock);
408 * Blocking read from director */
414 stat = bnet_wait_data_intr(m_sock, 1);
418 app->processEvents();
423 return bnet_recv(m_sock);
428 /* Called by signal when the Director has output for us */
429 void Console::read_dir(int fd)
437 stat = bnet_recv(m_sock);
443 display_text(m_sock->msg);
446 if (is_bnet_stop(m_sock)) { /* error or term request */
449 mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
450 QBrush redBrush(Qt::red);
451 m_consoleItem->setForeground(0, redBrush);
452 m_notifier->setEnabled(false);
455 mainWin->set_status(_(" Director disconnected."));
456 QApplication::restoreOverrideCursor();
459 /* Must be a signal -- either do something or ignore it */
460 if (m_sock->msglen == BNET_PROMPT) {
462 mainWin->set_status(_(" At prompt waiting for input ..."));
465 if (m_sock->msglen == BNET_EOD) {
466 mainWin->set_status_ready();