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