Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

editconnection.cpp

Go to the documentation of this file.
00001 #include <opie2/odebug.h>
00002 #include <qlistview.h>
00003 #include <qwidgetstack.h>
00004 #include <qframe.h>
00005 #include <qcombobox.h>
00006 #include <qtabwidget.h>
00007 #include <qmessagebox.h>
00008 #include <qpushbutton.h>
00009 #include <qlineedit.h>
00010 #include <qheader.h>
00011 #include <qpainter.h>
00012 #include <qcheckbox.h>
00013 #include <qlabel.h>
00014 
00015 #include "editconnection.h"
00016 #include "resources.h"
00017 #include "netnode.h"
00018 
00019 //
00020 //
00021 // THESE TO GIVE BETTER FEEDBACK ABOUT DISABLED ITEMS
00022 //
00023 //
00024 
00025 class MyQCheckListItem : public QCheckListItem
00026 {
00027 public:
00028     MyQCheckListItem( QListView *parent, const QString & S, Type T ) :
00029       QCheckListItem( parent, S, T ) { }
00030     MyQCheckListItem( QCheckListItem *parent, const QString & S, Type T ) :
00031       QCheckListItem( parent, S, T ) { }
00032     MyQCheckListItem( QListViewItem *parent, const QString & S, Type T ) :
00033       QCheckListItem( parent, S, T ) { }
00034 
00035     MyQCheckListItem( QListView *parent, const QString & S ) :
00036       QCheckListItem( parent, S, QCheckListItem::Controller ) { }
00037     MyQCheckListItem( QCheckListItem *parent, const QString & S ) :
00038       QCheckListItem( parent, S, QCheckListItem::Controller ) { }
00039     MyQCheckListItem( QListViewItem *parent, const QString & S ) :
00040       QCheckListItem( parent, S, QCheckListItem::Controller ) { }
00041 
00042     virtual void paintCell( QPainter *p, const QColorGroup &cg,
00043                             int column, int width, int alignment );
00044 
00045 };
00046 
00047 void MyQCheckListItem::paintCell( QPainter *p, const QColorGroup &cg,
00048                                  int column, int width, int alignment )
00049 {
00050     QColorGroup _cg( cg );
00051     QColor c = _cg.text();
00052     if ( ! isSelectable() )
00053         _cg.setColor( QColorGroup::Text, Qt::lightGray );
00054     QCheckListItem::paintCell( p, _cg, column, width, alignment );
00055     _cg.setColor( QColorGroup::Text, c );
00056 }
00057 
00058 class MyQListViewItem : public QListViewItem
00059 {
00060 public:
00061     MyQListViewItem( QListView *parent, const QString & S ) :
00062       QListViewItem( parent, S ) { }
00063     MyQListViewItem( QListViewItem *parent, const QString & S ) :
00064       QListViewItem( parent, S ) { }
00065 
00066     virtual void paintCell( QPainter *p, const QColorGroup &cg,
00067                             int column, int width, int alignment );
00068 
00069 };
00070 
00071 void MyQListViewItem::paintCell( QPainter *p, const QColorGroup &cg,
00072                                  int column, int width, int alignment )
00073 {
00074     QColorGroup _cg( cg );
00075     QColor c = _cg.text();
00076     if ( ! isSelectable() )
00077         _cg.setColor( QColorGroup::Text, Qt::lightGray );
00078     QListViewItem::paintCell( p, _cg, column, width, alignment );
00079     _cg.setColor( QColorGroup::Text, c );
00080 }
00081 
00082 //
00083 //
00084 // REAL GUI
00085 //
00086 //
00087 
00088 bool EditNetworkSetup::AutoCollapse = 1;
00089 
00090 EditNetworkSetup::EditNetworkSetup( QWidget* parent ) :
00091       EditNetworkSetupGUI( parent, 0, TRUE ), TmpCollection() {
00092 
00093       Tab_TB->setTabEnabled( Setup_FRM, FALSE );
00094       Setup_FRM->setEnabled( FALSE );
00095 
00096       TmpIsValid = 0;
00097       SelectedNodes = 0;
00098 
00099       AutoCollapse_CB->setChecked( AutoCollapse );
00100 
00101       Mapping = new QPtrDict<ANetNode>;
00102       Mapping->setAutoDelete( FALSE );
00103       Nodes_LV->header()->hide();
00104       // popluate tree with all NetNodes 
00105       buildFullTree();
00106 }
00107 
00108 NetworkSetup * EditNetworkSetup::getTmpCollection( void ) {
00109 
00110       if( TmpIsValid ) 
00111         // content is stil OK
00112         return &(TmpCollection);
00113 
00114       // reset collection -> delete all NEW NetNodes
00115       for( QListIterator<ANetNodeInstance> it(TmpCollection);
00116            it.current();
00117            ++it ) {
00118         if( it.current()->isNew() ) {
00119           delete it.current();
00120         }
00121       }
00122 
00123       TmpCollection.clear();
00124       if( SelectedNodes ) {
00125         // initialize like original
00126         TmpCollection.copyFrom( *SelectedNodes );
00127       }
00128 
00129       // update content
00130       QListViewItem * it = Nodes_LV->firstChild();
00131       ANetNode * NN;
00132 
00133       // start iter (if there is a collection)
00134       /*
00135 
00136           a node collection is sorted from the toplevel
00137           node to the deepest node
00138 
00139       */
00140       ANetNodeInstance * NNI = 
00141         (SelectedNodes) ? SelectedNodes->first() : 0 ;
00142 
00143       TmpCollection.setModified( 0 );
00144 
00145       // the listview always starts with the toplevel 
00146       // hierarchy.  This is always a controller item
00147       while ( it ) {
00148         NN = (*Mapping)[it];
00149         if( NN == 0 ) {
00150           // this item is a controller -> 
00151           // has radio items as children -> 
00152           // find selected one 
00153           it = it->firstChild();
00154           while( it ) {
00155             if( ((QCheckListItem *)it)->isOn() ) {
00156               // this radio is selected -> go deeper
00157               break;
00158             }
00159             it = it->nextSibling();
00160           }
00161 
00162           if( ! it ) {
00163             TmpIsValid = 0;
00164             return 0;
00165           }
00166 
00167           // it now contains selected radio
00168           NN = (*Mapping)[it];
00169         }
00170 
00171         // NN here contains the netnode of the
00172         // current item -> this node needs to
00173         // be stored in the collection
00174         if( NNI == 0 ||
00175             it->text(0) != NNI->nodeClass()->name() ) {
00176           // new item not in previous collection
00177           ANetNodeInstance * NNI = NN->createInstance();
00178           NNI->initialize();
00179           // this node type not in collection
00180           TmpCollection.append( NNI );
00181           // master collection changed because new item in it
00182           TmpCollection.setModified( 1 );
00183           // no more valid items in old list
00184           NNI = 0;
00185         } else {
00186           // already in list -> copy pointer
00187           TmpCollection.append( NNI );
00188           NNI = SelectedNodes->next();
00189         }
00190 
00191         // go deeper to next level
00192         // this level is can be a new controller
00193         // or an item
00194         it = it->firstChild();
00195       }
00196 
00197       TmpIsValid = 1;
00198       return &(TmpCollection);
00199 }
00200 
00201 // pass a NetworkSetup NetworkSetup to be edited
00202 void EditNetworkSetup::setNetworkSetup( NetworkSetup * NC ) {
00203       ANetNodeInstance * NNI;
00204       ANetNode * NN;
00205 
00206       SelectedNodes = NC;
00207       Name_LE->setText( NC->name() );
00208       NNI = NC->first();
00209 
00210       // show configure tabl
00211       Tab_TB->setCurrentPage( 1 );
00212 
00213       // valid colledction
00214       Tab_TB->setTabEnabled( Setup_FRM, FALSE );
00215       Setup_FRM->setEnabled( FALSE );
00216 
00217       // select items in collection
00218       QListViewItem * it = Nodes_LV->firstChild();
00219       bool Found;
00220 
00221       TmpIsValid = 0;
00222 
00223       while ( it ) {
00224         NN = (*Mapping)[it];
00225         if( NN == 0 ) {
00226           // this item is a controller -> 
00227           // has radio items as children -> 
00228           // find selected one 
00229           it = it->firstChild();
00230           Found = 0;
00231           while( it ) {
00232             if( NNI && it->text(0) == NNI->nodeClass()->name() ) {
00233               // this radio is part of the collection
00234               ((QCheckListItem *)it)->setOn( 1 );
00235               updateGUI( it, NNI->nodeClass() );
00236               // check its children
00237               Found = 1;
00238               it = it->firstChild();
00239               NNI = SelectedNodes->next();
00240               // do not bother to check other items
00241               break;
00242             }
00243             it = it->nextSibling();
00244           }
00245 
00246           if( ! Found ) {
00247             // this means that this level is NOT present in collection
00248             // probably INCOMPATIBEL collection OR Missing plugin
00249             QMessageBox::warning(
00250                 0, 
00251                 tr( "Error presentig NetworkSetup" ),
00252                 tr( "<p>Old NetworkSetup or missing plugin \"<i>%1</i>\"</p>" ).
00253                     arg(NNI->nodeClass()->name()) );
00254             return;
00255           }
00256 
00257           // it now contains selected radio
00258           NN = (*Mapping)[it];
00259         } else {
00260           // automatic selection 
00261           if( NNI == 0 ||  it->text(0) != NNI->nodeClass()->name() ) {
00262             // should exist and be the same
00263             if( NNI ) {
00264               QMessageBox::warning(
00265                   0, 
00266                   tr( "Error presentig NetworkSetup" ),
00267                   tr( "<p>Old NetworkSetup or missing plugin \"<i>%1</i>\"</p>" ).
00268                       arg(NNI->nodeClass()->name()) );
00269             } else {
00270               QMessageBox::warning(
00271                   0, 
00272                   tr( "Error presentig NetworkSetup" ),
00273                   tr( "<p>Missing NetworkSetup\"<i>%1</i>\"</p>" ).
00274                       arg(it->text(0)) );
00275             }
00276             return;
00277           }
00278           it = it->firstChild();
00279         }
00280       }
00281 }
00282 
00283 // get result of editing (either new OR updated collection
00284 NetworkSetup * EditNetworkSetup::networkSetup( void ) {
00285 
00286       if( SelectedNodes == 0 ) {
00287         // new collection 
00288         SelectedNodes = new NetworkSetup;
00289       }
00290 
00291       // clean out old entries
00292       SelectedNodes->clear();
00293 
00294       // transfer 
00295       for( QListIterator<ANetNodeInstance> it(TmpCollection);
00296            it.current();
00297            ++it ) {
00298         SelectedNodes->append( it.current() );
00299       }
00300 
00301       if( TmpCollection.isModified() )
00302         SelectedNodes->setModified( 1 );
00303 
00304       if( SelectedNodes->name() != Name_LE->text() ) {
00305         SelectedNodes->setName( Name_LE->text() );
00306         SelectedNodes->setModified( 1 );
00307       }
00308 
00309       return SelectedNodes;
00310 }
00311 
00312 // Build device tree -> start 
00313 void EditNetworkSetup::buildFullTree( void ) {
00314     ANetNode * NN;
00315 
00316     // toplevel item
00317     MyQCheckListItem * TheTop = new MyQCheckListItem( 
00318         Nodes_LV, 
00319         NSResources->netNode2Name("fullsetup"),
00320         QCheckListItem::Controller );
00321     TheTop->setOpen( TRUE );
00322     Description_LBL->setText( 
00323           NSResources->netNode2Description( "fullsetup" ) );
00324     Nodes_LV->setSelected( TheTop, TRUE );
00325 
00326     // find all Nodes that are toplevel nodes -> ie provide
00327     // TCP/IP NetworkSetup
00328     for( QDictIterator<ANetNode> Iter(NSResources->netNodes());
00329          Iter.current();
00330          ++Iter ) {
00331       NN = Iter.current();
00332 
00333       if( ! NN->isToplevel() ) {
00334         continue;
00335       }
00336 
00337       MyQCheckListItem * it = new MyQCheckListItem( TheTop, 
00338           NN->name(), 
00339           QCheckListItem::RadioButton );
00340       it->setPixmap( 0, 
00341                      NSResources->getPixmap( NN->pixmapName() )
00342                    );
00343       // remember that this node maps to this listitem
00344       Mapping->insert( it, NN );
00345       buildSubTree( it, NN );
00346     }
00347 }
00348 
00349 // Build device tree -> help function 
00350 void EditNetworkSetup::buildSubTree( QListViewItem * it, ANetNode *NN ) {
00351     ANetNode::NetNodeList & NNL = NN->alternatives();
00352 
00353     if( NNL.size() > 1 ) {
00354       // this node has alternatives -> needs radio buttons
00355       it = new MyQCheckListItem( 
00356         it, 
00357         NSResources->netNode2Name(NN->needs()[0]),
00358         QCheckListItem::Controller );
00359       it->setSelectable( FALSE );
00360     }
00361 
00362     for ( unsigned int i=0; i < NNL.size(); i++ ) {
00363       QListViewItem * CI;
00364       if( NNL.size() > 1 ) {
00365         // generate radio buttons
00366         CI = new MyQCheckListItem( 
00367                 (QCheckListItem *)it, 
00368                 NNL[i]->name(), QCheckListItem::RadioButton );
00369         // remember that this node maps to this listitem
00370         CI->setPixmap( 0, NSResources->getPixmap( NNL[i]->pixmapName() ) );
00371         Mapping->insert( CI, NNL[i] );
00372         CI->setSelectable( FALSE );
00373       } else {
00374         // Single item
00375         CI = new MyQListViewItem( it, NNL[i]->name() );
00376         // remember that this node maps to this listitem
00377         Mapping->insert( CI, NNL[i] );
00378         CI->setSelectable( FALSE );
00379         CI->setPixmap( 0, NSResources->getPixmap( NNL[i]->pixmapName() ) );
00380       }
00381       buildSubTree( CI, NNL[i] );
00382     }
00383 }
00384 
00385 // Clicked ok OK button
00386 void EditNetworkSetup::accept( void ) {
00387     if( ! haveCompleteConfig( 0 ) || Name_LE->text().isEmpty() ) {
00388       QMessageBox::warning(
00389           0, 
00390           tr( "Closing NetworkSetup Setup" ),
00391           tr( "Definition not complete or no name" ) );
00392       return;
00393     }
00394 
00395     // check if all devices have acceptable input
00396     getTmpCollection();
00397     { ANetNodeInstance * NNI;
00398       QString S;
00399 
00400       for( QListIterator<ANetNodeInstance> it(TmpCollection);
00401            it.current();
00402            ++it ) {
00403         NNI = it.current();
00404         // widget must show its own problems
00405         S = NNI->acceptable();
00406         if( ! S.isEmpty() ) {
00407           QMessageBox::warning(
00408               0, 
00409               tr( "Cannot save" ),
00410               S );
00411           return;
00412         }
00413         NNI->commit();
00414 
00415         if( NNI->isModified() ) {
00416           TmpCollection.setModified( 1 );
00417           // commit the data
00418         }
00419       }
00420     }
00421 
00422     QDialog::accept();
00423 }
00424 
00425 // triggered by CB
00426 void EditNetworkSetup::SLOT_AutoCollapse( bool b ) {
00427     AutoCollapse = b;
00428 }
00429 
00430 // clicked on node in tree -> update GUI
00431 void EditNetworkSetup::SLOT_SelectNode( QListViewItem * it ) {
00432     ANetNode * NN;
00433     if( it == 0 || it->depth() == 0 ) {
00434       Description_LBL->setText( 
00435           NSResources->netNode2Description( "fullsetup" ) );
00436       // topevel or no selection
00437       return;
00438     }
00439 
00440     // store conversion from lvitem to node
00441     NN = (*Mapping)[ it ];
00442 
00443     if( ! NN ) {
00444       // intermediate (controller) node
00445       NN = (*Mapping)[ it->parent() ];
00446       if( NN ) {
00447         // figure out type of this node -> produce message
00448         Description_LBL->setText( NSResources->netNode2Description(
00449                                   NN->needs()[0]) );
00450       } else {
00451         Description_LBL->setText( "" );
00452       }
00453       return;
00454     }
00455 
00456     // clicked on regular node 
00457     Description_LBL->setText( NN->nodeDescription() );
00458 
00459     if( ! it->isSelectable() ) {
00460       return;
00461     }
00462 
00463     ANetNode::NetNodeList & NNL = NN->alternatives();
00464 
00465     if( NNL.size() == 0 ) {
00466       // this item has no alternatives -> end node
00467       TmpIsValid = 0;
00468       updateGUI( it, NN );
00469       return;
00470     }
00471 
00472     if( ! ((MyQCheckListItem *)it)->isOn() ) {
00473       // not clicked on Check or Radio item
00474       return;
00475     }
00476 
00477     // item has really changed -> update 
00478     TmpIsValid = 0;
00479     updateGUI( it, NN );
00480 }
00481 
00482 // cliecked on TAB to go to setup
00483 void EditNetworkSetup::SLOT_AlterTab( const QString & S ) {
00484     if( S == tr( "Setup" ) && Setup_FRM->isEnabled() ) {
00485       // switched to setup -> update CB and populate ws with
00486       // forms for devices
00487 
00488       if( ! TmpIsValid ) {
00489         getTmpCollection();
00490 
00491         // clear CB and Ws
00492         { QWidget * W;
00493           int i = 0;
00494 
00495           Devices_CB->clear();
00496           while( ( W = Setup_WS->widget( i ) ) ) {
00497             Setup_WS->removeWidget( W );
00498             i ++;
00499           }
00500         }
00501 
00502         // update CB
00503         // and populate WidgetStack
00504         { ANetNodeInstance * NNI;
00505           QListIterator<ANetNodeInstance> it(TmpCollection);
00506           int i = 0;
00507           QWidget * W;
00508 
00509           for ( ; it.current(); ++it ) {
00510             NNI = it.current();
00511             Devices_CB->insertItem(
00512                 NSResources->getPixmap( NNI->nodeClass()->pixmapName() ),
00513                 NNI->nodeClass()->name()
00514             );
00515 
00516             // add edit widget
00517             W = NNI->edit( Setup_WS );
00518             if( ! W) {
00519               W = new QLabel( Setup_WS, 
00520                               tr("No configuration required"));
00521             }
00522             Setup_WS->addWidget( W , i );
00523             i ++;
00524           }
00525         }
00526         Setup_WS->raiseWidget( 0 );
00527       } // still valid
00528     }
00529 }
00530 
00531 // update visual feedback of selection state
00532 void EditNetworkSetup::updateGUI( QListViewItem * it, ANetNode * NN ) {
00533 
00534     bool HCC = haveCompleteConfig( it );
00535     Tab_TB->setTabEnabled( Setup_FRM, HCC );
00536     Log(( "COMPLETE CONFIG %d\n", HCC ));
00537     Setup_FRM->setEnabled( HCC );
00538 
00539     // disable children of all siblings at same level
00540     QListViewItem * Sbl = it->parent()->firstChild();
00541     while( Sbl ) {
00542       if ( Sbl != it ) {
00543         disableTree( Sbl->firstChild(), FALSE );
00544         Sbl->setSelectable( TRUE );
00545         if( AutoCollapse )
00546           Sbl->setOpen( FALSE );
00547       }
00548       Sbl = Sbl->nextSibling();
00549     }
00550 
00551     // enable selected path (as deep as it goes
00552     it->setOpen( TRUE );
00553     enablePath( it->firstChild(), 
00554                 (it->depth()==1) ? 
00555                     1 : // toplevel always alternatives
00556                     (NN->alternatives().size() > 1) );
00557 }
00558 
00559 void EditNetworkSetup::disableTree( QListViewItem * it, bool Mode ) {
00560     while( it ) {
00561       // disable sbl's chidren
00562       it->setSelectable( Mode );
00563       if( AutoCollapse )
00564         it->setOpen( Mode );
00565       disableTree( it->firstChild(), Mode );
00566       it = it->nextSibling();
00567     }
00568 }
00569 
00570 // pah : ParentHasAlternatives
00571 void EditNetworkSetup::enablePath( QListViewItem * it, bool pha ) {
00572     while( it ) {
00573       ANetNode * NN;
00574       NN = (*Mapping)[it];
00575       if( NN ) {
00576         if( pha ) {
00577           bool doOn = ((QCheckListItem *)it)->isOn();
00578           // we are a checklistitem for sure
00579           it->setSelectable( TRUE );
00580           if( AutoCollapse && ! doOn )
00581             it->setOpen( doOn );
00582           if( doOn ) {
00583             // selected alternative
00584             enablePath( it->firstChild(), 
00585                         NN->alternatives().size() > 1);
00586           } else {
00587             // non-selected alternative
00588             disableTree( it->firstChild(), FALSE);
00589           }
00590         } else {
00591           // we are single subitem
00592           it->setSelectable( TRUE );
00593           it->setOpen( TRUE );
00594           enablePath( it->firstChild(),
00595                       NN->alternatives().size() > 1);
00596         }
00597       } else {
00598         // controller node
00599         it->setSelectable( TRUE );
00600         it->setOpen( TRUE );
00601         enablePath( it->firstChild(), pha );
00602       }
00603       it = it->nextSibling();
00604     }
00605 }
00606 
00607 // do we have a complete configuration (all needs are provided for ?)
00608 bool EditNetworkSetup::haveCompleteConfig( QListViewItem * it ) {
00609 
00610     // check if all below this level is selected
00611     it = ( it ) ?it : Nodes_LV->firstChild();
00612     ANetNode *NN;
00613     bool Found;
00614 
00615     while ( it ) {
00616       NN = (*Mapping)[it];
00617       if( NN == 0 ) {
00618         // this item is a controller -> 
00619         // has radio items as children -> 
00620         // find selected one 
00621         it = it->firstChild();
00622         Found = 0;
00623         while( it ) {
00624           if( ((QCheckListItem *)it)->isOn() ) {
00625             Found = 1;
00626             // go deeper
00627             it = it->firstChild();
00628             break;
00629           }
00630           it = it->nextSibling();
00631         }
00632 
00633         if( ! Found ) {
00634           Log(( "Setup not complete\n" ));
00635           return 0; // no not complete -> a radio should have been chkd
00636         }
00637 
00638         // it now contains selected radio
00639         NN = (*Mapping)[it];
00640       } else {
00641         // automatic selection 
00642         it = it->firstChild();
00643       }
00644     }
00645     return 1;
00646 }

Generated on Sat Nov 5 16:17:53 2005 for OPIE by  doxygen 1.4.2