]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/console/console.cpp
Implement command output lists
[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  *  Console Class
31  *
32  *   Kern Sibbald, January MMVI
33  *
34  */ 
35
36 #include <QAbstractEventDispatcher>
37 #include "bat.h"
38 #include "console.h"
39 #include "restore.h"
40
41 Console::Console(QStackedWidget *parent)
42 {
43    QFont font;
44    QTreeWidgetItem *item, *topItem;
45    QTreeWidget *treeWidget = mainWin->treeWidget;
46
47    setupUi(this);
48    parent->addWidget(this);
49    m_sock = NULL;
50    m_at_prompt = false;
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")));
54
55    bRestore *restore = new bRestore(parent);
56    restore->setupUi(restore);
57    parent->addWidget(restore);
58
59    /* Just take the first Director */
60    LockRes();
61    m_dir = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
62    UnlockRes();
63
64    /* Dummy setup of treeWidget */
65    treeWidget->clear();
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);
72    m_consoleItem = item;
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, "Restore");
79    item->setText(1, "1");
80    treeWidget->expandItem(topItem);
81
82    readSettings();
83
84 }
85
86 /*
87  * Connect to Director. If there are more than one, put up
88  * a modal dialog so that the user chooses one.
89  */
90 void Console::connect()
91 {
92    JCR jcr;
93
94    m_textEdit = textEdit;   /* our console screen */
95
96    if (!m_dir) {          
97       mainWin->set_status(" No Director found.");
98       return;
99    }
100    if (m_sock) {
101       mainWin->set_status(" Already connected.");
102       return;
103    }
104
105    memset(&jcr, 0, sizeof(jcr));
106
107    mainWin->set_statusf(_(" Connecting to Director %s:%d"), m_dir->address, m_dir->DIRport);
108    set_textf(_("Connecting to Director %s:%d\n\n"), m_dir->address, m_dir->DIRport);
109
110    /* Give GUI a chance */
111    app->processEvents();
112    
113    LockRes();
114    /* If cons==NULL, default console will be used */
115    CONRES *cons = (CONRES *)GetNextRes(R_CONSOLE, (RES *)NULL);
116    UnlockRes();
117
118    m_sock = bnet_connect(NULL, 5, 15, _("Director daemon"), m_dir->address,
119                           NULL, m_dir->DIRport, 0);
120    if (m_sock == NULL) {
121       mainWin->set_status("Connection failed");
122       return;
123    } else {
124       /* Update page selector to green to indicate that Console is connected */
125       mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/connected.png")));
126       QBrush greenBrush(Qt::green);
127       m_consoleItem->setForeground(0, greenBrush);
128    }
129
130    jcr.dir_bsock = m_sock;
131
132    if (!authenticate_director(&jcr, m_dir, cons)) {
133       set_text(m_sock->msg);
134       return;
135    }
136
137    /* Give GUI a chance */
138    app->processEvents();
139
140    mainWin->set_status(_(" Initializing ..."));
141
142    /* Set up input notifier */
143    m_notifier = new QSocketNotifier(m_sock->fd, QSocketNotifier::Read, 0);
144    QObject::connect(m_notifier, SIGNAL(activated(int)), this, SLOT(read_dir(int)));
145
146    job_list = get_list(".jobs");
147    client_list = get_list(".clients");
148    fileset_list = get_list(".filesets");
149    messages_list = get_list(".messages");
150    messages_list = get_list(".pools");
151    messages_list = get_list(".storages");
152    messages_list = get_list(".types");
153    messages_list = get_list(".levels");
154
155    mainWin->set_status(_(" Connected"));
156    return;
157 }
158
159
160 /*  
161  * Send a command to the director, and read all the resulting
162  *  output into a list.
163  */
164 QStringList Console::get_list(char *cmd)
165 {
166    QStringList list;
167    int stat;
168
169    setEnabled(false);
170    write(cmd);
171    while ((stat = read()) > 0) {
172       strip_trailing_junk(msg());
173       list << msg();
174    }
175    setEnabled(true);
176    return list;
177 }
178
179
180 void Console::writeSettings()
181 {
182    QFont font = get_font();
183
184    QSettings settings("bacula.org", "bat");
185    settings.beginGroup("Console");
186    settings.setValue("consoleFont", font.family());
187    settings.setValue("consolePointSize", font.pointSize());
188    settings.setValue("consoleFixedPitch", font.fixedPitch());
189    settings.endGroup();
190 }
191
192 void Console::readSettings()
193
194    QFont font = get_font();
195
196    QSettings settings("bacula.org", "bat");
197    settings.beginGroup("Console");
198    font.setFamily(settings.value("consoleFont", "Courier").value<QString>());
199    font.setPointSize(settings.value("consolePointSize", 10).toInt());
200    font.setFixedPitch(settings.value("consoleFixedPitch", true).toBool());
201    settings.endGroup();
202    m_textEdit->setFont(font);
203 }
204
205 void Console::set_font()
206 {
207    bool ok;
208    QFont font = QFontDialog::getFont(&ok, QFont(m_textEdit->font()), this);
209    if (ok) {
210       m_textEdit->setFont(font);
211    }
212 }
213
214 const QFont Console::get_font()
215 {
216    return m_textEdit->font();
217 }
218
219
220 void Console::status_dir()
221 {
222    write_dir("status dir\n");
223 }
224
225 void Console::set_textf(const char *fmt, ...)
226 {
227    va_list arg_ptr;
228    char buf[1000];
229    int len;
230    va_start(arg_ptr, fmt);
231    len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
232    va_end(arg_ptr);
233    set_text(buf);
234 }
235
236 void Console::set_text(const QString buf)
237 {
238    m_cursor->movePosition(QTextCursor::End);
239    m_cursor->insertText(buf);
240 }
241
242
243 void Console::set_text(const char *buf)
244 {
245    m_cursor->movePosition(QTextCursor::End);
246    m_cursor->insertText(buf);
247 }
248
249 /* Position cursor to end of screen */
250 void Console::update_cursor()
251 {
252    QApplication::restoreOverrideCursor();
253    m_textEdit->moveCursor(QTextCursor::End);
254    m_textEdit->ensureCursorVisible();
255 }
256
257 char *Console::msg()
258 {
259    if (m_sock) {
260       return m_sock->msg;
261    }
262    return NULL;
263 }
264
265 /* Send a command to the Director */
266 void Console::write_dir(const char *msg)
267 {
268    if (m_sock) {
269       m_at_prompt = false;
270       mainWin->set_status(_(" Processing command ..."));
271       QApplication::setOverrideCursor(Qt::WaitCursor);
272       m_sock->msglen = strlen(msg);
273       pm_strcpy(&m_sock->msg, msg);
274       bnet_send(m_sock);
275    } else {
276       mainWin->set_status(" Director not connected. Click on connect button.");
277       mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
278       QBrush redBrush(Qt::red);
279       m_consoleItem->setForeground(0, redBrush);
280    }
281 }
282
283 int Console::write(const char *msg)
284 {
285    m_sock->msglen = strlen(msg);
286    pm_strcpy(&m_sock->msg, msg);
287    return bnet_send(m_sock);
288 }
289
290 /* 
291  * Blocking read from director */
292 int Console::read()
293 {
294    int stat;
295    if (m_sock) {
296       for (;;) {
297          stat = bnet_wait_data_intr(m_sock, 1);
298          if (stat > 0) {
299             break;
300          } 
301          app->processEvents();
302          if (stat < 0) {
303             return BNET_ERROR;
304          }
305       }
306       return bnet_recv(m_sock);
307    } 
308    return BNET_HARDEOF;
309 }
310
311 /* Called by signal when the Director has output for us */
312 void Console::read_dir(int fd)
313 {
314    int stat;
315    (void)fd;
316
317    if (!m_sock) {
318       return;
319    }
320    stat = bnet_recv(m_sock);
321    if (stat >= 0) {
322       if (m_at_prompt) {
323          set_text("\n");
324          m_at_prompt = false;
325       }
326       set_text(m_sock->msg);
327       return;
328    }
329    if (is_bnet_stop(m_sock)) {         /* error or term request */
330       bnet_close(m_sock);
331       m_sock = NULL;
332       mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
333       QBrush redBrush(Qt::red);
334       m_consoleItem->setForeground(0, redBrush);
335       m_notifier->setEnabled(false);
336       delete m_notifier;
337       m_notifier = NULL;
338       mainWin->set_status(_(" Director disconnected."));
339       QApplication::restoreOverrideCursor();
340       return;
341    }
342    /* Must be a signal -- either do something or ignore it */
343    if (m_sock->msglen == BNET_PROMPT) {
344       m_at_prompt = true;
345       mainWin->set_status(_(" At prompt waiting for input ..."));
346       update_cursor();
347    }
348    if (m_sock->msglen == BNET_EOD) {
349       mainWin->set_status_ready();
350       update_cursor();
351    }
352    return;
353 }