// Connections search combobox -> clicked
void MainWindow::on_connectionsSearchComboBox_currentIndexChanged(int index){
    QString searchString = ui->connectionsSearchField->text();

    // If search criteria is empty, display all
    if(searchString.isEmpty()){
        // Get all machines
        displayConnectionsTable();
        return;
    }

    // Disable delete button
    ui->connectionsDeleteButton->setEnabled(false);

    // Search
    searchConnections(searchString, index);
}
// Check connections search
void MainWindow::checkConnectionsSearch(){
    QString searchString = ui->connectionsSearchField->text();

    // If search criteria is empty, display all
    if(searchString.isEmpty()){
        // Get all machines
        displayConnectionsTable();
        return;
    }

    // What field is selected
    int column = ui->connectionsSearchComboBox->currentIndex();

    // Search
    searchConnections(searchString, column);
}
// Connections search field -> clicked
void MainWindow::on_connectionsSearchField_textChanged(const QString &arg1){
    // If search criteria is empty, display all
    if(arg1.isEmpty()){
        // Get all machines
        displayConnectionsTable();
        return;
    }

    // Disable delete button
    ui->connectionsDeleteButton->setEnabled(false);

    // What field is selected
    int column = ui->connectionsSearchComboBox->currentIndex();

    // Search
    searchConnections(arg1, column);
}
const CN_CONNECTIVITY_ALGO::CLUSTERS CN_CONNECTIVITY_ALGO::SearchClusters( CLUSTER_SEARCH_MODE aMode,
        const KICAD_T aTypes[], int aSingleNet )
{
    bool withinAnyNet = ( aMode != CSM_PROPAGATE );

    std::deque<CN_ITEM*> Q;
    CN_ITEM* head = nullptr;
    CLUSTERS clusters;

    if( m_itemList.IsDirty() )
        searchConnections();

    auto addToSearchList = [&head, withinAnyNet, aSingleNet, aTypes] ( CN_ITEM *aItem )
    {
        if( withinAnyNet && aItem->Net() <= 0 )
            return;

        if( !aItem->Valid() )
            return;

        if( aSingleNet >=0 && aItem->Net() != aSingleNet )
            return;

        bool found = false;

        for( int i = 0; aTypes[i] != EOT; i++ )
        {
            if( aItem->Parent()->Type() == aTypes[i] )
            {
                found = true;
                break;
            }
        }

        if( !found )
            return;

        aItem->ListClear();
        aItem->SetVisited( false );

        if( !head )
            head = aItem;
        else
            head->ListInsert( aItem );
    };

    std::for_each( m_itemList.begin(), m_itemList.end(), addToSearchList );

    while( head )
    {
        CN_CLUSTER_PTR cluster ( new CN_CLUSTER() );

        Q.clear();
        CN_ITEM* root = head;
        root->SetVisited ( true );

        head = root->ListRemove();

        Q.push_back( root );

        while( Q.size() )
        {
            CN_ITEM* current = Q.front();

            Q.pop_front();
            cluster->Add( current );

            for( auto n : current->ConnectedItems() )
            {
                if( withinAnyNet && n->Net() != root->Net() )
                    continue;

                if( !n->Visited() && n->Valid() )
                {
                    n->SetVisited( true );
                    Q.push_back( n );
                    head = n->ListRemove();
                }
            }
        }

        clusters.push_back( cluster );
    }


    std::sort( clusters.begin(), clusters.end(), []( CN_CLUSTER_PTR a, CN_CLUSTER_PTR b ) {
        return a->OriginNet() < b->OriginNet();
    } );

#ifdef CONNECTIVITY_DEBUG
    printf("Active clusters: %d\n", clusters.size() );

    for( auto cl : clusters )
    {
        printf( "Net %d\n", cl->OriginNet() );
        cl->Dump();
    }
#endif

    return clusters;
}