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