]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/console/console.cpp
bat: Call parent constructor in all pages
[bacula/bacula] / bacula / src / qt-console / console / console.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2010 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 three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    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 Affero 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 Kern Sibbald.
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  *  Console Class
30  *
31  *   Kern Sibbald, January MMVII
32  *
33  */ 
34
35 #include "bat.h"
36 #include "console.h"
37 #include "restore.h"
38 #include "select.h"
39 #include "run/run.h"
40
41 Console::Console(QTabWidget *parent) : Pages()
42 {
43    QFont font;
44    m_name = tr("Console");
45    m_messages_pending = false;
46    m_parent = parent;
47    m_closeable = false;
48    m_console = this;
49    m_warningPrevent = false;
50    m_dircommCounter = 0;
51
52    /* 
53     * Create a connection to the Director and put it in a hash table
54     */
55    m_dircommHash.insert(m_dircommCounter, new DirComm(this, m_dircommCounter));
56
57    setupUi(this);
58    m_textEdit = textEdit;   /* our console screen */
59    m_cursor = new QTextCursor(m_textEdit->document());
60    mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
61
62    m_timer = NULL;
63    m_contextActions.append(actionStatusDir);
64    m_contextActions.append(actionConsoleHelp);
65    m_contextActions.append(actionRequestMessages);
66    m_contextActions.append(actionConsoleReload);
67    connect(actionStatusDir, SIGNAL(triggered()), this, SLOT(status_dir()));
68    connect(actionConsoleHelp, SIGNAL(triggered()), this, SLOT(consoleHelp()));
69    connect(actionConsoleReload, SIGNAL(triggered()), this, SLOT(consoleReload()));
70    connect(actionRequestMessages, SIGNAL(triggered()), this, SLOT(messages()));
71 }
72
73 Console::~Console()
74 {
75 }
76
77 void Console::startTimer()
78 {
79    m_timer = new QTimer(this);
80    QWidget::connect(m_timer, SIGNAL(timeout()), this, SLOT(poll_messages()));
81    m_timer->start(mainWin->m_checkMessagesInterval*1000);
82 }
83
84 void Console::stopTimer()
85 {
86    if (m_timer) {
87       QWidget::disconnect(m_timer, SIGNAL(timeout()), this, SLOT(poll_messages()));
88       m_timer->stop();
89       delete m_timer;
90       m_timer = NULL;
91    }
92 }
93
94 /* slot connected to the timer
95  * requires preferences of check messages and operates at interval */
96 void Console::poll_messages()
97 {
98    int conn;
99
100    /* Do not poll if notifier off */
101    if (!mainWin->m_notify) {
102       return;
103    }
104
105    /*
106     * Note if we call getDirComm here, we continuously consume
107     *  file descriptors.
108     */
109    if (!findDirComm(conn)) {    /* find a free DirComm */
110       return;                   /* try later */
111    }
112
113    DirComm *dircomm = m_dircommHash.value(conn);
114    if (mainWin->m_checkMessages && dircomm->m_at_main_prompt && hasFocus() && !mainWin->getWaitState()){
115       messagesPending(true);
116       dircomm->write(".messages");
117       displayToPrompt(conn);
118       messagesPending(false);
119    }
120 }
121
122 /*
123  * Connect to Director.  This does not connect to the director, dircomm does.
124  * This creates the first and possibly 2nd dircomm instance
125  */
126 void Console::connect_dir()
127 {
128    DirComm *dircomm = m_dircommHash.value(0);
129
130    if (!m_console->m_dir) {
131       mainWin->set_status( tr("No Director found."));
132       return;
133    }
134
135    m_textEdit = textEdit;   /* our console screen */
136
137    if (dircomm->connect_dir()) {
138       if (mainWin->m_connDebug) {
139          Pmsg1(000, "DirComm 0 Seems to have Connected %s\n", m_dir->name());
140       }
141       beginNewCommand(0);
142    }
143    mainWin->set_status(_("Connected"));
144    
145    startTimer();                      /* start message timer */
146 }
147
148 /*
149  * A function created to separate out the population of the lists
150  * from the Console::connect_dir function
151  */
152 void Console::populateLists(bool /*forcenew*/)
153 {
154    int conn;
155    if (!getDirComm(conn)) {
156       if (mainWin->m_connDebug) Pmsg0(000, "call newDirComm\n");
157       if (!newDirComm(conn)) {
158          Emsg1(M_ABORT, 0, "Failed to connect to %s for populateLists.\n", m_dir->name());
159          return;
160       }
161    }
162    populateLists(conn);
163 }
164
165 void Console::populateLists(int conn)
166 {
167    job_list.clear();
168    restore_list.clear();
169    client_list.clear();
170    fileset_list.clear();
171    messages_list.clear();
172    pool_list.clear();
173    storage_list.clear();
174    type_list.clear();
175    level_list.clear();
176    volstatus_list.clear();
177    mediatype_list.clear();
178    dir_cmd(conn, ".jobs", job_list);
179    dir_cmd(conn, ".jobs type=R", restore_list);
180    dir_cmd(conn, ".clients", client_list);
181    dir_cmd(conn, ".filesets", fileset_list);  
182    dir_cmd(conn, ".msgs", messages_list);
183    dir_cmd(conn, ".pools", pool_list);
184    dir_cmd(conn, ".storage", storage_list);
185    dir_cmd(conn, ".types", type_list);
186    dir_cmd(conn, ".levels", level_list);
187    dir_cmd(conn, ".volstatus", volstatus_list);
188    dir_cmd(conn, ".mediatypes", mediatype_list);
189    dir_cmd(conn, ".locations", location_list);
190
191    if (mainWin->m_connDebug) {
192       QString dbgmsg = QString("jobs=%1 clients=%2 filesets=%3 msgs=%4 pools=%5 storage=%6 types=%7 levels=%8 conn=%9 %10\n")
193         .arg(job_list.count()).arg(client_list.count()).arg(fileset_list.count()).arg(messages_list.count())
194         .arg(pool_list.count()).arg(storage_list.count()).arg(type_list.count()).arg(level_list.count())
195         .arg(conn).arg(m_dir->name());
196       Pmsg1(000, "%s", dbgmsg.toUtf8().data());
197    }
198    job_list.sort();
199    client_list.sort();
200    fileset_list.sort();
201    messages_list.sort();
202    pool_list.sort();
203    storage_list.sort();
204    type_list.sort();
205    level_list.sort();
206 }
207
208 /*
209  *  Overload function for dir_cmd with a QString
210  *  Ease of use
211  */
212 bool Console::dir_cmd(QString &cmd, QStringList &results)
213 {
214    return dir_cmd(cmd.toUtf8().data(), results);
215 }
216
217 /*
218  *  Overload function for dir_cmd, this is if connection is not worried about
219  */
220 bool Console::dir_cmd(const char *cmd, QStringList &results)
221 {
222    int conn;
223    if (getDirComm(conn)) {
224       dir_cmd(conn, cmd, results);
225       return true;
226    } else {
227       Pmsg1(000, "dir_cmd failed to connect to %s\n", m_dir->name());
228       return false;
229    }
230 }
231
232 /*
233  * Send a command to the Director, and return the
234  *  results in a QStringList.  
235  */
236 bool Console::dir_cmd(int conn, const char *cmd, QStringList &results)
237 {
238    mainWin->waitEnter();
239    DirComm *dircomm = m_dircommHash.value(conn);
240    int stat;
241    bool prev_notify = mainWin->m_notify;
242
243    if (mainWin->m_connDebug) {
244       QString dbgmsg = QString("dir_cmd conn %1 %2 %3\n").arg(conn).arg(m_dir->name()).arg(cmd);
245       Pmsg1(000, "%s", dbgmsg.toUtf8().data());
246    }
247    notify(conn, false);
248    dircomm->write(cmd);
249    while ((stat = dircomm->read()) > 0 && dircomm->is_in_command()) {
250       if (mainWin->m_displayAll) display_text(dircomm->msg());
251       strip_trailing_junk(dircomm->msg());
252       results << dircomm->msg();
253    }
254    if (stat > 0 && mainWin->m_displayAll) display_text(dircomm->msg());
255    if (prev_notify) {
256       notify(conn, true);         /* turn it back on */
257    }
258    discardToPrompt(conn);
259    mainWin->waitExit();
260    return true;                  /* ***FIXME*** return any command error */
261 }
262
263 /*
264  * OverLoads for sql_cmd
265  */
266 bool Console::sql_cmd(int &conn, QString &query, QStringList &results)
267 {
268    return sql_cmd(conn, query.toUtf8().data(), results, false);
269 }
270
271 bool Console::sql_cmd(QString &query, QStringList &results)
272 {
273    int conn;
274    if (!getDirComm(conn)) {
275       return false;
276    }
277    return sql_cmd(conn, query.toUtf8().data(), results, true);
278 }
279
280 bool Console::sql_cmd(const char *query, QStringList &results)
281 {
282    int conn;
283    if (!getDirComm(conn)) {
284       return false;
285    }
286    return sql_cmd(conn, query, results, true);
287 }
288
289 /*
290  * Send an sql query to the Director, and return the
291  *  results in a QStringList.  
292  */
293 bool Console::sql_cmd(int &conn, const char *query, QStringList &results, bool donotify)
294 {
295    DirComm *dircomm = m_dircommHash.value(conn);
296    int stat;
297    POOL_MEM cmd(PM_MESSAGE);
298    bool prev_notify = mainWin->m_notify;
299
300    if (!is_connectedGui()) {
301       return false;
302    }
303
304    if (mainWin->m_connDebug) Pmsg2(000, "sql_cmd conn %i %s\n", conn, query);
305    if (donotify) {
306       dircomm->notify(false);
307    }
308    mainWin->waitEnter();
309    
310    pm_strcpy(cmd, ".sql query=\"");
311    pm_strcat(cmd, query);
312    pm_strcat(cmd, "\"");
313    dircomm->write(cmd.c_str());
314    while ((stat = dircomm->read()) > 0) {
315       bool first = true;
316       if (mainWin->m_displayAll) {
317          display_text(dircomm->msg());
318          display_text("\n");
319       }
320       strip_trailing_junk(dircomm->msg());
321       bool doappend = true;
322       if (first) {
323          QString dum = dircomm->msg();
324          if ((dum.left(6) == "*None*")) doappend = false;
325       }
326       if (doappend) {
327          results << dircomm->msg();
328       }
329       first = false;
330    }
331    if (donotify && prev_notify) {
332       dircomm->notify(true);
333    }
334    discardToPrompt(conn);
335    mainWin->waitExit();
336    return !mainWin->isClosing();      /* return false if closing */
337 }
338
339 /* 
340  * Overloads for
341  * Sending a command to the Director
342  */
343 int Console::write_dir(const char *msg)
344 {
345    int conn;
346    if (getDirComm(conn)) {
347       write_dir(conn, msg);
348    }
349    return conn;
350 }
351
352 int Console::write_dir(const char *msg, bool dowait)
353 {
354    int conn;
355    if (getDirComm(conn)) {
356       write_dir(conn, msg, dowait);
357    }
358    return conn;
359 }
360
361 void Console::write_dir(int conn, const char *msg)
362 {
363    write_dir(conn, msg, true);
364 }
365
366 /*
367  * Send a command to the Director
368  */
369 void Console::write_dir(int conn, const char *msg, bool dowait)
370 {
371    DirComm *dircomm = m_dircommHash.value(conn);
372
373    if (dircomm->m_sock) {
374       mainWin->set_status(_("Processing command ..."));
375       if (dowait)
376          mainWin->waitEnter();
377       dircomm->write(msg);
378       if (dowait)
379          mainWin->waitExit();
380    } else {
381       mainWin->set_status( tr(" Director not connected. Click on connect button."));
382       mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
383       QBrush redBrush(Qt::red);
384       QTreeWidgetItem *item = mainWin->getFromHash(this);
385       item->setForeground(0, redBrush);
386       dircomm->m_at_prompt = false;
387       dircomm->m_at_main_prompt = false;
388    }
389 }
390
391 /*
392  * get_job_defaults overload
393  */
394 bool Console::get_job_defaults(struct job_defaults &job_defs)
395 {
396    int conn;
397    return get_job_defaults(conn, job_defs, true);
398 }
399
400 bool Console::get_job_defaults(int &conn, struct job_defaults &job_defs)
401 {
402    return get_job_defaults(conn, job_defs, false);
403 }
404
405 /*  
406  * Send a job name to the director, and read all the resulting
407  *  defaults. 
408  */
409 bool Console::get_job_defaults(int &conn, struct job_defaults &job_defs, bool donotify)
410 {
411    QString scmd;
412    int stat;
413    char *def;
414    bool prev_notify = mainWin->m_notify;
415    bool rtn = false;
416
417    if (donotify) {
418       conn = notifyOff();
419    }
420    beginNewCommand(conn);
421    DirComm *dircomm = m_dircommHash.value(conn);
422    bool prevWaitState = mainWin->getWaitState();
423    if (!prevWaitState)
424       mainWin->waitEnter();
425    if (mainWin->m_connDebug)
426       Pmsg2(000, "job_defaults conn %i %s\n", conn, m_dir->name());
427    scmd = QString(".defaults job=\"%1\"").arg(job_defs.job_name);
428    dircomm->write(scmd);
429    while ((stat = dircomm->read()) > 0) {
430       if (mainWin->m_displayAll) display_text(dircomm->msg());
431       def = strchr(dircomm->msg(), '=');
432       if (!def) {
433          continue;
434       }
435       /* Pointer to default value */
436       *def++ = 0;
437       strip_trailing_junk(def);
438
439       if (strcmp(dircomm->msg(), "job") == 0) {
440          if (strcmp(def, job_defs.job_name.toUtf8().data()) != 0) {
441             goto bail_out;
442          }
443          continue;
444       }
445       if (strcmp(dircomm->msg(), "pool") == 0) {
446          job_defs.pool_name = def;
447          continue;
448       }
449       if (strcmp(dircomm->msg(), "messages") == 0) {
450          job_defs.messages_name = def;
451          continue;
452       }
453       if (strcmp(dircomm->msg(), "client") == 0) {
454          job_defs.client_name = def;
455          continue;
456       }
457       if (strcmp(dircomm->msg(), "storage") == 0) {
458          job_defs.store_name = def;
459          continue;
460       }
461       if (strcmp(dircomm->msg(), "where") == 0) {
462          job_defs.where = def;
463          continue;
464       }
465       if (strcmp(dircomm->msg(), "level") == 0) {
466          job_defs.level = def;
467          continue;
468       }
469       if (strcmp(dircomm->msg(), "type") == 0) {
470          job_defs.type = def;
471          continue;
472       }
473       if (strcmp(dircomm->msg(), "fileset") == 0) {
474          job_defs.fileset_name = def;
475          continue;
476       }
477       if (strcmp(dircomm->msg(), "catalog") == 0) {
478          job_defs.catalog_name = def;
479          continue;
480       }
481       if (strcmp(dircomm->msg(), "enabled") == 0) {
482          job_defs.enabled = *def == '1' ? true : false;
483          continue;
484       }
485    }
486    rtn = true;
487    /* Fall through wanted */
488 bail_out:
489    if (donotify && prev_notify) {
490       notify(conn, true);
491    }
492    if (!prevWaitState) {
493       mainWin->waitExit();
494    }
495    return rtn;
496 }
497
498
499 /*
500  * Save user settings associated with this console
501  */
502 void Console::writeSettings()
503 {
504    QFont font = get_font();
505
506    QSettings settings(m_dir->name(), "bat");
507    settings.beginGroup("Console");
508    settings.setValue("consoleFont", font.family());
509    settings.setValue("consolePointSize", font.pointSize());
510    settings.setValue("consoleFixedPitch", font.fixedPitch());
511    settings.endGroup();
512 }
513
514 /*
515  * Read and restore user settings associated with this console
516  */
517 void Console::readSettings()
518
519    QFont font = get_font();
520
521    QSettings settings(m_dir->name(), "bat");
522    settings.beginGroup("Console");
523    font.setFamily(settings.value("consoleFont", "Courier").value<QString>());
524    font.setPointSize(settings.value("consolePointSize", 10).toInt());
525    font.setFixedPitch(settings.value("consoleFixedPitch", true).toBool());
526    settings.endGroup();
527    m_textEdit->setFont(font);
528 }
529
530 /*
531  * Set the console textEdit font
532  */
533 void Console::set_font()
534 {
535    bool ok;
536    QFont font = QFontDialog::getFont(&ok, QFont(m_textEdit->font()), this);
537    if (ok) {
538       m_textEdit->setFont(font);
539    }
540 }
541
542 /*
543  * Get the console text edit font
544  */
545 const QFont Console::get_font()
546 {
547    return m_textEdit->font();
548 }
549
550 /*
551  * Slot for responding to status dir button on button bar
552  */
553 void Console::status_dir()
554 {
555    QString cmd("status dir");
556    consoleCommand(cmd);
557 }
558
559 /*
560  * Slot for responding to messages button on button bar
561  * Here we want to bring the console to the front so use pages' consoleCommand
562  */
563 void Console::messages()
564 {
565    QString cmd(".messages");
566    consoleCommand(cmd);
567    messagesPending(false);
568 }
569
570 /*
571  * Put text into the console window
572  */
573 void Console::display_textf(const char *fmt, ...)
574 {
575    va_list arg_ptr;
576    char buf[1000];
577    int len;
578    va_start(arg_ptr, fmt);
579    len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
580    va_end(arg_ptr);
581    display_text(buf);
582 }
583
584 void Console::display_text(const QString buf)
585 {
586    if (buf.size() != 0) {
587       m_cursor->insertText(buf);
588       update_cursor();
589    }
590 }
591
592
593 void Console::display_text(const char *buf)
594 {
595    if (*buf != 0) {
596       m_cursor->insertText(buf);
597       update_cursor();
598    }
599 }
600
601 void Console::display_html(const QString buf)
602 {
603    if (buf.size() != 0) {
604       m_cursor->insertHtml(buf);
605       update_cursor();
606    }
607 }
608
609 /* Position cursor to end of screen */
610 void Console::update_cursor()
611 {
612    m_textEdit->moveCursor(QTextCursor::End);
613    m_textEdit->ensureCursorVisible();
614 }
615
616 void Console::beginNewCommand(int conn)
617 {
618    DirComm *dircomm = m_dircommHash.value(conn);
619
620    for (int i=0; i < 3; i++) {
621       dircomm->write(".");
622       while (dircomm->read() > 0) {
623          if (mainWin->m_commDebug) Pmsg2(000, "begin new command loop %i %s\n", i, m_dir->name());
624          if (mainWin->m_displayAll) display_text(dircomm->msg());
625       }
626       if (dircomm->m_at_main_prompt) {
627          break;
628       }
629    }
630    display_text("\n");
631 }
632
633 void Console::displayToPrompt(int conn)
634
635    DirComm *dircomm = m_dircommHash.value(conn);
636
637    int stat = 0;
638    QString buf;
639    if (mainWin->m_commDebug) Pmsg1(000, "DisplaytoPrompt %s\n", m_dir->name());
640    while (!dircomm->m_at_prompt) {
641       if ((stat=dircomm->read()) > 0) {
642          buf += dircomm->msg();
643          if (buf.size() >= 8196 || m_messages_pending) {
644             display_text(buf);
645             buf.clear();
646             messagesPending(false);
647          }
648       }
649    }
650    display_text(buf);
651    if (mainWin->m_commDebug) Pmsg2(000, "endDisplaytoPrompt=%d %s\n", stat, m_dir->name());
652 }
653
654 void Console::discardToPrompt(int conn)
655 {
656    DirComm *dircomm = m_dircommHash.value(conn);
657
658    int stat = 0;
659    if (mainWin->m_commDebug) Pmsg1(000, "discardToPrompt %s\n", m_dir->name());
660    if (mainWin->m_displayAll) {
661       displayToPrompt(conn);
662    } else {
663       while (!dircomm->m_at_prompt) {
664          stat = dircomm->read();
665          if (stat < 0) {
666             break;
667          }
668       }
669    }
670    if (mainWin->m_commDebug) {
671       Pmsg2(000, "endDiscardToPrompt conn=%i %s\n", conn, m_dir->name());
672    }
673 }
674
675 QString Console::returnFromPrompt(int conn)
676
677    DirComm *dircomm = m_dircommHash.value(conn);
678    QString text("");
679
680    int stat = 0;
681    text = "";
682    dircomm->read();
683    text += dircomm->msg();
684    if (mainWin->m_commDebug) Pmsg1(000, "returnFromPrompt %s\n", m_dir->name());
685    while (!dircomm->m_at_prompt) {
686       if ((stat=dircomm->read()) > 0) {
687          text += dircomm->msg();
688       }
689    }
690    if (mainWin->m_commDebug) Pmsg2(000, "endreturnFromPrompt=%d %s\n", stat, m_dir->name());
691    return text;
692 }
693
694 /*
695  * When the notifier is enabled, read_dir() will automatically be
696  * called by the Qt event loop when ever there is any output 
697  * from the Director, and read_dir() will then display it on
698  * the console.
699  *
700  * When we are in a bat dialog, we want to control *all* output
701  * from the Director, so we set notify to off.
702  *    m_console->notifiy(false);
703  */
704
705 /* dual purpose function to turn notify off and return a connection */
706 int Console::notifyOff()
707
708    int conn = 0;
709    if (getDirComm(conn)) {
710       notify(conn, false);
711    }
712    return conn;
713 }
714
715 /* knowing a connection, turn notify off or on */
716 bool Console::notify(int conn, bool enable)
717
718    DirComm *dircomm = m_dircommHash.value(conn);
719    return dircomm->notify(enable);
720 }
721
722 /* knowing a connection, return notify state */
723 bool Console::is_notify_enabled(int conn) const
724 {
725    DirComm *dircomm = m_dircommHash.value(conn);
726    return dircomm->is_notify_enabled();
727 }
728
729 void Console::setDirectorTreeItem(QTreeWidgetItem *item)
730 {
731    m_directorTreeItem = item;
732 }
733
734 void Console::setDirRes(DIRRES *dir) 
735
736    m_dir = dir;
737 }
738
739 /*
740  * To have the ability to get the name of the director resource.
741  */
742 void Console::getDirResName(QString &name_returned)
743 {
744    name_returned = m_dir->name();
745 }
746
747 /* Slot for responding to page selectors status help command */
748 void Console::consoleHelp()
749 {
750    QString cmd("help");
751    consoleCommand(cmd);
752 }
753
754 /* Slot for responding to page selectors reload bacula-dir.conf */
755 void Console::consoleReload()
756 {
757    QString cmd("reload");
758    consoleCommand(cmd);
759 }
760
761 /* For suppressing .messages
762  * This may be rendered not needed if the multiple connections feature gets working */
763 bool Console::hasFocus()
764 {
765    if (mainWin->tabWidget->currentIndex() == mainWin->tabWidget->indexOf(this))
766       return true;
767    else
768       return false;
769 }
770
771 /* For adding feature to have the gui's messages button change when 
772  * messages are pending */
773 bool Console::messagesPending(bool pend)
774 {
775    bool prev = m_messages_pending;
776    m_messages_pending = pend;
777    mainWin->setMessageIcon();
778    return prev;
779 }
780
781 /* terminate all existing connections */
782 void Console::terminate()
783 {
784    foreach(DirComm* dircomm,  m_dircommHash) {
785       dircomm->terminate();
786    }
787    m_console->stopTimer();
788 }
789
790 /* Maybe this should be checking the list, for the moment lets check 0 which should be connected */
791 bool Console::is_connectedGui()
792 {
793    if (is_connected(0)) {
794       return true;
795    } else {
796       QString message = tr("Director is currently disconnected\nPlease reconnect!");
797       QMessageBox::warning(this, "Bat", message, QMessageBox::Ok );
798       return false;
799    }
800 }
801
802 int Console::read(int conn)
803 {
804    DirComm *dircomm = m_dircommHash.value(conn);
805    return dircomm->read();
806 }
807
808 char *Console::msg(int conn)
809 {
810    DirComm *dircomm = m_dircommHash.value(conn);
811    return dircomm->msg();
812 }
813
814 int Console::write(int conn, const QString msg)
815 {
816    DirComm *dircomm = m_dircommHash.value(conn);
817    mainWin->waitEnter();
818    int ret = dircomm->write(msg);
819    mainWin->waitExit();
820    return ret;
821 }
822
823 int Console::write(int conn, const char *msg)
824 {
825    DirComm *dircomm = m_dircommHash.value(conn);
826    mainWin->waitEnter();
827    int ret = dircomm->write(msg);
828    mainWin->waitExit();
829    return ret;
830 }
831
832 /* This checks to see if any is connected */
833 bool Console::is_connected()
834 {
835    bool connected = false;
836    foreach(DirComm* dircomm,  m_dircommHash) {
837       if (dircomm->is_connected())
838          return true;
839    }
840    return connected;
841 }
842
843 /* knowing the connection id, is it connected */
844 bool Console::is_connected(int conn)
845 {
846    DirComm *dircomm = m_dircommHash.value(conn);
847    return dircomm->is_connected();
848 }
849
850 /*
851  * Need a connection.  Check existing connections or create one
852  */
853 bool Console::getDirComm(int &conn)
854 {
855    if (findDirComm(conn)) {
856       return true;
857    }
858    if (mainWin->m_connDebug) Pmsg0(000, "call newDirComm\n");
859    return newDirComm(conn);
860 }
861
862
863 /*
864  * Try to find a free (unused but established) connection
865  * KES: Note, I think there is a problem here because for
866  *   some reason, the notifier is often turned off on file  
867  *   descriptors that seem to me to be available.  That means
868  *   that we do not use a free descriptor and thus we will create
869  *   a new connection that is maybe not necessary.  Someone needs
870  *   to look into whether or not notify() is correctly turned on
871  *   when we are back at the command prompt and idle.
872  *                         
873  */
874 bool Console::findDirComm(int &conn)
875 {
876    int i = 1;
877    QHash<int, DirComm*>::const_iterator iter = m_dircommHash.constBegin();
878    while (iter != m_dircommHash.constEnd()) {
879       DirComm *dircomm = iter.value();
880       if (dircomm->m_at_prompt && dircomm->m_at_main_prompt && dircomm->is_notify_enabled()) {
881          conn = dircomm->m_conn;
882          return true;
883       }
884       if (mainWin->m_connDebug) {
885          Pmsg4(000, "currentDirComm=%d at_prompt=%d at_main=%d && notify=%d\n",                                      
886             i, dircomm->m_at_prompt, dircomm->m_at_main_prompt, dircomm->is_notify_enabled());
887          i++;
888       }
889       ++iter;
890    }
891    return false;
892 }
893
894 /*
895  *  Create a new connection
896  */
897 bool Console::newDirComm(int &conn)
898 {
899    m_dircommCounter++;
900    if (mainWin->m_connDebug) {
901       Pmsg2(000, "newDirComm=%i to: %s\n", m_dircommCounter, m_dir->name());
902    }
903    DirComm *dircomm = new DirComm(this, m_dircommCounter);
904    m_dircommHash.insert(m_dircommCounter, dircomm);
905    bool success = dircomm->connect_dir();
906    if (mainWin->m_connDebug) {
907       if (success) {
908          Pmsg2(000, "newDirComm=%i Connected %s\n", m_dircommCounter, m_dir->name());
909       } else {
910          Emsg2(M_ERROR, 0, "DirComm=%i. Unable to connect to %s\n",
911                m_dircommCounter, m_dir->name());
912       }
913    }
914    if (!success) {
915       m_dircommHash.remove(m_dircommCounter);
916       delete dircomm;
917       m_dircommCounter--;
918    }
919    conn = m_dircommCounter;
920    return success;
921 }