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