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