kdeprint Library API Documentation

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"
KDE Logo
This file is part of the documentation for kdeprint Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 14 00:34:43 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003