| # kdeprint Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# networkscanner.cpp

    00001 /*
    00002  *  This file is part of the KDE libraries
    00003  *  Copyright (c) 2001-2002 Michael Goffioul <kdeprint@swing.be>
    00004  *
    00005  *  This library is free software; you can redistribute it and/or
    00006  *  modify it under the terms of the GNU Library General Public
    00007  *  License version 2 as published by the Free Software Foundation.
    00008  *
    00009  *  This library is distributed in the hope that it will be useful,
    00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00012  *  Library General Public License for more details.
    00013  *
    00014  *  You should have received a copy of the GNU Library General Public License
    00015  *  along with this library; see the file COPYING.LIB.  If not, write to
    00016  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00017  *  Boston, MA 02111-1307, USA.
    00018  **/
    00019
    00020 #define USE_QSOCKET
    00021
    00022 #include "networkscanner.h"
    00023
    00024 #include <qprogressbar.h>
    00025 #include <kpushbutton.h>
    00026 #include <qlayout.h>
    00027 #include <qtimer.h>
    00028 #include <qlabel.h>
    00029 #include <qcombobox.h>
    00030 #include <qlineedit.h>
    00031 #include <qregexp.h>
    00032 #include <qsocket.h>
    00033 #include <klocale.h>
    00034 #include <kextendedsocket.h>
    00035 #include <kmessagebox.h>
    00036 #include <knumvalidator.h>
    00037 #include <kdebug.h>
    00038 #include <unistd.h>
    00039
    00040 class NetworkScanner::NetworkScannerPrivate
    00041 {
    00042 public:
    00043     int port;
    00044     QString prefixaddress;
    00045     int currentaddress;
    00046     int timeout;
    00047     bool scanning;
    00048     QPtrList<NetworkScanner::SocketInfo> printers;
    00049
    00050     QProgressBar *bar;
    00051     KPushButton *scan, *settings;
    00052     QLabel *subnetlab;
    00053     QTimer *timer;
    00054 #ifdef USE_QSOCKET
    00055     QSocket *socket;
    00056 #else
    00057     KExtendedSocket *socket;
    00058 #endif
    00059
    00060     NetworkScannerPrivate( int portvalue ) : port( portvalue )
    00061     {
    00062         prefixaddress = localPrefix();
    00063         currentaddress = 1;
    00064         timeout = 50;
    00065         scanning = false;
    00066         printers.setAutoDelete( true );
    00067     }
    00068     QString localPrefix();
    00069     QString scanString();
    00070 };
    00071
    00072 QString NetworkScanner::NetworkScannerPrivate::localPrefix()
    00073 {
    00074     char    buf[256];
    00075     buf[0] = '\0';
    00076     if (!gethostname(buf, sizeof(buf)))
    00077         buf[sizeof(buf)-1] = '\0';
    00078     QPtrList<KAddressInfo>  infos = KExtendedSocket::lookup(buf, QString::null);
    00079     infos.setAutoDelete(true);
    00080     if (infos.count() > 0)
    00081     {
    00082         QString IPstr = infos.first()->address()->nodeName();
    00083         int p = IPstr.findRev('.');
    00084         IPstr.truncate(p);
    00085         return IPstr;
    00086     }
    00087     return QString::null;
    00088 }
    00089
    00090 QString NetworkScanner::NetworkScannerPrivate::scanString()
    00091 {
    00092     QString s = prefixaddress + ".*";
    00093     if ( port != -1 )
    00094         s.append( ":" ).append( QString::number( port ) );
    00095     return s;
    00096 }
    00097
    00098 NetworkScanner::NetworkScanner( int port, QWidget *parent, const char *name )
    00099     : QWidget( parent, name )
    00100 {
    00101     d = new NetworkScannerPrivate( port );
    00102     d->bar = new QProgressBar( 256, this );
    00103     d->settings = new KPushButton( KGuiItem( i18n( "&Settings" ), "configure" ), this );
    00104     d->scan = new KPushButton( KGuiItem( i18n( "Sc&an" ), "viewmag" ), this );
    00105     d->timer = new QTimer( this );
    00106 #ifdef USE_QSOCKET
    00107     d->socket = new QSocket( this );
    00108 #else
    00109     d->socket = new KExtendedSocket();
    00110 #endif
    00111     QLabel *label = new QLabel( i18n( "Network scan:" ), this );
    00112     d->subnetlab = new QLabel( i18n( "Subnet: %1" ).arg( d->scanString() ), this );
    00113
    00114     QGridLayout *l0 = new QGridLayout( this, 4, 2, 0, 10 );
    00115     l0->addMultiCellWidget( label, 0, 0, 0, 1 );
    00116     l0->addMultiCellWidget( d->bar, 1, 1, 0, 1 );
    00117     l0->addMultiCellWidget( d->subnetlab, 2, 2, 0, 1 );
    00118     l0->addWidget( d->settings, 3, 0 );
    00119     l0->addWidget( d->scan, 3, 1 );
    00120
    00121     connect( d->timer, SIGNAL( timeout() ), SLOT( slotTimeout() ) );
    00122     connect( d->settings, SIGNAL( clicked() ), SLOT( slotSettingsClicked() ) );
    00123     connect( d->scan, SIGNAL( clicked() ), SLOT( slotScanClicked() ) );
    00124 #ifdef USE_QSOCKET
    00125     connect( d->socket, SIGNAL( connected() ), SLOT( slotConnectionSuccess() ) );
    00126     connect( d->socket, SIGNAL( error( int ) ), SLOT( slotConnectionFailed( int ) ) );
    00127 #else
    00128     connect( d->socket, SIGNAL( connectionSuccess() ), SLOT( slotConnectionSuccess() ) );
    00129     connect( d->socket, SIGNAL( connectionFailed( int ) ), SLOT( slotConnectionFailed( int ) ) );
    00130 #endif
    00131 }
    00132
    00133 NetworkScanner::~NetworkScanner()
    00134 {
    00135 #ifndef USE_QSOCKET
    00136     delete d->socket;
    00137 #endif
    00138     delete d;
    00139 }
    00140
    00141 void NetworkScanner::start()
    00142 {
    00143     if ( d->scanning )
    00144         return;
    00145
    00146     d->printers.clear();
    00147     emit scanStarted();
    00148     d->settings->setEnabled( false );
    00149     d->scan->setGuiItem( KGuiItem( i18n( "&Abort" ), "stop" ) );
    00150     d->currentaddress = -1;
    00151     d->scanning = true;
    00152     next();
    00153 }
    00154
    00155 void NetworkScanner::slotScanClicked()
    00156 {
    00157     if ( !d->scanning )
    00158     {
    00159         if ( d->localPrefix() == d->prefixaddress ||
    00160                 KMessageBox::warningContinueCancel( this->parentWidget(),
    00161                     i18n( "You are about to scan a subnet (%1.*) that does not "
    00162                           "correspond to the current subnet of this computer (%2.*). Do you want "
    00163                           "to scan the specified subnet anyway?" ).arg( d->prefixaddress ).arg( d->localPrefix() ),
    00164                     QString::null, KGuiItem( i18n( "&Scan" ), "viewmag" ), "askForScan" ) == KMessageBox::Continue )
    00165             start();
    00166     }
    00167     else
    00168     {
    00169 #ifdef USE_QSOCKET
    00170         d->socket->close();
    00171 #else
    00172         d->socket->cancelAsyncConnect();
    00173 #endif
    00174         finish();
    00175     }
    00176 }
    00177
    00178 void NetworkScanner::finish()
    00179 {
    00180     if ( !d->scanning )
    00181         return;
    00182
    00183     d->settings->setEnabled( true );
    00184     d->scan->setGuiItem( KGuiItem( i18n( "Sc&an" ), "viewmag" ) );
    00185     d->bar->reset();
    00186     d->scanning = false;
    00187     emit scanFinished();
    00188 }
    00189
    00190 void NetworkScanner::slotSettingsClicked()
    00191 {
    00192     NetworkScannerConfig dlg( this );
    00193     dlg.exec();
    00194 }
    00195
    00196 void NetworkScanner::slotNext()
    00197 {
    00198     if ( !d->scanning )
    00199         return;
    00200
    00201     d->timer->stop();
    00202 #ifdef USE_QSOCKET
    00203     d->socket->connectToHost( d->prefixaddress + "." + QString::number( d->currentaddress ), d->port );
    00204     kdDebug() << "Address: " << d->socket->peerName() << ", Port: " << d->socket->peerPort() << endl;
    00205 #else
    00206     d->socket->setAddress( d->prefixaddress + "." + QString::number( d->currentaddress ), d->port );
    00207     d->socket->startAsyncLookup();
    00208     kdDebug() << "Address: " << d->socket->host() << ", Port: " << d->socket->port() << endl;
    00209 #endif
    00210     d->timer->start( d->timeout, true );
    00211 }
    00212
    00213 void NetworkScanner::next()
    00214 {
    00215     //kdDebug() << "Next" << endl;
    00216     d->currentaddress++;
    00217     if ( d->currentaddress >= 256 )
    00218         finish();
    00219     else
    00220     {
    00221         d->bar->setProgress( d->currentaddress );
    00222         QTimer::singleShot( 0, this, SLOT( slotNext() ) );
    00223     }
    00224 }
    00225
    00226 void NetworkScanner::slotTimeout()
    00227 {
    00228     kdDebug() << "Timeout" << endl;
    00229     if ( !d->scanning )
    00230         return;
    00231
    00232 #ifdef USE_QSOCKET
    00233     d->socket->close();
    00234 #else
    00235     d->socket->cancelAsyncConnect();
    00236 #endif
    00237     next();
    00238 }
    00239
    00240 void NetworkScanner::slotConnectionSuccess()
    00241 {
    00242     kdDebug() << "Success" << endl;
    00243 #ifdef USE_QSOCKET
    00244     KSocketAddress *addr = KExtendedSocket::peerAddress( d->socket->socket() );
    00245 #else
    00246     KSocketAddress *addr = const_cast<KSocketAddress*>( d->socket->peerAddress() );
    00247 #endif
    00248     kdDebug() << "Connection success: " << ( addr ? addr->pretty() : QString( "ERROR" ) ) << endl;
    00249     kdDebug() << "Socket: " << d->socket->socket() << endl;
    00250     if ( addr )
    00251     {
    00252         SocketInfo *info = new SocketInfo;
    00253 #ifdef USE_QSOCKET
    00254         info->IP = d->socket->peerName();
    00255 #else
    00256         info->IP = d->socket->host();
    00257 #endif
    00258         info->Port = d->port;
    00259         QString portname;
    00260         KExtendedSocket::resolve( addr, info->Name, portname );
    00261         d->printers.append( info );
    00262         d->socket->close();
    00263         delete addr;
    00264     }
    00265     else
    00266         kdDebug() << "Unconnected socket, skipping" << endl;
    00267     next();
    00268 }
    00269
    00270 void NetworkScanner::slotConnectionFailed( int )
    00271 {
    00272     kdDebug() << "Failure" << endl;
    00273     next();
    00274 }
    00275
    00276 const QPtrList<NetworkScanner::SocketInfo>* NetworkScanner::printerList()
    00277 {
    00278     return &( d->printers );
    00279 }
    00280
    00281 int NetworkScanner::timeout() const
    00282 {
    00283     return d->timeout;
    00284 }
    00285
    00286 void NetworkScanner::setTimeout( int to )
    00287 {
    00288     d->timeout = to;
    00289 }
    00290
    00291 QString NetworkScanner::subnet() const
    00292 {
    00293     return d->prefixaddress;
    00294 }
    00295
    00296 void NetworkScanner::setSubnet( const QString& sn )
    00297 {
    00298     d->prefixaddress = sn;
    00299     d->subnetlab->setText( i18n( "Subnet: %1" ).arg( d->scanString() ) );
    00300 }
    00301
    00302 int NetworkScanner::port() const
    00303 {
    00304     return d->port;
    00305 }
    00306
    00307 void NetworkScanner::setPort( int p )
    00308 {
    00309     d->port = p;
    00310     d->subnetlab->setText( i18n( "Subnet: %1" ).arg( d->scanString() ) );
    00311 }
    00312
    00313 bool NetworkScanner::checkPrinter( const QString& host, int port )
    00314 {
    00315     // try first to find it in the SocketInfo list
    00316     QPtrListIterator<NetworkScanner::SocketInfo> it( d->printers );
    00317     for ( ; it.current(); ++it )
    00318     {
    00319         if ( port == it.current()->Port && ( host == it.current()->IP ||
    00320                     host == it.current()->Name ) )
    00321             return true;
    00322     }
    00323
    00324     // not found in SocketInfo list, try to establish connection
    00325     KExtendedSocket extsock( host, port );
    00326     extsock.setBlockingMode( false );
    00327     extsock.setTimeout( 0, d->timeout * 1000 );
    00328     return ( extsock.connect() == 0 );
    00329 }
    00330
    00331 NetworkScannerConfig::NetworkScannerConfig(NetworkScanner *scanner, const char *name)
    00332     : KDialogBase(scanner, name, true, QString::null, Ok|Cancel, Ok, true)
    00333 {
    00334     scanner_ = scanner;
    00335     QWidget *dummy = new QWidget(this);
    00336     setMainWidget(dummy);
    00337         KIntValidator *val = new KIntValidator( this );
    00338     QLabel  *masklabel = new QLabel(i18n("&Subnetwork:"),dummy);
    00339     QLabel  *portlabel = new QLabel(i18n("&Port:"),dummy);
    00340     QLabel  *toutlabel = new QLabel(i18n("&Timeout (ms):"),dummy);
    00341     QLineEdit   *mm = new QLineEdit(dummy);
    00342     mm->setText(QString::fromLatin1(".[0-255]"));
    00343     mm->setReadOnly(true);
    00344     mm->setFixedWidth(fontMetrics().width(mm->text())+10);
    00345
    00346     mask_ = new QLineEdit(dummy);
    00347     mask_->setAlignment(Qt::AlignRight);
    00348     port_ = new QComboBox(true,dummy);
    00349         if ( port_->lineEdit() )
    00350             port_->lineEdit()->setValidator( val );
    00351     tout_ = new QLineEdit(dummy);
    00352         tout_->setValidator( val );
    00353
    00354     masklabel->setBuddy(mask_);
    00355     portlabel->setBuddy(port_);
    00356     toutlabel->setBuddy(tout_);
    00357
    00358     mask_->setText(scanner_->subnet());
    00359     port_->insertItem("631");
    00360     port_->insertItem("9100");
    00361     port_->insertItem("9101");
    00362     port_->insertItem("9102");
    00363     port_->setEditText(QString::number(scanner_->port()));
    00364     tout_->setText(QString::number(scanner_->timeout()));
    00365
    00366     QGridLayout *main_ = new QGridLayout(dummy, 3, 2, 0, 10);
    00367     QHBoxLayout *lay1 = new QHBoxLayout(0, 0, 5);
    00368     main_->addWidget(masklabel, 0, 0);
    00369     main_->addWidget(portlabel, 1, 0);
    00370     main_->addWidget(toutlabel, 2, 0);
    00371     main_->addLayout(lay1, 0, 1);
    00372     main_->addWidget(port_, 1, 1);
    00373     main_->addWidget(tout_, 2, 1);
    00374     lay1->addWidget(mask_,1);
    00375     lay1->addWidget(mm,0);
    00376
    00377     resize(250,130);
    00378     setCaption(i18n("Scan Configuration"));
    00379 }
    00380
    00381 NetworkScannerConfig::~NetworkScannerConfig()
    00382 {
    00383 }
    00384
    00385 void NetworkScannerConfig::slotOk()
    00386 {
    00387     QString msg;
    00388     QRegExp re("(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})");
    00389     if (!re.exactMatch(mask_->text()))
    00390         msg = i18n("Wrong subnetwork specification.");
    00391     else
    00392     {
    00393         for (int i=1; i<=3; i++)
    00394             if (re.cap(i).toInt() >= 255)
    00395             {
    00396                 msg = i18n("Wrong subnetwork specification.");
    00397                 break;
    00398             }
    00399     }
    00400
    00401     bool    ok(false);
    00402     int     v = tout_->text().toInt(&ok);
    00403     if (!ok || v <= 0)
    00404         msg = i18n("Wrong timeout specification.");
    00405     v = port_->currentText().toInt(&ok);
    00406     if (!ok || v <= 0)
    00407         msg = i18n("Wrong port specification.");
    00408     if (!msg.isEmpty())
    00409     {
    00410         KMessageBox::error(this,msg);
    00411         return;
    00412     }
    00413
    00414     scanner_->setTimeout( tout_->text().toInt() );
    00415     scanner_->setSubnet( mask_->text() );
    00416     scanner_->setPort( port_->currentText().toInt() );
    00417
    00418     KDialogBase::slotOk();
    00419 }
    00420
    00421 #include "networkscanner.moc"

This file is part of the documentation for kdeprint Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:31:05 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003