]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/console/console.cpp
Update
[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    /* 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(char *job_name, struct job_defaults &job_defs)
186 {
187    char cmd[1000];
188    int stat;
189
190    setEnabled(false);
191    bsnprintf(cmd, sizeof(cmd), ".defaults job=\"%s\"", job_name);
192    write(cmd);
193    while ((stat = read()) > 0) {
194       strip_trailing_junk(msg());
195       set_text(msg());
196    }
197    setEnabled(true);
198    return true;
199 }
200
201
202 /*
203  * Save user settings
204  */
205 void Console::writeSettings()
206 {
207    QFont font = get_font();
208
209    QSettings settings("bacula.org", "bat");
210    settings.beginGroup("Console");
211    settings.setValue("consoleFont", font.family());
212    settings.setValue("consolePointSize", font.pointSize());
213    settings.setValue("consoleFixedPitch", font.fixedPitch());
214    settings.endGroup();
215 }
216
217 /*
218  * Read and restore user settings
219  */
220 void Console::readSettings()
221
222    QFont font = get_font();
223
224    QSettings settings("bacula.org", "bat");
225    settings.beginGroup("Console");
226    font.setFamily(settings.value("consoleFont", "Courier").value<QString>());
227    font.setPointSize(settings.value("consolePointSize", 10).toInt());
228    font.setFixedPitch(settings.value("consoleFixedPitch", true).toBool());
229    settings.endGroup();
230    m_textEdit->setFont(font);
231 }
232
233 /*
234  * Set the console textEdit font
235  */
236 void Console::set_font()
237 {
238    bool ok;
239    QFont font = QFontDialog::getFont(&ok, QFont(m_textEdit->font()), this);
240    if (ok) {
241       m_textEdit->setFont(font);
242    }
243 }
244
245 /*
246  * Get the console text edit font
247  */
248 const QFont Console::get_font()
249 {
250    return m_textEdit->font();
251 }
252
253
254 void Console::status_dir()
255 {
256    write_dir("status dir\n");
257 }
258
259 /*
260  * Put text into the console window
261  */
262 void Console::set_textf(const char *fmt, ...)
263 {
264    va_list arg_ptr;
265    char buf[1000];
266    int len;
267    va_start(arg_ptr, fmt);
268    len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
269    va_end(arg_ptr);
270    set_text(buf);
271 }
272
273 void Console::set_text(const QString buf)
274 {
275    m_cursor->movePosition(QTextCursor::End);
276    m_cursor->insertText(buf);
277 }
278
279
280 void Console::set_text(const char *buf)
281 {
282    m_cursor->movePosition(QTextCursor::End);
283    m_cursor->insertText(buf);
284 }
285
286 /* Position cursor to end of screen */
287 void Console::update_cursor()
288 {
289    QApplication::restoreOverrideCursor();
290    m_textEdit->moveCursor(QTextCursor::End);
291    m_textEdit->ensureCursorVisible();
292 }
293
294 /* 
295  * This should be moved into a bSocket class 
296  */
297 char *Console::msg()
298 {
299    if (m_sock) {
300       return m_sock->msg;
301    }
302    return NULL;
303 }
304
305 /* Send a command to the Director */
306 void Console::write_dir(const char *msg)
307 {
308    if (m_sock) {
309       m_at_prompt = false;
310       mainWin->set_status(_(" Processing command ..."));
311       QApplication::setOverrideCursor(Qt::WaitCursor);
312       m_sock->msglen = strlen(msg);
313       pm_strcpy(&m_sock->msg, msg);
314       bnet_send(m_sock);
315    } else {
316       mainWin->set_status(" Director not connected. Click on connect button.");
317       mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
318       QBrush redBrush(Qt::red);
319       m_consoleItem->setForeground(0, redBrush);
320    }
321 }
322
323 int Console::write(const char *msg)
324 {
325    m_sock->msglen = strlen(msg);
326    pm_strcpy(&m_sock->msg, msg);
327    return bnet_send(m_sock);
328 }
329
330 /* 
331  * Blocking read from director */
332 int Console::read()
333 {
334    int stat;
335    if (m_sock) {
336       for (;;) {
337          stat = bnet_wait_data_intr(m_sock, 1);
338          if (stat > 0) {
339             break;
340          } 
341          app->processEvents();
342          if (stat < 0) {
343             return BNET_ERROR;
344          }
345       }
346       return bnet_recv(m_sock);
347    } 
348    return BNET_HARDEOF;
349 }
350
351 /* Called by signal when the Director has output for us */
352 void Console::read_dir(int fd)
353 {
354    int stat;
355    (void)fd;
356
357    if (!m_sock) {
358       return;
359    }
360    stat = bnet_recv(m_sock);
361    if (stat >= 0) {
362       if (m_at_prompt) {
363          set_text("\n");
364          m_at_prompt = false;
365       }
366       set_text(m_sock->msg);
367       return;
368    }
369    if (is_bnet_stop(m_sock)) {         /* error or term request */
370       bnet_close(m_sock);
371       m_sock = NULL;
372       mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
373       QBrush redBrush(Qt::red);
374       m_consoleItem->setForeground(0, redBrush);
375       m_notifier->setEnabled(false);
376       delete m_notifier;
377       m_notifier = NULL;
378       mainWin->set_status(_(" Director disconnected."));
379       QApplication::restoreOverrideCursor();
380       return;
381    }
382    /* Must be a signal -- either do something or ignore it */
383    if (m_sock->msglen == BNET_PROMPT) {
384       m_at_prompt = true;
385       mainWin->set_status(_(" At prompt waiting for input ..."));
386       update_cursor();
387    }
388    if (m_sock->msglen == BNET_EOD) {
389       mainWin->set_status_ready();
390       update_cursor();
391    }
392    return;
393 }