source: UH/SAMGAR/SAMGAR Gui/SourceFiles/MainComponent.cpp @ 125

Revision 125, 39.5 KB checked in by KDucasse, 10 years ago (diff)
Line 
1
2
3#include "MainComponent.h"
4
5#define definedsizeofball 50
6#define Pi  3.14159265
7#define SetupMode 0
8#define RunMode 1
9
10static int MyMode;
11static  Port MyConnectionTesterPort;
12
13string NameOfServer = "/local";
14using namespace std;
15
16#define local 1
17#define global  2
18
19bool IgnoreTimer =false;
20
21list<string> MigSites;
22string NameofMigrate;
23
24BufferedPort<Bottle> ThePortForModules;
25
26
27
28
29/*! main window constructor !*/
30MainComponent::MainComponent (): helloWorldLabel (0), quitButton (0)
31{
32
33        Network yarp;
34
35        WhatShownDebug[0]=1;
36        WhatShownDebug[1]=1;
37        WhatShownDebug[2]=1;
38        WhatShownDebug[3]=1;
39
40        startTimer (5000);
41        helloWorldLabel = new Label (String::empty,T("SAMGAR Network Profile"));
42    addAndMakeVisible (helloWorldLabel);
43    helloWorldLabel->setFont (Font (10.0000f, Font::bold));
44        helloWorldLabel->setBounds(890,100,10,20);
45    helloWorldLabel->setJustificationType (Justification::centred);
46    helloWorldLabel->setEditable (false, false, false);
47    helloWorldLabel->setColour (Label::textColourId, Colours::black);
48    helloWorldLabel->setColour (TextEditor::textColourId, Colours::black);
49    helloWorldLabel->setColour (TextEditor::backgroundColourId, Colour (0x0));
50
51        addAndMakeVisible(MytextEditor = new TextEditor());
52    MytextEditor->setBounds (890, 25, 300, 300);
53    MytextEditor->setText (T("Debug Log Init \n"));
54        MytextEditor->setMultiLine(true,true);
55        MytextEditor->setReadOnly(true);
56        MytextEditor->setCaretVisible(false);
57
58        addAndMakeVisible(MytextEditor2 = new TextEditor());
59    MytextEditor2->setBounds (890, 300+25+30, 300, 100);
60    MytextEditor2->setText (T("Feedback Log Init \n"));
61        MytextEditor2->setMultiLine(true,true);
62        MytextEditor2->setReadOnly(true);
63        MytextEditor2->setCaretVisible(false);
64
65
66        addAndMakeVisible(ModParent1 = new ComboBox("N/A"));
67    ModParent1->setBounds (900-5,480, 175-30, 25);
68        ModParent1->setText(T("Parent 1"));
69
70        addAndMakeVisible(ModParent2 = new ComboBox("N/A"));
71    ModParent2->setBounds (900+140,480, 175-30, 25);
72        ModParent2->setText(T("Parent 2"));
73
74        addAndMakeVisible(ModChild1 = new ComboBox("N/A"));
75    ModChild1->setBounds (900-5,480+5+25, 175-30, 25);
76        ModChild1->setText(T("Child 1"));
77
78        addAndMakeVisible(ModChild2 = new ComboBox("N/A"));
79    ModChild2->setBounds (900+140,480+5+25, 175-30, 25);
80        ModChild2->setText(T("Child 2"));
81
82        addAndMakeVisible(LossBox = new ComboBox("N/A"));
83    LossBox->setBounds (900-5,480+5+25+30, 175-30, 25);
84        LossBox->setText(T("Lossy/Unlossy"));
85        LossBox->addItem("Lossy",1);
86        LossBox->addItem("Unlossy",2);
87
88
89
90
91        addAndMakeVisible(Connect = new ComboBox("N/A"));
92    Connect->setBounds (900-5,480+5+25+30+30, 175-30, 25);
93        Connect->setText(T("Connect/Disconnect"));
94        Connect->addItem("Connect",1);
95        Connect->addItem("Disconnect",2);
96
97        addAndMakeVisible(NetworkBox = new ComboBox("N/A"));
98    NetworkBox->setBounds (900+140,480+5+25+30, 175-30, 25);
99        NetworkBox->setText(T("Network Type"));
100
101        NetworkBox->addItem("Process",1);
102        NetworkBox->addItem("Platform",2);
103        NetworkBox->addItem("Local Network",3);
104
105       
106
107        ConnectionStuff = new TextButton (String::empty);
108        addAndMakeVisible (ConnectionStuff);
109        ConnectionStuff->setBounds (900+140,480+5+25+30+30, 175-30, 25);
110        ConnectionStuff->setButtonText (T("Proceed"));
111    ConnectionStuff->addButtonListener (this);
112
113    addAndMakeVisible (quitButton = new TextButton (String::empty));
114        quitButton->setButtonText (T("Quit"));
115    quitButton->addButtonListener (this);
116
117        ClearLog = new TextButton (String::empty);
118        addAndMakeVisible (ClearLog);
119        ClearLog->setBounds(740,27+120+30+10,100,30);
120        ClearLog->setButtonText (T("Clear Log"));
121    ClearLog->addButtonListener (this);
122
123        RefreshConnect = new TextButton (String::empty);
124        addAndMakeVisible (RefreshConnect);
125        RefreshConnect->setBounds(740,27+120+30+30+10+10,100,30);
126        RefreshConnect->setButtonText (T("RefreshConnect"));
127    RefreshConnect->addButtonListener (this);
128
129        StopButton = new TextButton (String::empty);
130        addAndMakeVisible (StopButton);
131        StopButton->setBounds(740,27+120+30+30+10+10+10+30,100,30);
132        StopButton->setButtonText (T("Stop Modules"));
133    StopButton->addButtonListener (this);
134
135        MigrateButton = new TextButton (String::empty);
136        addAndMakeVisible (MigrateButton);
137        MigrateButton->setBounds(740,27+120+30+30+10+10+10+40+40+40,100,30);
138        MigrateButton->setButtonText (T("Migrate - Test"));
139    MigrateButton->addButtonListener (this);
140
141        StartButton = new TextButton (String::empty);
142        addAndMakeVisible (StartButton);
143        StartButton->setBounds(740,27+120+30+30+10+10+10+40+40,100,30);
144        StartButton->setButtonText (T("Start Modules"));
145    StartButton->addButtonListener (this);
146
147        OpenLogButton = new TextButton (String::empty);
148        addAndMakeVisible (OpenLogButton);
149        OpenLogButton->setBounds(740,27+120+30+30+10+10+10+40+40+80,100,30);
150        OpenLogButton->setButtonText (T("Open log"));
151    OpenLogButton->addButtonListener (this);
152
153
154        SaveLog = new TextButton (String::empty);
155        addAndMakeVisible (SaveLog);
156        SaveLog->setBounds(740,27+120+5,100,30);
157        SaveLog->setButtonText (T("Save log"));
158    SaveLog->addButtonListener (this);
159
160        SaveMod = new TextButton (String::empty);
161        addAndMakeVisible (SaveMod);
162        SaveMod->setBounds(740,27+120+30+30+10+10+10+40+40+80+40,100,30);
163        SaveMod->setButtonText (T("Save Modules"));
164    SaveMod->addButtonListener (this);
165
166        LoadMod = new TextButton (String::empty);
167        addAndMakeVisible (LoadMod);
168        LoadMod->setBounds(740,27+120+30+30+10+10+10+40+40+80+40+40,100,30);
169        LoadMod->setButtonText (T("Load Modules"));
170    LoadMod->addButtonListener (this);
171
172        SaveCon = new TextButton (String::empty);
173        addAndMakeVisible (SaveCon);
174        SaveCon->setBounds(740,27+120+30+30+10+10+10+40+40+80+40+40+40,100,30);
175        SaveCon->setButtonText (T("Save Connections"));
176    SaveCon->addButtonListener (this);
177
178        LoadCon = new TextButton (String::empty);
179        addAndMakeVisible (LoadCon);
180        LoadCon->setBounds(740,27+120+30+30+10+10+10+40+40+80+40+40+40+40,100,30);
181        LoadCon->setButtonText (T("Load Connections"));
182    LoadCon->addButtonListener (this);
183
184        DebugButton1 = new TextButton (String::empty);
185        addAndMakeVisible (DebugButton1);
186        DebugButton1->setBounds(740,27,100,30);
187        DebugButton1->setButtonText (T("debug priority 1 on"));
188    DebugButton1->addButtonListener (this);
189        DebugButton1->setConnectedEdges(Button::ConnectedOnBottom);     
190
191        DebugButton2 = new TextButton (String::empty);
192        addAndMakeVisible (DebugButton2);
193        DebugButton2->setBounds(740,27+30,100,30);
194        DebugButton2->setButtonText (T("debug priority 2 on"));
195    DebugButton2->addButtonListener (this);
196        DebugButton2->setConnectedEdges(Button::ConnectedOnTop | Button::ConnectedOnBottom);   
197
198        DebugButton3 = new TextButton (String::empty);
199        addAndMakeVisible (DebugButton3);
200        DebugButton3->setBounds(740,27+30+30,100,30);
201        DebugButton3->setButtonText (T("debug priority 3 on"));
202    DebugButton3->addButtonListener (this);
203        DebugButton3->setConnectedEdges(Button::ConnectedOnTop | Button::ConnectedOnBottom);   
204
205        DebugButton4 = new TextButton (String::empty);
206        addAndMakeVisible (DebugButton4);
207        DebugButton4->setBounds(740,27+30+30+30,100,30);
208        DebugButton4->setButtonText (T("debug priority 4 on"));
209    DebugButton4->addButtonListener (this);
210        DebugButton4->setConnectedEdges(Button::ConnectedOnTop);       
211    setSize (1200, 600);
212
213        DebugButton1->setClickingTogglesState(true);
214        DebugButton1->setColour(0x1000100,Colours::green);
215        DebugButton1->setColour(0x1000101,Colours::red);
216
217        DebugButton2->setClickingTogglesState(true);
218        DebugButton2->setColour(0x1000100,Colours::green);
219        DebugButton2->setColour(0x1000101,Colours::red);
220
221        DebugButton3->setClickingTogglesState(true);
222        DebugButton3->setColour(0x1000100,Colours::green);
223        DebugButton3->setColour(0x1000101,Colours::red);
224
225        DebugButton4->setClickingTogglesState(true);
226        DebugButton4->setColour(0x1000100,Colours::green);
227        DebugButton4->setColour(0x1000101,Colours::red);
228
229        GetCurrentServerName();
230        RegisterMigrationPort();
231
232        ThePortForModules.open("/PortForModules");
233        ThePortForModules.setStrict(true);
234
235}
236
237/*! main window de-structor !*/
238MainComponent::~MainComponent()
239{
240        // save the mod log;
241        MyTime.getCurrentTime();
242        String datePlus = MyTime.toString(true,true,true,true);
243        datePlus = datePlus + ".SamModLog";
244        myFileforModReport = datePlus;
245        myFileforModReport.create ();
246        myFileforModReport.appendText (MytextEditor2->getText ()); // get from the mod log editor
247
248
249        Network::fini();
250        MigrationPort.close();
251        AllConnections.clear();
252    deleteAndZero (helloWorldLabel);
253    deleteAndZero (quitButton);
254}
255
256/*! changes the current namespace , allows to com with local and global server !*/
257void ChangeServer(int change){  Network::setNameServerName((change==local)?NameOfServer.c_str():"/global");}
258
259/*! Get the current namespace and save it so we can always switch back!*/
260void GetCurrentServerName(void){NameOfServer=Network::getNameServerName();}
261
262/*! Register the main migration port!*/
263void MainComponent::RegisterMigrationPort (void)
264{
265        IgnoreTimer=true;
266        ChangeServer(global);
267        NameofMigrate = NameOfServer + "_Migration";
268        static bool opened = MigrationPort.open(NameofMigrate.c_str());
269
270        ChangeServer(local);
271        IgnoreTimer=false;
272
273        if(opened==true){AddToLog("Addid myself to global server :\n",1);}
274        else                    {AddToLog("could not Add myself to global server :\n",1);}
275        AddToLog(NameofMigrate.c_str(),1);
276        AddToLog("\n",1);
277}
278
279/*! Migrate function!*/
280bool MainComponent::Migrate (string nameofwhere)
281{
282        AddToLog(" Attempting to Migrate  \n",1);
283        IgnoreTimer=true;
284        ChangeServer(global);
285
286        if(MigrationPort.isClosed()==true){AddToLog("Migration port is closed \n",1);}
287
288        Bottle& MyBottle =MigrationPort.prepare();
289        MyBottle.clear();
290
291        nameofwhere = "/" + nameofwhere + "_Migration";
292
293        AddToLog(nameofwhere.c_str(),1);AddToLog(" to ",1);AddToLog(MigrationPort.getName().c_str(),1);AddToLog("\n",1);
294
295bool true1= MigrationPort.addOutput(nameofwhere.c_str()); 
296
297
298if(true1==false){AddToLog("Could not connect to migrate, operation aborted \n",1);}
299
300
301if(true1==false){ChangeServer(local);IgnoreTimer=false; return false;}
302
303  string line;
304  ifstream myfile ("Personality.txt");
305 
306  if (myfile.is_open())
307  {
308        //  AddToLog(" opened file  \n",1);
309    while (! myfile.eof() )
310    {
311     getline (myfile,line);
312          MyBottle.addString(line.c_str());
313    }
314    myfile.close();
315//      AddToLog("   \n",1);
316 }
317  else
318  {
319          AddToLog(" could not open file \n",1);
320          ChangeServer(local);
321          IgnoreTimer=false;
322          return false;
323  }
324
325 MigrationPort.write();
326 AddToLog(" Migration Sucsessfull \n",1);
327
328 Network::disconnect(MigrationPort.getName(),nameofwhere.c_str());
329 Network::disconnect(nameofwhere.c_str(),MigrationPort.getName());
330
331
332 ChangeServer(local);
333IgnoreTimer=false;
334return true ;// if its sucsessfull
335}
336
337
338
339
340
341/*! update a list of available platforms we can migrate to !*/
342void MainComponent::UpdateMigrationProto(void)
343{
344IgnoreTimer=true;
345FILE *inpipe;
346char inbuf[200];
347String hello;
348int lineno = 0;
349int start,fin;
350
351ChangeServer(global);
352RegisterMigrationPort(); // registers istelf, doesn't matter cos it cleans the server anyways
353// if its windows
354#ifdef  Rectangle
355        inpipe = _popen("yarp clean","r");
356        inpipe = _popen("yarp name list","r");
357#else
358        inpipe =  popen("yarp clean","r");
359    inpipe =  popen("yarp name list", "r");
360#endif
361
362        MigrationPlatformsAvail.clear();
363    if (!inpipe){AddToLog("Cannot access needid function to find other platforms\n",1);   }
364    else
365        {
366                AddToLog(" List of possible migration platforms :\n",1);
367
368         while (fgets(inbuf, sizeof(inbuf), inpipe))
369                 {
370
371                    String mystring = inbuf;
372                        mystring=mystring +"\n";
373                        if(mystring.containsChar('/')==true && mystring.contains(String("Migration"))==true)
374                         {
375                                 int start = mystring.indexOf(String("/"));
376                                 int fin   = mystring.indexOf(start,String(" "));
377
378                                 mystring=mystring.substring(start,fin);
379                                 MigrationPlatformsAvail.push_front(string(mystring));
380                                 mystring = "--->"+mystring+   "\n";
381                 AddToLog(mystring,1);
382
383                                 /// need to add it to the list here as well
384                         }
385                }
386    }
387 ChangeServer(local);
388
389 IgnoreTimer=false;
390}
391
392
393
394
395/*! Checks that each connection is working, ignores failed modules !*/
396void MainComponent::ConnectionAutoUpdate(void)
397{
398
399                list<connections>::iterator it2;
400                list<TextButton*>::iterator itTextButton55;
401                TextButton* TempModuleButton55;
402
403
404        for ( it2=AllConnections.begin() ; it2 != AllConnections.end(); it2++ )
405                {
406                        connections mytempconnect;
407                        mytempconnect = *it2;
408                        string tempstring10 = mytempconnect.firstport;
409                        string tempstring20 = mytempconnect.secoundport;
410                        tempstring10=tempstring10.substr(1,tempstring10.length()-1);
411                        tempstring20=tempstring20.substr(1,tempstring20.length()-1);
412
413                        string firststring = "/Port_"   + mytempconnect.Daddyfirstport + "_"  + tempstring10.c_str();
414                        string secoundstring = "/Port_" + mytempconnect.Daddysecoundport + "_" + tempstring20.c_str();
415
416                        // only connect with UDP or TCP for time being
417                        bool true1,true2;
418                        bool skip;
419                        skip = false;
420
421
422                        for ( itTextButton55=SeenModules.begin() ; itTextButton55 != SeenModules.end(); itTextButton55++ )
423                        {
424                                TempModuleButton55 = *itTextButton55;
425                                if(TempModuleButton55->getButtonText()==mytempconnect.Daddyfirstport || TempModuleButton55->getButtonText()==mytempconnect.Daddysecoundport)
426                                {
427                                        if(Colours::red==TempModuleButton55->findColour(0x1000102,false)){skip=true;}
428                                }
429                        }
430
431
432                        if(skip==false)
433                        {
434
435                                true1=Network::isConnected(firststring.c_str(),secoundstring.c_str(),true);
436                                true2=Network::isConnected(secoundstring.c_str(),firststring.c_str(),true);
437
438                                if(true1!=true || true2!=true)
439                                {
440                                        if(mytempconnect.Lossy==String("Lossy"))
441                                        {
442                                                true1 = Network::connect(firststring.c_str(),secoundstring.c_str(),"udp",true);
443                                                true2 = Network::connect(secoundstring.c_str(),firststring.c_str(),"udp",true);
444                                        }
445                                        else
446                                        {
447                                                true1 = Network::connect(firststring.c_str(),secoundstring.c_str(),"tcp",true);
448                                                true2 = Network::connect(secoundstring.c_str(),firststring.c_str(),"tcp",true);
449                                        }
450                                        if(true1==true && true2==true){mytempconnect.IsConnected=true; }
451                                        else                                              {mytempconnect.IsConnected=false; }
452                                }
453                        }
454                        else
455                        {
456                                mytempconnect.IsConnected=false;
457                        }
458                        *it2=mytempconnect;
459                        RefreashConnections();
460                }
461
462}
463/*! checks the main port for each module can be connected to so its up and running!*/
464void MainComponent::CheckConnectionRight()
465{
466                list<TextButton*>::iterator itTextButton66;
467                TextButton* TempModuleButton66;
468
469        for ( itTextButton66=SeenModules.begin() ; itTextButton66 != SeenModules.end(); itTextButton66++ )
470                {
471                        TempModuleButton66 = *itTextButton66;
472                        if(Colours::red!=TempModuleButton66->findColour(0x1000102,false))
473                        {
474                                string mystring = TempModuleButton66->getButtonText();
475                                mystring = "/Main_" + mystring;
476
477                                //ought to be check for connection and if not connected then reconnect;
478                                if(Network::isConnected(mystring.c_str(),"/PortForModules",true)==false || Network::isConnected("/PortForModules",mystring.c_str(),true)==false)
479                                {
480                                        if(Network::connect(mystring.c_str(),"/PortForModules","tcp",true)==false || Network::connect("/PortForModules",mystring.c_str(),"tcp",true)==false)
481                                        {
482                                                TempModuleButton66->setColour(0x1000102 ,Colours::red);
483                                                AddToLog("The module Main_"+TempModuleButton66->getButtonText()+ " is in error \n",2);
484                                        }
485                                }
486                        }
487                }
488
489}
490
491/*!
492Time callback checks modules and connections , also checks the keytomodules port which recives data from ports ie stop commands etc
493bounces a few of them back as well to enable one module to communicate with all of them
494!*/
495
496void MainComponent::timerCallback()
497{
498        Bottle b;
499        list<string>::iterator it;
500
501
502        if(IgnoreTimer==false)
503        {
504                ChangeServer(local);
505                Network yarp;
506
507                CheckConnectionRight(); // looks like the problem is in here
508                ConnectionAutoUpdate();
509               
510
511
512//              int mycounterthingy = ThePortForModules.getPendingReads();
513                while(ThePortForModules.getPendingReads()>0)
514                {
515
516                        Bottle *b = ThePortForModules.read(true);
517                        if(b!=NULL && b->isNull()==false) // if theres data on the port
518                        {
519                                Bottle& cc = ThePortForModules.prepare();
520                                /// if its a report on how well its done then add to a log else
521                                if(b->get(0).asInt()==20)
522                                {
523                                        String MyNewString = b->get(1).asString().c_str();
524                                        double ModScore = b->get(2).asInt();
525                                        MyNewString = MyNewString + " achived score " + String(ModScore) + " \n";
526                                        MytextEditor2->insertTextAtCursor(MyNewString);
527                                }
528                                // add to log
529                                else if(b->get(0).asInt()==30)
530                                {
531                                        String MyNewString = b->get(1).asString().c_str();
532                                        String LogScore    = b->get(2).asString().c_str();
533                                        MyNewString = MyNewString + " : " + LogScore + " \n";
534                                        AddToLog(MyNewString,b->get(3).asInt());
535                                }
536                                else if(b->get(0).asInt()==40)
537                                {
538                                        UpdateMigrationProto();
539                                        cc.addInt(50); // code for platforms
540                                        for ( it=MigrationPlatformsAvail.begin() ; it != MigrationPlatformsAvail.end(); it++ )
541                                        {
542                                                string temppy = *it;
543                                                cc.addString(temppy.c_str());
544                                        }
545                                        ThePortForModules.write();
546
547                                }
548                                // just send on
549                                else if(b->get(0).asInt()==10)
550                                {
551                                        cc.addInt(10);
552                                        cc.addString(b->get(1).asString());
553                                        cc.addString(b->get(2).asString());
554                                        cc.addString(b->get(3).asString());
555                                        ThePortForModules.write();
556                                }
557
558                                // send the global command on to all modules
559                                else if(b->get(0).asInt()>=0 && b->get(0).asInt()<=2)
560                                {
561                                        AddToLog("recived command to stop all modules \n",1);
562                                        cc.addInt(b->get(0).asInt());
563                                        ThePortForModules.write();
564                                }
565                                // send the personal command to all modules
566                                else if(b->get(0).asInt()>=3 && b->get(0).asInt()<=5)
567                                {
568                                AddToLog("recived command to stop a module \n",1);
569                                        cc.addInt   (b->get(0).asInt());
570                                        cc.addString(b->get(1).asString());
571                                        ThePortForModules.write();
572                                }
573
574                        }
575                }
576
577                if(MigrationPort.Ivebeenused==1)
578                {
579                        AddToLog("Someone has tryed to acess my migration port \n",1);
580                        MigrationPort.Ivebeenused=0;
581                }
582
583        }
584}
585
586
587
588
589
590
591
592
593
594/*!
595Adds a module to the lists and displayes it on screen
596!*/
597void MainComponent::AddModule(String name)
598{
599static int TotalModules=5;
600static int menucount = 1;
601bool IsItOnList=false;
602        // need to put a bit in here to add to the port list and give it its id
603
604for ( itTextButton2=SeenModules.begin() ; itTextButton2 != SeenModules.end(); itTextButton2++ )
605                {
606                TempModuleButton = *itTextButton2;
607                if(name==TempModuleButton->getButtonText())
608                        {
609                        TempModuleButton->setColour(0x1000102 ,Colours::black);
610                        IsItOnList=true;
611                        }
612                }
613
614
615        if(IsItOnList==false)
616        {
617        AddToLog("New Module called " + name +" has been found \n",1);
618        TotalModules++;
619        SeenModules.push_front (new TextButton (String::empty));
620        SeenModules.front()->setButtonText (name);
621        SeenModules.front()->setRadioGroupId(TotalModules);
622        MainComponent::Updatemodules();
623        ModParent1->addItem(name,menucount);
624        ModParent2->addItem(name,menucount);
625        menucount++;
626        }
627        else
628        {
629        AddToLog("Module called " + name +" has been reconnected \n",2);
630       
631        }
632}
633
634
635/*!
636Adds a port to the list and screen also sets its group id to its parent module
637
638!*/
639void MainComponent::AddPort(String Parent,String name)
640{
641bool IsItOnList=false;
642static int menucount2=1;
643
644        for ( itTextButton2=SeenModules.begin() ; itTextButton2 != SeenModules.end(); itTextButton2++ ) // go through pos parents
645                {
646                TempModuleButton = *itTextButton2;
647                if(TempModuleButton->getButtonText()==Parent) // if it is parent
648                        {
649                for ( itTextButton=SeenPorts.begin() ; itTextButton != SeenPorts.end(); itTextButton++ ) // check that child isn't on list
650                                {
651                                TempModuleButton2 = *itTextButton;
652                                // it its name is on the list and the list name has the same parent then its already been addid
653                                if(TempModuleButton2->getButtonText()==name && TempModuleButton2->getRadioGroupId() == TempModuleButton->getRadioGroupId())
654                                        {
655                                        IsItOnList=true;
656                                        }
657                                }
658
659                        if(IsItOnList==false)
660                        {
661                        SeenPorts.push_front (new TextButton (String::empty));
662                        SeenPorts.front()->setButtonText (name);
663                        AddToLog("Found port " + name + " child of " + Parent + " \n",1);
664                        SeenPorts.front()->setRadioGroupId(TempModuleButton->getRadioGroupId());
665                        ModChild1->addItem(name,menucount2);
666                        ModChild2->addItem(name,menucount2);
667                        menucount2++;
668                        }
669                        else
670                        {
671                        AddToLog("Found port " + name + " child of " + Parent + " has been reconnected \n",1);
672                        }
673
674                        }
675                }
676MainComponent::Updatemodules();
677
678}
679/*!
680
681This function is used to display the modules and ports in a nice circuler pattern
682needs to have some work done so it resizes a little better
683
684!*/
685void MainComponent::Updatemodules(void)
686{
687double count =0, count2 =0;
688int size;
689size =SeenModules.size();
690double radias;
691double some;
692int x ;
693int y ;
694
695
696
697sizeofball=definedsizeofball;
698if(size>25){sizeofball=(25*definedsizeofball)/size;}
699
700for ( itTextButton=SeenModules.begin() ; itTextButton != SeenModules.end(); itTextButton++ )
701        {
702        if(size>6){radias = ((sizeofball/2)*size)/Pi;}
703        else      {radias = sizeofball;}
704
705        some=6.28318531/size;   
706        x = radias*(cos((some)*count));   
707        y = radias*(sin((some)*count));   
708
709        /// this is the module button this works ok
710        /// basicly it puts all modules in a circle, when theres many modules it increases the radias
711        /// and if need be decreases the size of the buttons
712        TempModuleButton = *itTextButton;
713        addAndMakeVisible (TempModuleButton);
714        TempModuleButton->setBounds(345+x-(sizeofball/2),297+y-(sizeofball/2),sizeofball,sizeofball);
715        TempModuleButton->addButtonListener (this);
716
717        // for the ports.
718        for ( itTextButton2=SeenPorts.begin() ; itTextButton2 != SeenPorts.end(); itTextButton2++ )
719                {
720                TempPortButton = *itTextButton2;
721                if(TempPortButton->getRadioGroupId()==TempModuleButton->getRadioGroupId())
722                        {
723                        addAndMakeVisible (TempPortButton);
724                        double Angle = atan2(double(y),double(x));  // get the angle
725                        int x2 = (sizeofball*0.075)+((sizeofball*0.85)*(count2+1.1))*(cos(Angle));   
726                        int y2 = (sizeofball*0.075)+((sizeofball*0.85)*(count2+1.1))*(sin(Angle)); 
727                        x2=x2+TempModuleButton->getX();
728                        y2=y2+TempModuleButton->getY();
729                        TempPortButton->setBounds(x2,y2,sizeofball*0.85,sizeofball*0.85);
730                        TempPortButton->addButtonListener (this);
731                        count2++;
732                        }
733                else
734                        {
735                        count2=0;
736                        }
737                }
738        count++;
739        }
740
741if(MyMode==RunMode || AllConnections.size()>0)
742{
743RefreashConnections();
744return;
745}
746}
747
748/*
749RefreashConnections
750Used to create the network profile by figuring out what modules go where and then drawing lines
751from port to port to show how there interconnected, need to change connections from a array of
752strings to a list of objects, so they can be added easerly by other methods for starting creations
753*/
754
755void MainComponent::RefreashConnections(void)
756{
757        static int HaveIDoneThisBefore=0;
758    list<connections>::iterator it2;
759
760
761int mylittlecount=0;
762/// puts everything top left to begin with
763for ( itTextButton=SeenModules.begin() ; itTextButton != SeenModules.end(); itTextButton++ )
764        {
765                TempModuleButton = *itTextButton;
766                TempModuleButton->setTopLeftPosition(20,20); 
767        }
768/// puts the modules across and down, if a child is found then it goes right and down, else it just goes down and
769/// if it hits anouther module it pushes that one down
770for(int ii=0;ii<10;ii++)
771{
772for ( itTextButton=SeenModules.begin() ; itTextButton != SeenModules.end(); itTextButton++ )
773        {
774        for ( itTextButton2=SeenModules.begin() ; itTextButton2 != SeenModules.end(); itTextButton2++ )
775                {
776                        TempModuleButton = *itTextButton;
777                        TempModuleButton2 = *itTextButton2;
778
779                for ( it2=AllConnections.begin() ; it2 != AllConnections.end(); it2++ )
780                        {
781                        connections mytempconect = *it2;
782                        /// if there connected move it down and right
783                        if(mytempconect.Daddyfirstport == TempModuleButton->getButtonText() && mytempconect.Daddysecoundport==TempModuleButton2->getButtonText())
784                                {
785                                TempModuleButton2->setTopLeftPosition(TempModuleButton->getX()+30,TempModuleButton->getY()+60);//woz 60
786                                }
787                        }
788                        // if not connected just move it down
789                for ( itTextButton3=SeenModules.begin() ; itTextButton3 != SeenModules.end(); itTextButton3++ )
790                        {
791                        TempModuleButton3 = *itTextButton3;
792                        if(TempModuleButton3->getY()==TempModuleButton2->getY()&&TempModuleButton2!=TempModuleButton3)
793                                {
794                                TempModuleButton3->setTopLeftPosition(TempModuleButton3->getX(),TempModuleButton3->getY()+60);//woz 60
795                                }
796                        }
797                }
798        }
799// puts the ports next to the modules
800MainComponent::SortPorts();
801}
802
803/// this bit just puts in the line in from port to port
804for ( itTextButton=SeenPorts.begin() ; itTextButton != SeenPorts.end(); itTextButton++ )
805        {
806        for ( itTextButton2=SeenPorts.begin() ; itTextButton2 != SeenPorts.end(); itTextButton2++ )
807                {
808                        TempModuleButton = *itTextButton;
809                        TempModuleButton2 = *itTextButton2;
810               
811                for ( it2=AllConnections.begin() ; it2 != AllConnections.end(); it2++ )
812                        {
813                connections mytempconect = *it2;
814
815                        if(mytempconect.firstport == TempModuleButton->getButtonText() && mytempconect.secoundport==TempModuleButton2->getButtonText())
816                                {
817                               
818                        //      if(TempModuleButton->getY()>TempModuleButton2->getY())
819                        //              {
820                                        mytempconect.MyPath.clear();
821                                        mytempconect.MyPath.startNewSubPath (float(TempModuleButton->getX()+(sizeofball*0.425)),float(TempModuleButton->getY()-2+(sizeofball*0.85)));// top left
822                                        mytempconect.MyPath.lineTo (float(TempModuleButton2->getX()+(sizeofball*0.425)), float(TempModuleButton2->getY()+2));// bottem left
823                                        mytempconect.MyPath.closeSubPath();
824                                        *it2 = mytempconect;
825                        //              }
826                        //      else
827                        //              {
828                        //              AddToLog("adding path 2 \n",1);
829                        //              mytempconect.MyPath.clear();
830                        //              mytempconect.MyPath.startNewSubPath (float(TempModuleButton->getX()+(sizeofball*0.425)),float(TempModuleButton->getY()-2+(sizeofball*0.85)));// top left
831                        //              mytempconect.MyPath.lineTo (float(TempModuleButton2->getX()+(sizeofball*0.425)), float(TempModuleButton2->getY()+2));// bottem left
832                        //              mytempconect.MyPath.closeSubPath();
833                        //              }
834                                }
835                        }
836                }
837        }
838// bug in the system that unless the windows forced to redraw everything then not all lines are seen
839// changed this by everytime changing the main window size a little.
840if(HaveIDoneThisBefore==0)      {centreWithSize (getWidth()+1, getHeight());HaveIDoneThisBefore=1;}
841else                                            {centreWithSize (getWidth()-1, getHeight());HaveIDoneThisBefore=0;}
842}
843/*!
844This just puts the ports in the right order next to the modules used by refreash connections
845 !*/
846void MainComponent::SortPorts(void)
847{
848int counter=0;
849for ( itTextButton=SeenModules.begin() ; itTextButton != SeenModules.end(); itTextButton++ )
850        {
851                counter=0;
852                TempModuleButton = *itTextButton;
853                TempModuleButton->setConnectedEdges(Button::ConnectedOnRight);
854        for ( itTextButton2=SeenPorts.begin() ; itTextButton2 != SeenPorts.end(); itTextButton2++ )
855                {
856               
857                TempPortButton   = *itTextButton2;
858                TempPortButton->setConnectedEdges(Button::ConnectedOnRight|Button::ConnectedOnLeft);
859                if(TempModuleButton->getRadioGroupId()==TempPortButton->getRadioGroupId())
860                        {
861                        TempPortButton->setTopLeftPosition(TempModuleButton->getX()+((sizeofball*0.85)*counter)+sizeofball,TempModuleButton->getY());
862                        counter++;
863                        }
864                }       
865        }
866}
867
868/*!
869adds data to the log, makes sure that if button is pressed it doesn't print data they dont want
870!*/
871
872void MainComponent::AddToLog(const String VV, int priority)
873{
874if(WhatShownDebug[priority]==1)
875        {
876        switch (priority)
877                {
878        case 0: MytextEditor->setColour(TextEditor::textColourId,Colours::black);       break; // normal debug stuff
879        case 1: MytextEditor->setColour(TextEditor::textColourId,Colours::blue);        break; // SAMGAR only debug
880        case 2: MytextEditor->setColour(TextEditor::textColourId,Colours::darkred);     break; // SAMGAR Crit Level 1
881        case 3: MytextEditor->setColour(TextEditor::textColourId,Colours::red);         break; // normal CRIT Level 2
882                }
883        MytextEditor->insertTextAtCursor(VV);
884        }
885}
886/*!
887this bit actully does all the drawing for the whole program for lines and stuff like that
888mainly used for drawing the lines
889!*/
890
891void MainComponent::paint (Graphics& g)
892{
893        // main box on left
894        g.fillAll (Colour (0xff8f9ef6)); // background color
895        g.setColour (Colour (0xffbdc5f7)); // color inside path
896    g.fillPath (internalPath1);
897        g.setColour (Colour (0xff5f74f1)); // line color
898    g.strokePath (internalPath1, PathStrokeType (5.2000f));
899
900
901//      g.fillAll (Colour (0xff8f9ef6)); // background color
902        g.setColour (Colour (0xffbdc5f7)); // color inside path
903   g.fillPath (internalPath4);
904        g.setColour (Colour (0xff5f74f1)); // line color
905    g.strokePath (internalPath4, PathStrokeType (5.2000f));
906
907        // button box on right
908        g.setColour (Colour (0xffbdc5f7)); // color inside path
909        g.fillPath (internalPath2);
910        g.setColour (Colour (0xff5f74f1)); // line color
911    g.strokePath (internalPath2, PathStrokeType (5.2000f));
912
913
914        list<connections>::iterator it2;
915        connections temmp;
916        g.setColour (Colours::grey);
917
918for ( it2=AllConnections.begin() ; it2 != AllConnections.end(); it2++ )
919        {
920    temmp=*it2;
921        if(temmp.IsConnected==true)     {g.setColour (Colours::blue);}
922        else                                            {g.setColour (Colours::grey);}
923        g.strokePath (temmp.MyPath, PathStrokeType (5.2000f));
924        }
925
926}
927
928/*
929this bit is called when the window resizes, should be altered to allow better scaling of all buttons etc when resized
930*/
931
932void MainComponent::resized()
933{
934        // little connection box on right
935    internalPath4.clear();
936    internalPath4.startNewSubPath (890.0f, 470.0f);
937    internalPath4.lineTo (890.0f + 300, 470.0f);
938        internalPath4.lineTo (890.0f + 300, 590.0f );
939        internalPath4.lineTo (890.0f , 590.0f);
940        internalPath4.lineTo (890.0f , 470.0f);
941        internalPath4.closeSubPath();
942
943        // main box on left     
944    internalPath1.clear();
945    internalPath1.startNewSubPath (10.0f, 10.0f);
946    internalPath1.lineTo (700.0f, 10.0f);
947    internalPath1.lineTo (700.0f, 590.0f);
948        internalPath1.lineTo (10.0f, 590.0f);
949    internalPath1.lineTo (10.0f, 10.0f);
950    internalPath1.closeSubPath();
951
952
953        internalPath2.clear();
954    internalPath2.startNewSubPath (720.0f, 10.0f);// top left
955    internalPath2.lineTo (910.0f-50, 10.0f);// top right
956    internalPath2.lineTo (910.0f-50, 590.0f); // bottem right
957        internalPath2.lineTo (720.0f, 590.0f); //
958    internalPath2.lineTo (720.0f, 10.0f);
959    internalPath2.closeSubPath();
960
961}
962
963/*!
964Interupt when any button is clicked
965!*/
966
967void MainComponent::buttonClicked (Button* buttonThatWasClicked)
968{
969String tempnames[10];
970  Bottle& cc = ThePortForModules.prepare();
971  cc.clear();
972
973  if (buttonThatWasClicked == StopButton)
974  {
975        cc.addInt(0);
976        ThePortForModules.write();
977  }
978
979  if (buttonThatWasClicked == StartButton)
980  {
981        cc.addInt(1);
982        ThePortForModules.write();
983  }
984 
985  if (buttonThatWasClicked == MigrateButton)
986  {
987        if(NameOfServer == "/Red"){Migrate("Blue");}
988        if(NameOfServer == "/Blue"){Migrate("Red");}
989  }
990
991
992
993   if (buttonThatWasClicked == RefreshConnect)
994    {
995      MainComponent::RefreashConnections();
996          MyMode=RunMode;
997    }
998    if (buttonThatWasClicked == quitButton)
999    {
1000      JUCEApplication::quit();
1001    }
1002if (buttonThatWasClicked == DebugButton1)
1003    {
1004                switch(WhatShownDebug[0])
1005                {
1006                case 0:
1007                        WhatShownDebug[0]=1;
1008                        DebugButton1->setButtonText (T("debug priority 1 on"));
1009                break;
1010                case 1:
1011                        WhatShownDebug[0]=0;
1012                        DebugButton1->setButtonText (T("debug priority 1 off"));
1013                break;
1014                }
1015    }
1016if (buttonThatWasClicked == DebugButton2)
1017    {
1018                switch(WhatShownDebug[1])
1019                {
1020                case 0:
1021                        WhatShownDebug[1]=1;
1022                        DebugButton2->setButtonText (T("debug priority 2 on"));
1023                break;
1024                case 1:
1025                        WhatShownDebug[1]=0;
1026                        DebugButton2->setButtonText (T("debug priority 2 off"));
1027                break;
1028                }
1029    }
1030if (buttonThatWasClicked == DebugButton3)
1031    {
1032                switch(WhatShownDebug[2])
1033                {
1034                case 0:
1035                        WhatShownDebug[2]=1;
1036                        DebugButton3->setButtonText (T("debug priority 3 on"));
1037                break;
1038                case 1:
1039                        WhatShownDebug[2]=0;
1040                        DebugButton3->setButtonText (T("debug priority 3 off"));
1041                break;
1042                }
1043    }
1044if (buttonThatWasClicked == DebugButton4)
1045    {
1046                switch(WhatShownDebug[3])
1047                {
1048                case 0:
1049                        WhatShownDebug[3]=1;
1050                        DebugButton4->setButtonText (T("debug priority 4 on"));
1051                break;
1052                case 1:
1053                        WhatShownDebug[3]=0;
1054                        DebugButton4->setButtonText (T("debug priority 4 off"));
1055                break;
1056                }
1057    }
1058
1059if (buttonThatWasClicked == ClearLog)
1060    {
1061                MytextEditor->clear();
1062                MainComponent::AddToLog("Log has been cleared \n", 1);
1063        }
1064
1065//      TextButton* SaveMod;
1066//  TextButton* LoadMod;
1067//      TextButton* SaveCon;
1068//  TextButton* LoadCon;
1069
1070if (buttonThatWasClicked == LoadCon)
1071    {
1072                connections mytempconnect;
1073        FileChooser chooser6 ("Please select log you wish to load...",File::getSpecialLocation (File::userHomeDirectory),"*.SamCon");
1074        if (chooser6.browseForFileToOpen ())
1075                {
1076                myFileforCon = chooser6.getResult ();
1077                FileInputStream *hello= myFileforCon.createInputStream();
1078
1079                String Tempy = " hello ";
1080
1081                while(Tempy.length()>0)
1082                {
1083                Tempy=hello->readNextLine();
1084                mytempconnect.Daddyfirstport = Tempy;
1085                mytempconnect.firstport=hello->readNextLine();
1086                mytempconnect.Daddysecoundport=hello->readNextLine();
1087                mytempconnect.secoundport=hello->readNextLine();
1088                mytempconnect.Lossy=hello->readNextLine();
1089                mytempconnect.Network=hello->readNextLine();
1090                AllConnections.push_front(mytempconnect);
1091                }
1092                }
1093        }
1094
1095if (buttonThatWasClicked == SaveCon)
1096    {
1097                list<connections>::iterator itter;
1098                connections mytempconnect;
1099
1100    FileChooser chooser5 ("Please select the save name...",File::getSpecialLocation (File::userHomeDirectory),"*.SamCon");
1101        if (chooser5.browseForFileToSave (true))
1102                {
1103                myFileforCon = chooser5.getResult ();
1104                if (myFileforCon.existsAsFile ()){myFileforCon.deleteFile ();}
1105
1106                        myFileforCon.create ();
1107
1108                for ( itter=AllConnections.begin() ; itter != AllConnections.end(); itter++ )
1109                        {
1110                        mytempconnect = *itter;
1111                        myFileforCon.appendText(mytempconnect.Daddyfirstport + "\n");
1112                        myFileforCon.appendText(mytempconnect.firstport + "\n");
1113                        myFileforCon.appendText(mytempconnect.Daddysecoundport + "\n");
1114                        myFileforCon.appendText(mytempconnect.secoundport + "\n");
1115                        myFileforCon.appendText(mytempconnect.Lossy + "\n");
1116                        myFileforCon.appendText(mytempconnect.Network + "\n");
1117                        }
1118                }
1119        }
1120
1121if (buttonThatWasClicked == SaveMod)
1122    {
1123    FileChooser chooser3 ("Please select the save name...",File::getSpecialLocation (File::userHomeDirectory),"*.SamMod");
1124        if (chooser3.browseForFileToSave (true))
1125                {
1126                myFileforMod = chooser3.getResult ();
1127                if (myFileforMod.existsAsFile ()){myFileforLog.deleteFile ();}
1128
1129                        myFileforMod.create ();
1130                for ( itTextButton=SeenModules.begin() ; itTextButton != SeenModules.end(); itTextButton++ )
1131                        {
1132                        TempModuleButton = *itTextButton;
1133                        String SaveName = TempModuleButton->getButtonText() + "\n";
1134                        myFileforMod.appendText(SaveName);
1135                        }
1136                }
1137        }
1138if (buttonThatWasClicked == LoadMod)
1139    {
1140        FileChooser chooser4 ("Please select log you wish to load...",File::getSpecialLocation (File::userHomeDirectory),"*.SamLog");
1141        if (chooser4.browseForFileToOpen ())
1142                {
1143                myFileforMod = chooser4.getResult ();
1144                FileInputStream *hello= myFileforMod.createInputStream();
1145
1146                String Tempy = " hello ";
1147
1148                while(Tempy.length()>0)
1149                {
1150                        Tempy=hello->readNextLine();
1151                        if(Tempy.length()>0){AddModule(Tempy);}
1152                }
1153                }
1154        }
1155
1156if (buttonThatWasClicked == SaveLog)
1157    {
1158    FileChooser chooser2 ("Please select the save name...",File::getSpecialLocation (File::userHomeDirectory),"*.SamLog");
1159        if (chooser2.browseForFileToSave (true))
1160                {
1161                myFileforLog = chooser2.getResult ();
1162                if (myFileforLog.existsAsFile ()){myFileforLog.deleteFile ();}
1163
1164                        myFileforLog.create ();
1165                        myFileforLog.appendText (MytextEditor->getText ());
1166                }
1167        }
1168if (buttonThatWasClicked == OpenLogButton)
1169    {
1170        FileChooser chooser ("Please select log you wish to load...",File::getSpecialLocation (File::userHomeDirectory),"*.SamLog");
1171        if (chooser.browseForFileToOpen ())
1172                {
1173                myFileforLog = chooser.getResult ();
1174                MytextEditor->setText (myFileforLog.loadFileAsString());
1175                }
1176        }
1177
1178
1179if (buttonThatWasClicked == ConnectionStuff)
1180    {
1181                int abort = 0;
1182                if( ModParent1->getText() == String("Parent 1"))                 {abort = 1;}
1183                if( ModParent2->getText() == String("Parent 2"))                 {abort = 1;}
1184                if( ModChild1->getText()  == String("Child 1"))                  {abort = 1;}
1185                if( ModChild2->getText()  == String("Child 2"))                  {abort = 1;}
1186                if( Connect->getText()    == String("Connect/Disconnect"))       {abort = 1;}
1187                if( NetworkBox->getText() == String("Network Type"))     {abort = 1;}
1188
1189                if(abort==1){AddToLog("not all choices have been selected for connection", 1);}
1190                else
1191                {
1192                        if(Connect->getText() == String("Connect"))
1193                        {
1194                        AddConnection(ModParent1->getText(),ModChild1->getText(),ModParent2->getText(),ModChild2->getText(),Connect->getText(),NetworkBox->getText());
1195                        }
1196                        if(Connect->getText() == String("Disconnect"))
1197                        {
1198                        DelConnection(ModParent1->getText(),ModChild1->getText(),ModParent2->getText(),ModChild2->getText(),Connect->getText(),NetworkBox->getText());
1199                        }
1200                ModParent1->setText("Parent 1");
1201                ModParent2->setText("Parent 2") ;
1202                ModChild1->setText("Child 1");
1203                ModChild2->setText("Child 2");
1204                Connect->setText("Connect/Disconnect");
1205                NetworkBox->setText("Network Type");
1206                }
1207        }
1208
1209}
1210
1211
1212//==============================================================================
1213/*!
1214This function gets called by the connect button to add a new connection to the list
1215!*/
1216void MainComponent::AddConnection(String parent1,String child1,String parent2, String child2,String Lossyornot,String Network)
1217{
1218        static int county =0;
1219connections temp;
1220temp.Daddyfirstport=parent1;
1221temp.firstport=child1;
1222temp.Daddysecoundport=parent2;
1223temp.secoundport=child2;
1224temp.Lossy=Lossyornot;
1225temp.Network=Network;
1226AllConnections.push_front(temp);
1227}
1228
1229/*!
1230This function gets called by the connect button to deleate a new connection to the list
1231!*/
1232void MainComponent::DelConnection(String parent1,String child1,String parent2, String child2,String Lossyornot,String Network)
1233{
1234connections mytempconnect;
1235list<connections>::iterator it2;
1236list<connections>::iterator SavedIt;
1237bool killcon;
1238int x =0;
1239
1240        killcon = false;
1241        for ( it2=AllConnections.begin() ; it2 != AllConnections.end(); it2++ )
1242        {
1243        mytempconnect = *it2;
1244        x=0;
1245
1246        string tempstring10 = mytempconnect.firstport;
1247        string tempstring20 = mytempconnect.secoundport;
1248        tempstring10=tempstring10.substr(1,tempstring10.length()-1);
1249        tempstring20=tempstring20.substr(1,tempstring20.length()-1);
1250
1251        if(mytempconnect.Daddyfirstport == parent1){x++;}
1252        if(mytempconnect.Daddysecoundport == parent2){x++;}
1253        if(mytempconnect.firstport == child1){x++;}
1254        if(mytempconnect.secoundport == child2){x++;}
1255        if(x>=4)
1256        {
1257                SavedIt = it2;
1258                killcon = true;
1259        //      it2 = AllConnections.erase (it2);   AddToLog("erased connection \n",1); }
1260        }
1261        }
1262        if(killcon == true)
1263        {
1264        SavedIt = AllConnections.erase (SavedIt);
1265
1266                string tempstring10 = mytempconnect.firstport;
1267                string tempstring20 = mytempconnect.secoundport;
1268                tempstring10=tempstring10.substr(1,tempstring10.length()-1);
1269                tempstring20=tempstring20.substr(1,tempstring20.length()-1);
1270
1271                string firststring = "/Port_"   + mytempconnect.Daddyfirstport + "_"  + tempstring10.c_str();
1272                string secoundstring = "/Port_" + mytempconnect.Daddysecoundport + "_" + tempstring20.c_str();
1273
1274         Network::disconnect(firststring.c_str(),secoundstring.c_str());
1275         Network::disconnect(secoundstring.c_str(),firststring.c_str());
1276RefreashConnections();
1277
1278        AddToLog("erased connection \n",1);
1279        }
1280}
1281
1282
Note: See TracBrowser for help on using the repository browser.