]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/console/console.cpp
Get job defaults
[bacula/bacula] / bacula / src / qt-console / console / console.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
5
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.
12
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.
17
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
21    02110-1301, USA.
22
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.
27 */
28  
29 /*
30  *   Version $Id$
31  *
32  *  Console Class
33  *
34  *   Kern Sibbald, January MMVI
35  *
36  */ 
37
38 #include <QAbstractEventDispatcher>
39 #include "bat.h"
40 #include "console.h"
41
42 Console::Console(QStackedWidget *parent)
43 {
44    QFont font;
45    QTreeWidgetItem *item, *topItem;
46    QTreeWidget *treeWidget = mainWin->treeWidget;
47
48    setupUi(this);
49    parent->addWidget(this);
50    m_sock = NULL;
51    m_at_prompt = false;
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")));
55
56    bRestore *brestore = new bRestore(parent);
57    brestore->setupUi(brestore);
58    parent->addWidget(brestore);
59
60    /* Just take the first Director */
61    LockRes();
62    m_dir = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
63    UnlockRes();
64
65    /* ***FIXME*** Dummy setup of treeWidget */
66    treeWidget->clear();
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);
73    m_consoleItem = item;
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);
82
83    readSettings();
84
85 }
86
87 /*
88  * Connect to Director. If there are more than one, put up
89  * a modal dialog so that the user chooses one.
90  */
91 void Console::connect()
92 {
93    JCR jcr;
94
95    m_textEdit = textEdit;   /* our console screen */
96
97    if (!m_dir) {          
98       mainWin->set_status(" No Director found.");
99       return;
100    }
101    if (m_sock) {
102       mainWin->set_status(" Already connected.");
103       return;
104    }
105
106    memset(&jcr, 0, sizeof(jcr));
107
108    mainWin->set_statusf(_(" Connecting to Director %s:%d"), m_dir->address, m_dir->DIRport);
109    set_textf(_("Connecting to Director %s:%d\n\n"), m_dir->address, m_dir->DIRport);
110
111    /* Give GUI a chance */
112    app->processEvents();
113    
114    LockRes();
115    /* If cons==NULL, default console will be used */
116    CONRES *cons = (CONRES *)GetNextRes(R_CONSOLE, (RES *)NULL);
117    UnlockRes();
118
119    m_sock = bnet_connect(NULL, 5, 15, _("Director daemon"), m_dir->address,
120                           NULL, m_dir->DIRport, 0);
121    if (m_sock == NULL) {
122       mainWin->set_status("Connection failed");
123       return;
124    } else {
125       /* Update page selector to green to indicate that Console is connected */
126       mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/connected.png")));
127       QBrush greenBrush(Qt::green);
128       m_consoleItem->setForeground(0, greenBrush);
129    }
130
131    jcr.dir_bsock = m_sock;
132
133    if (!authenticate_director(&jcr, m_dir, cons)) {
134       set_text(m_sock->msg);
135       return;
136    }
137
138    /* Give GUI a chance */
139    app->processEvents();
140
141    mainWin->set_status(_(" Initializing ..."));
142
143    /* Set up input notifier */
144    m_notifier = new QSocketNotifier(m_sock->fd, QSocketNotifier::Read, 0);
145    QObject::connect(m_notifier, SIGNAL(activated(int)), this, SLOT(read_dir(int)));
146
147    job_list = get_list(".jobs");
148    client_list = get_list(".clients");
149    fileset_list = get_list(".filesets");
150    messages_list = get_list(".messages");
151    pool_list = get_list(".pools");
152    storage_list = get_list(".storage");
153    type_list = get_list(".types");
154    level_list = get_list(".levels");
155
156    mainWin->set_status(_(" Connected"));
157    return;
158 }
159
160
161 /*  
162  * Send a command to the director, and read all the resulting
163  *  output into a list.
164  */
165 QStringList Console::get_list(char *cmd)
166 {
167    QStringList list;
168    int stat;
169
170    setEnabled(false);
171    write(cmd);
172    while ((stat = read()) > 0) {
173       strip_trailing_junk(msg());
174       list << msg();
175    }
176    setEnabled(true);
177    list.sort();
178    return list;
179 }
180
181 /*  
182  * Send a job name to the director, and read all the resulting
183  *  defaults. 
184  */
185 bool Console::get_job_defaults(struct job_defaults &job_defs)
186 {
187    char cmd[1000];
188    int stat;
189    char *def;
190
191    setEnabled(false);
192    bsnprintf(cmd, sizeof(cmd), ".defaults job=\"%s\"", job_defs.job_name);
193    write(cmd);
194    while ((stat = read()) > 0) {
195       def = strchr(msg(), '=');
196       if (!def) {
197          continue;
198       }
199       /* Pointer to default value */
200       *def++ = 0;
201       strip_trailing_junk(def);
202
203       if (strcmp(msg(), "job") == 0) {
204          if (strcmp(def, job_defs.job_name) != 0) {
205             goto bail_out;
206          }
207          continue;
208       }
209       if (strcmp(msg(), "pool") == 0) {
210          bstrncpy(job_defs.pool_name, def, sizeof(job_defs.pool_name));
211          continue;
212       }
213       if (strcmp(msg(), "messages") == 0) {
214          bstrncpy(job_defs.messages_name, def, sizeof(job_defs.messages_name));
215          continue;
216       }
217       if (strcmp(msg(), "client") == 0) {
218          bstrncpy(job_defs.client_name, def, sizeof(job_defs.client_name));
219          continue;
220       }
221       if (strcmp(msg(), "storage") == 0) {
222          bstrncpy(job_defs.store_name, def, sizeof(job_defs.store_name));
223          continue;
224       }
225       if (strcmp(msg(), "where") == 0) {
226          bstrncpy(job_defs.where, def, sizeof(job_defs.where));
227          continue;
228       }
229       if (strcmp(msg(), "level") == 0) {
230          bstrncpy(job_defs.level, def, sizeof(job_defs.level));
231          continue;
232       }
233       if (strcmp(msg(), "type") == 0) {
234          bstrncpy(job_defs.type, def, sizeof(job_defs.type));
235          continue;
236       }
237       if (strcmp(msg(), "fileset") == 0) {
238          bstrncpy(job_defs.fileset_name, def, sizeof(job_defs.fileset_name));
239          continue;
240       }
241       if (strcmp(msg(), "catalog") == 0) {
242          bstrncpy(job_defs.catalog_name, def, sizeof(job_defs.catalog_name));
243          continue;
244       }
245       if (strcmp(msg(), "enabled") == 0) {
246          job_defs.enabled = *def == '1' ? true : false;
247          continue;
248       }
249    }
250    bsnprintf(cmd, sizeof(cmd), "job=%s pool=%s client=%s storage=%s where=%s\n"
251       "level=%s type=%s fileset=%s catalog=%s enabled=%d\n",
252       job_defs.job_name, job_defs.pool_name, job_defs.client_name, 
253       job_defs.pool_name, job_defs.messages_name, job_defs.store_name,
254       job_defs.where, job_defs.level, job_defs.type, job_defs.fileset_name,
255       job_defs.catalog_name, job_defs.enabled);
256
257    setEnabled(true);
258    return true;
259
260 bail_out:
261    setEnabled(true);
262    return false;
263 }
264
265
266 /*
267  * Save user settings
268  */
269 void Console::writeSettings()
270 {
271    QFont font = get_font();
272
273    QSettings settings("bacula.org", "bat");
274    settings.beginGroup("Console");
275    settings.setValue("consoleFont", font.family());
276    settings.setValue("consolePointSize", font.pointSize());
277    settings.setValue("consoleFixedPitch", font.fixedPitch());
278    settings.endGroup();
279 }
280
281 /*
282  * Read and restore user settings
283  */
284 void Console::readSettings()
285
286    QFont font = get_font();
287
288    QSettings settings("bacula.org", "bat");
289    settings.beginGroup("Console");
290    font.setFamily(settings.value("consoleFont", "Courier").value<QString>());
291    font.setPointSize(settings.value("consolePointSize", 10).toInt());
292    font.setFixedPitch(settings.value("consoleFixedPitch", true).toBool());
293    settings.endGroup();
294    m_textEdit->setFont(font);
295 }
296
297 /*
298  * Set the console textEdit font
299  */
300 void Console::set_font()
301 {
302    bool ok;
303    QFont font = QFontDialog::getFont(&ok, QFont(m_textEdit->font()), this);
304    if (ok) {
305       m_textEdit->setFont(font);
306    }
307 }
308
309 /*
310  * Get the console text edit font
311  */
312 const QFont Console::get_font()
313 {
314    return m_textEdit->font();
315 }
316
317
318 void Console::status_dir()
319 {
320    write_dir("status dir\n");
321 }
322
323 /*
324  * Put text into the console window
325  */
326 void Console::set_textf(const char *fmt, ...)
327 {
328    va_list arg_ptr;
329    char buf[1000];
330    int len;
331    va_start(arg_ptr, fmt);
332    len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
333    va_end(arg_ptr);
334    set_text(buf);
335 }
336
337 void Console::set_text(const QString buf)
338 {
339    m_cursor->movePosition(QTextCursor::End);
340    m_cursor->insertText(buf);
341 }
342
343
344 void Console::set_text(const char *buf)
345 {
346    m_cursor->movePosition(QTextCursor::End);
347    m_cursor->insertText(buf);
348 }
349
350 /* Position cursor to end of screen */
351 void Console::update_cursor()
352 {
353    QApplication::restoreOverrideCursor();
354    m_textEdit->moveCursor(QTextCursor::End);
355    m_textEdit->ensureCursorVisible();
356 }
357
358 /* 
359  * This should be moved into a bSocket class 
360  */
361 char *Console::msg()
362 {
363    if (m_sock) {
364       return m_sock->msg;
365    }
366    return NULL;
367 }
368
369 /* Send a command to the Director */
370 void Console::write_dir(const char *msg)
371 {
372    if (m_sock) {
373       m_at_prompt = false;
374       mainWin->set_status(_(" Processing command ..."));
375       QApplication::setOverrideCursor(Qt::WaitCursor);
376       m_sock->msglen = strlen(msg);
377       pm_strcpy(&m_sock->msg, msg);
378       bnet_send(m_sock);
379    } else {
380       mainWin->set_status(" Director not connected. Click on connect button.");
381       mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
382       QBrush redBrush(Qt::red);
383       m_consoleItem->setForeground(0, redBrush);
384    }
385 }
386
387 int Console::write(const char *msg)
388 {
389    m_sock->msglen = strlen(msg);
390    pm_strcpy(&m_sock->msg, msg);
391    return bnet_send(m_sock);
392 }
393
394 /* 
395  * Blocking read from director */
396 int Console::read()
397 {
398    int stat;
399    if (m_sock) {
400       for (;;) {
401          stat = bnet_wait_data_intr(m_sock, 1);
402          if (stat > 0) {
403             break;
404          } 
405          app->processEvents();
406          if (stat < 0) {
407             return BNET_ERROR;
408          }
409       }
410       return bnet_recv(m_sock);
411    } 
412    return BNET_HARDEOF;
413 }
414
415 /* Called by signal when the Director has output for us */
416 void Console::read_dir(int fd)
417 {
418    int stat;
419    (void)fd;
420
421    if (!m_sock) {
422       return;
423    }
424    stat = bnet_recv(m_sock);
425    if (stat >= 0) {
426       if (m_at_prompt) {
427          set_text("\n");
428          m_at_prompt = false;
429       }
430       set_text(m_sock->msg);
431       return;
432    }
433    if (is_bnet_stop(m_sock)) {         /* error or term request */
434       bnet_close(m_sock);
435       m_sock = NULL;
436       mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
437       QBrush redBrush(Qt::red);
438       m_consoleItem->setForeground(0, redBrush);
439       m_notifier->setEnabled(false);
440       delete m_notifier;
441       m_notifier = NULL;
442       mainWin->set_status(_(" Director disconnected."));
443       QApplication::restoreOverrideCursor();
444       return;
445    }
446    /* Must be a signal -- either do something or ignore it */
447    if (m_sock->msglen == BNET_PROMPT) {
448       m_at_prompt = true;
449       mainWin->set_status(_(" At prompt waiting for input ..."));
450       update_cursor();
451    }
452    if (m_sock->msglen == BNET_EOD) {
453       mainWin->set_status_ready();
454       update_cursor();
455    }
456    return;
457 }