2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-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.
33 * Kern Sibbald, January MMVII
37 #include <QAbstractEventDispatcher>
41 Console::Console(QStackedWidget *parent)
44 QTreeWidgetItem *item, *topItem;
45 QTreeWidget *treeWidget = mainWin->treeWidget;
48 parent->addWidget(this);
51 m_textEdit = textEdit; /* our console screen */
52 m_cursor = new QTextCursor(m_textEdit->document());
53 mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
55 bRestore *brestore = new bRestore(parent);
56 brestore->setupUi(brestore);
57 parent->addWidget(brestore);
59 /* Just take the first Director */
61 m_dir = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
64 /* ***FIXME*** Dummy setup of treeWidget */
66 treeWidget->setColumnCount(1);
67 treeWidget->setHeaderLabel("Selection");
68 topItem = new QTreeWidgetItem(treeWidget);
69 topItem->setText(0, m_dir->name());
70 topItem->setIcon(0, QIcon(QString::fromUtf8("images/server.png")));
71 item = new QTreeWidgetItem(topItem);
73 item->setText(0, "Console");
74 item->setText(1, "0");
75 QBrush redBrush(Qt::red);
76 item->setForeground(0, redBrush);
77 item = new QTreeWidgetItem(topItem);
78 item->setText(0, "brestore");
79 item->setText(1, "1");
80 treeWidget->expandItem(topItem);
83 /* Check for messages every 5 seconds */
84 // m_timer = new QTimer(this);
85 // QWidget::connect(m_timer, SIGNAL(timeout()), this, SLOT(poll_messages()));
86 // m_timer->start(5000);
90 void Console::poll_messages()
92 m_messages_pending = true;
95 /* Terminate any open socket */
96 void Console::terminate()
106 * Connect to Director. If there are more than one, put up
107 * a modal dialog so that the user chooses one.
109 void Console::connect()
113 m_textEdit = textEdit; /* our console screen */
116 mainWin->set_status("No Director found.");
120 mainWin->set_status("Already connected.");
124 memset(&jcr, 0, sizeof(jcr));
126 mainWin->set_statusf(_("Connecting to Director %s:%d"), m_dir->address, m_dir->DIRport);
127 display_textf(_("Connecting to Director %s:%d\n\n"), m_dir->address, m_dir->DIRport);
129 /* Give GUI a chance */
130 app->processEvents();
133 /* If cons==NULL, default console will be used */
134 CONRES *cons = (CONRES *)GetNextRes(R_CONSOLE, (RES *)NULL);
137 m_sock = bnet_connect(NULL, 5, 15, _("Director daemon"), m_dir->address,
138 NULL, m_dir->DIRport, 0);
139 if (m_sock == NULL) {
140 mainWin->set_status("Connection failed");
143 /* Update page selector to green to indicate that Console is connected */
144 mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/connected.png")));
145 QBrush greenBrush(Qt::green);
146 m_consoleItem->setForeground(0, greenBrush);
149 jcr.dir_bsock = m_sock;
151 if (!authenticate_director(&jcr, m_dir, cons)) {
152 display_text(m_sock->msg);
156 /* Give GUI a chance */
157 app->processEvents();
159 mainWin->set_status(_("Initializing ..."));
161 /* Set up input notifier */
162 m_notifier = new QSocketNotifier(m_sock->fd, QSocketNotifier::Read, 0);
163 QObject::connect(m_notifier, SIGNAL(activated(int)), this, SLOT(read_dir(int)));
169 job_list = get_list(".jobs");
170 client_list = get_list(".clients");
171 fileset_list = get_list(".filesets");
172 messages_list = get_list(".messages");
173 pool_list = get_list(".pools");
174 storage_list = get_list(".storage");
175 type_list = get_list(".types");
176 level_list = get_list(".levels");
178 mainWin->set_status(_("Connected"));
184 * Send a command to the director, and read all the resulting
185 * output into a list.
187 QStringList Console::get_list(char *cmd)
194 while ((stat = read()) > 0) {
195 strip_trailing_junk(msg());
204 * Send a job name to the director, and read all the resulting
207 bool Console::get_job_defaults(struct job_defaults &job_defs)
216 scmd = QString(".defaults job=\"%1\"").arg(job_defs.job_name);
218 while ((stat = read()) > 0) {
219 def = strchr(msg(), '=');
223 /* Pointer to default value */
225 strip_trailing_junk(def);
227 if (strcmp(msg(), "job") == 0) {
228 if (strcmp(def, job_defs.job_name.toUtf8().data()) != 0) {
233 if (strcmp(msg(), "pool") == 0) {
234 job_defs.pool_name = def;
237 if (strcmp(msg(), "messages") == 0) {
238 job_defs.messages_name = def;
241 if (strcmp(msg(), "client") == 0) {
242 job_defs.client_name = def;
245 if (strcmp(msg(), "storage") == 0) {
246 job_defs.store_name = def;
249 if (strcmp(msg(), "where") == 0) {
250 job_defs.where = def;
253 if (strcmp(msg(), "level") == 0) {
254 job_defs.level = def;
257 if (strcmp(msg(), "type") == 0) {
261 if (strcmp(msg(), "fileset") == 0) {
262 job_defs.fileset_name = def;
265 if (strcmp(msg(), "catalog") == 0) {
266 job_defs.catalog_name = def;
269 if (strcmp(msg(), "enabled") == 0) {
270 job_defs.enabled = *def == '1' ? true : false;
274 bsnprintf(cmd, sizeof(cmd), "job=%s pool=%s client=%s storage=%s where=%s\n"
275 "level=%s type=%s fileset=%s catalog=%s enabled=%d\n",
276 job_defs.job_name.toUtf8().data(), job_defs.pool_name.toUtf8().data(),
277 job_defs.client_name.toUtf8().data(),
278 job_defs.pool_name.toUtf8().data(), job_defs.messages_name.toUtf8().data(),
279 job_defs.store_name.toUtf8().data(),
280 job_defs.where.toUtf8().data(), job_defs.level.toUtf8().data(),
281 job_defs.type.toUtf8().data(), job_defs.fileset_name.toUtf8().data(),
282 job_defs.catalog_name.toUtf8().data(), job_defs.enabled);
294 * Save user settings associated with this console
296 void Console::writeSettings()
298 QFont font = get_font();
300 QSettings settings("bacula.org", "bat");
301 /* ***FIXME*** make console name unique */
302 settings.beginGroup("Console");
303 settings.setValue("consoleFont", font.family());
304 settings.setValue("consolePointSize", font.pointSize());
305 settings.setValue("consoleFixedPitch", font.fixedPitch());
310 * Read and restore user settings associated with this console
312 void Console::readSettings()
314 QFont font = get_font();
316 QSettings settings("bacula.org", "bat");
317 settings.beginGroup("Console");
318 font.setFamily(settings.value("consoleFont", "Courier").value<QString>());
319 font.setPointSize(settings.value("consolePointSize", 10).toInt());
320 font.setFixedPitch(settings.value("consoleFixedPitch", true).toBool());
322 m_textEdit->setFont(font);
326 * Set the console textEdit font
328 void Console::set_font()
331 QFont font = QFontDialog::getFont(&ok, QFont(m_textEdit->font()), this);
333 m_textEdit->setFont(font);
338 * Get the console text edit font
340 const QFont Console::get_font()
342 return m_textEdit->font();
346 void Console::status_dir()
348 write_dir("status dir\n");
353 * Put text into the console window
355 void Console::display_textf(const char *fmt, ...)
360 va_start(arg_ptr, fmt);
361 len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
366 void Console::display_text(const QString buf)
368 m_cursor->movePosition(QTextCursor::End);
369 m_cursor->insertText(buf);
373 void Console::display_text(const char *buf)
375 m_cursor->movePosition(QTextCursor::End);
376 m_cursor->insertText(buf);
379 /* Position cursor to end of screen */
380 void Console::update_cursor()
382 QApplication::restoreOverrideCursor();
383 m_textEdit->moveCursor(QTextCursor::End);
384 m_textEdit->ensureCursorVisible();
388 * This should be moved into a bSocket class
398 /* Send a command to the Director */
399 void Console::write_dir(const char *msg)
402 mainWin->set_status(_("Processing command ..."));
403 QApplication::setOverrideCursor(Qt::WaitCursor);
406 mainWin->set_status(" Director not connected. Click on connect button.");
407 mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
408 QBrush redBrush(Qt::red);
409 m_consoleItem->setForeground(0, redBrush);
413 int Console::write(const QString msg)
415 return write(msg.toUtf8().data());
418 int Console::write(const char *msg)
420 m_sock->msglen = strlen(msg);
421 pm_strcpy(&m_sock->msg, msg);
423 if (commDebug) Pmsg1(000, "send: %s\n", msg);
424 return m_sock->send();
428 * Get to main command prompt
430 void Console::beginNewCommand()
444 void Console::displayToPrompt()
447 if (commDebug) Pmsg0(000, "DisplaytoPrompt\n");
448 m_notifier->setEnabled(false);
449 while ((stat = read()) > 0) {
452 if (commDebug) Pmsg1(000, "endDisplaytoPrompt=%d\n", stat);
453 m_notifier->setEnabled(true);
456 void Console::discardToPrompt()
459 if (commDebug) Pmsg0(000, "discardToPrompt\n");
460 m_notifier->setEnabled(false);
461 while ((stat = read()) > 0) {
463 if (commDebug) Pmsg1(000, "endDisplayToPrompt=%d\n", stat);
464 m_notifier->setEnabled(true);
469 * Blocking read from director
473 int stat = BNET_HARDEOF;
476 stat = bnet_wait_data_intr(m_sock, 1);
480 app->processEvents();
481 // if (m_api_set && m_messages_pending) {
482 // write_dir(".messages");
483 // m_messages_pending = false;
486 stat = m_sock->recv();
492 if (commDebug) Pmsg1(000, "got: %s", m_sock->msg);
495 switch (m_sock->msglen) {
496 case BNET_SERVER_READY:
497 // if (m_api_set && m_messages_pending) {
498 // write_dir(".messages");
499 // m_messages_pending = false;
503 case BNET_MESSAGES_PENDING:
504 m_messages_pending = true;
511 if (commDebug) Pmsg0(000, "CMD OK/PROMPT\n");
513 mainWin->set_status(_("At prompt waiting for input ..."));
515 QApplication::restoreOverrideCursor();
517 case BNET_CMD_FAILED:
518 if (commDebug) Pmsg0(000, "CMD FAIL\n");
520 mainWin->set_status(_("Command failed. At prompt waiting for input ..."));
522 QApplication::restoreOverrideCursor();
525 if (commDebug) Pmsg0(000, "EOD\n");
526 mainWin->set_status_ready();
528 QApplication::restoreOverrideCursor();
534 if (is_bnet_stop(m_sock)) { /* error or term request */
537 mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
538 QBrush redBrush(Qt::red);
539 m_consoleItem->setForeground(0, redBrush);
540 m_notifier->setEnabled(false);
543 mainWin->set_status(_("Director disconnected."));
544 QApplication::restoreOverrideCursor();
551 /* Called by signal when the Director has output for us */
552 void Console::read_dir(int fd)
557 if (commDebug) Pmsg0(000, "read_dir\n");
558 while ((stat = read()) >= 0) {