merge in my changes from soc-krdc branch
[kdenetwork.git] / krdc / maindialogwidget.cpp
bloba0256e5c9e01f3ddf2db780b6f34dc18aebfb76f
1 /* This file is part of the KDE project
2 Copyright (C) 2002-2003 Tim Jansen <tim@tjansen.de>
3 Copyright (C) 2003-2004 Nadeem Hasan <nhasan@kde.org>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or ( at your option ) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
21 #include <config-krdc.h>
23 #include <QRegExp>
24 #include <QTimer>
26 #include <kcombobox.h>
27 #include <kdebug.h>
28 #include <klineedit.h>
29 #include <k3listview.h>
30 #include <klocale.h>
31 #include <kmessagebox.h>
32 #include <kpushbutton.h>
33 #include <QWhatsThis>
35 #include "hostpreferences.h"
36 #include "maindialogwidget.h"
38 static const QString DEFAULT_SCOPE = "default";
39 static const QString DNSSD_SCOPE = "DNS-SD";
41 class UrlListViewItem : public K3ListViewItem
43 public:
44 UrlListViewItem( Q3ListView *v, const QString &url, const QString &host,
45 const QString &protocol, const QString &type, const QString &userid,
46 const QString &fullname, const QString &desc,
47 const QString &serviceid )
48 : K3ListViewItem( v, host, i18n( "unknown" ), host, protocol ),
49 m_url( url ), m_serviceid( serviceid )
51 if ( !type.isNull() )
53 //User connects to somebody else's desktop, used for krfb
54 if ( type.toLower() == "shared" )
55 setText( 1, i18n( "Shared Desktop" ) );
56 //User connects to desktop that exists only on the network
57 else if ( type.toLower() == "private" )
58 setText( 1, i18n( "Standalone Desktop" ) );
60 if ( !desc.isNull() )
61 setText( 0, desc );
62 if ( ( !userid.isEmpty() ) && ( !fullname.isEmpty() ) )
63 setText( 0, QString( "%1 (%2)" ).arg( fullname ).arg( userid ) );
64 else if ( !userid.isNull() )
65 setText( 0, userid );
66 else if ( !fullname.isNull() )
67 setText( 0, fullname );
70 QString url()
72 return m_url;
74 const QString& serviceid() const
76 return m_serviceid;
79 protected:
80 QString m_url;
81 QString m_serviceid;
84 MainDialogWidget::MainDialogWidget( QWidget *parent )
85 : QWidget( parent ), m_scanning( false ), m_locator_dnssd_rfb(0),m_locator_dnssd_vnc(0)
87 setupUi(this);
88 // These should be folded back into the .ui, if we keep it.
89 m_browseButton->setText( i18n( "Browse >>" ) );
90 m_rescanButton->setText( i18n( "Rescan" ) );
91 m_activeNoteLabel->setWordWrap( true );
94 // signals and slots connections
95 connect(m_browseButton, SIGNAL(clicked()), this, SLOT(toggleBrowsingArea()));
96 connect(m_rescanButton, SIGNAL(clicked()), this, SLOT(rescan()));
97 connect(m_serverInput, SIGNAL(textChanged(const QString&)),
98 this, SLOT(hostChanged(const QString&)));
99 connect(m_searchInput, SIGNAL(returnPressed()), this, SLOT(rescan()));
100 connect(m_activeNoteLabel, SIGNAL(linkActivated(const QString&)),
101 this, SLOT(exampleWhatsThis(const QString&)));
103 HostPreferences *hp = HostPreferences::instance();
104 QStringList list;
106 list = hp->serverCompletions();
107 m_serverInput->completionObject()->setItems( list );
108 list = hp->serverHistory();
109 m_serverInput->setHistoryItems( list );
111 m_searchInput->setTrapReturnKey( true );
113 connect( m_browsingView,
114 SIGNAL( selectionChanged( Q3ListViewItem * ) ),
115 SLOT( itemSelected( Q3ListViewItem * ) ) );
116 connect( m_browsingView,
117 SIGNAL( doubleClicked( Q3ListViewItem *, const QPoint &, int ) ),
118 SLOT( itemDoubleClicked( Q3ListViewItem * ) ) );
119 connect( m_scopeCombo,
120 SIGNAL( activated( const QString & ) ),
121 SLOT( scopeSelected( const QString & ) ) );
122 connect( m_serverInput,
123 SIGNAL( returnPressed( const QString & ) ),
124 SLOT( rescan() ) );
126 bool showBrowse = hp->showBrowsingPanel();
127 enableBrowsingArea( showBrowse );
129 adjustSize();
133 * Sets the strings of the subwidgets using the current
134 * language.
136 void MainDialogWidget::languageChange()
138 retranslateUi(this);
141 void MainDialogWidget::save()
143 HostPreferences *hp = HostPreferences::instance();
144 QStringList list;
146 m_serverInput->addToHistory( m_serverInput->currentText() );
147 list = m_serverInput->completionObject()->items();
148 hp->setServerCompletions( list );
149 list = m_serverInput->historyItems();
150 hp->setServerHistory( list );
152 hp->setShowBrowsingPanel( m_browsingPanel->isVisible() );
155 void MainDialogWidget::setRemoteHost( const QString &host )
157 m_serverInput->setEditText( host );
160 QString MainDialogWidget::remoteHost()
162 return m_serverInput->currentText();
165 void MainDialogWidget::hostChanged( const QString &text )
167 emit hostValid(text.contains(QRegExp(":[0-9]+$")) ||
168 text.contains(QRegExp("^vnc:/.+")) ||
169 text.contains(QRegExp("^rdp:/.+")));
172 void MainDialogWidget::toggleBrowsingArea()
174 enableBrowsingArea(!m_browsingPanel->isVisible());
177 void MainDialogWidget::exampleWhatsThis(const QString & link)
179 if ( link == QString( "whatsthisExampleUrls" ) ) {
180 QString whatsThisText( "<h3>Examples</h3>" );
181 whatsThisText += "for a computer called 'megan':";
182 whatsThisText += "<table>";
183 whatsThisText += "<tr><td>megan:1</td><td>connect to the VNC server on 'megan' with display number 1</td></tr>";
184 whatsThisText += "<tr><td>vnc:/megan:1</td><td>longer form for the same thing</td></tr>";
185 whatsThisText += "<tr><td>rdp:/megan</td><td>connect to the RDP server on 'megan'</td></tr>";
186 whatsThisText += "</table>";
187 QWhatsThis::showText( QCursor::pos(), whatsThisText, this );
188 } else {
189 kDebug() << "got unexpected whatsThis link: " << link << endl;
193 void MainDialogWidget::enableBrowsingArea( bool enable )
195 int hOffset = 0;
196 if (enable)
198 m_browsingPanel->show();
199 m_browsingPanel->setMaximumSize(1000, 1000);
200 m_browsingPanel->setEnabled(true);
201 m_browseButton->setText(m_browseButton->text().replace(">>", "<<"));
203 else
205 hOffset = m_browsingPanel->height();
206 m_browsingPanel->hide();
207 m_browsingPanel->setMaximumSize(0, 0);
208 m_browsingPanel->setEnabled(false);
209 m_browseButton->setText(m_browseButton->text().replace("<<", ">>"));
210 int h = minimumSize().height()-hOffset;
211 setMinimumSize(minimumSize().width(), (h > 0) ? h : 0);
212 resize(width(), height()-hOffset);
214 QTimer::singleShot( 0, parentWidget(), SLOT( adjustWidgetSize() ) );
217 if (enable)
218 rescan();
221 void MainDialogWidget::itemSelected( Q3ListViewItem *item )
223 UrlListViewItem *u = ( UrlListViewItem* ) item;
224 QRegExp rx( "^service:remotedesktop\\.kde:([^;]*)" );
225 if ( rx.indexIn( u->url() ) < 0 )
226 m_serverInput->setItemText( m_serverInput->currentIndex(), u->url() );
227 else
228 m_serverInput->setItemText( m_serverInput->currentIndex(), rx.cap( 1 ) );
231 void MainDialogWidget::itemDoubleClicked( Q3ListViewItem *item )
233 itemSelected( item );
234 emit accept();
237 void MainDialogWidget::scopeSelected( const QString &scope )
239 QString s = scope;
240 if ( s == i18n( "default" ) )
241 s = DEFAULT_SCOPE;
243 if ( m_scope == s )
244 return;
245 m_scope = s;
246 rescan();
249 void MainDialogWidget::rescan()
251 QStringList scopeList;
253 if ( m_scanning )
254 return;
255 m_scanning = true;
256 m_rescanButton->setEnabled( false );
257 m_scopeCombo->setEnabled( false );
258 if ( !ensureLocatorOpen() )
259 return;
261 m_browsingView->clear();
263 if (m_locator_dnssd_rfb) {
264 delete m_locator_dnssd_rfb; // still active browsers
265 m_locator_dnssd_rfb = 0;
266 delete m_locator_dnssd_vnc;
267 m_locator_dnssd_vnc=0;
270 if (m_scope == DNSSD_SCOPE) {
271 kDebug() << "Scope is DNSSD\n";
272 //FIXME: non-default domains too
273 m_locator_dnssd_rfb = new DNSSD::ServiceBrowser("_rfb._tcp",true);
274 m_locator_dnssd_vnc = new DNSSD::ServiceBrowser("_vnc._tcp",true);
275 connect(m_locator_dnssd_rfb,SIGNAL(serviceAdded(DNSSD::RemoteService::Ptr)),
276 SLOT(addedService(DNSSD::RemoteService::Ptr)));
277 connect(m_locator_dnssd_rfb,SIGNAL(serviceRemoved(DNSSD::RemoteService::Ptr)),
278 SLOT(removedService(DNSSD::RemoteService::Ptr)));
279 connect(m_locator_dnssd_vnc,SIGNAL(serviceAdded(DNSSD::RemoteService::Ptr)),
280 SLOT(addedService(DNSSD::RemoteService::Ptr)));
281 connect(m_locator_dnssd_vnc,SIGNAL(serviceRemoved(DNSSD::RemoteService::Ptr)),
282 SLOT(removedService(DNSSD::RemoteService::Ptr)));
283 m_locator_dnssd_vnc->startBrowse();
284 m_locator_dnssd_rfb->startBrowse();
285 // now find scopes
286 lastSignalServices(true);
287 } else {
288 QString filter;
289 if ( !m_searchInput->text().trimmed().isEmpty() ) {
290 QString ef = KServiceLocator::escapeFilter(
291 m_searchInput->text().trimmed() );
292 filter = "(|(|(description=*"+ef+"*)(username=*"+ef+"*))(fullname=*"+ef+"*))";
295 if ( !m_locator->findServices( "service:remotedesktop.kde",
296 filter, m_scope ) ) {
297 kWarning() << "Failure in findServices()" << endl;
298 errorScanning();
299 return;
304 bool MainDialogWidget::ensureLocatorOpen()
306 if ( m_locator )
307 return true;
309 m_locator = new KServiceLocator();
311 if ( !m_locator->available() ) {
312 #ifdef HAVE_SLP
313 KMessageBox::error( 0,
314 i18n( "Browsing the network is not possible. You probably "
315 "did not install SLP support correctly." ),
316 i18n( "Browsing Not Possible" ), false );
317 #endif
318 return false;
321 connect( m_locator, SIGNAL( foundService( QString,int ) ),
322 SLOT( foundService( QString,int ) ) );
323 connect( m_locator, SIGNAL( lastServiceSignal( bool ) ),
324 SLOT( lastSignalServices( bool ) ) );
325 connect( m_locator, SIGNAL( foundScopes( QStringList ) ),
326 SLOT( foundScopes( QStringList ) ) );
327 return true;
330 void MainDialogWidget::errorScanning()
332 KMessageBox::error( 0,
333 i18n( "An error occurred while scanning the network." ),
334 i18n( "Error While Scanning" ), false );
335 finishScanning();
338 void MainDialogWidget::finishScanning()
340 m_rescanButton->setEnabled( true );
341 m_scopeCombo->setEnabled( true );
342 m_scanning = false;
345 void MainDialogWidget::foundService( QString url, int )
347 QRegExp rx( "^service:remotedesktop\\.kde:(\\w+)://([^;]+);(.*)$" );
349 if ( rx.indexIn( url ) < 0 )
351 rx = QRegExp( "^service:remotedesktop\\.kde:(\\w+)://(.*)$" );
352 if ( rx.indexIn( url ) < 0 )
353 return;
356 QMap<QString,QString> map;
357 KServiceLocator::parseAttributeList( rx.cap( 3 ), map );
359 new UrlListViewItem( m_browsingView, url, rx.cap( 2 ), rx.cap( 1 ),
360 KServiceLocator::decodeAttributeValue( map[ "type" ] ),
361 KServiceLocator::decodeAttributeValue( map[ "username" ] ),
362 KServiceLocator::decodeAttributeValue( map[ "fullname" ] ),
363 KServiceLocator::decodeAttributeValue( map[ "description" ] ),
364 KServiceLocator::decodeAttributeValue( map[ "serviceid" ] ) );
367 void MainDialogWidget::addedService( DNSSD::RemoteService::Ptr service )
369 QString type = service->type().mid(1,3);
370 if (type == "rfb") type = "vnc";
371 QString url = type+"://"+service->hostName()+':'+QString::number(service->port());
372 new UrlListViewItem( m_browsingView, url, service->serviceName(),
373 type.toUpper(),service->textData()["type"],
374 service->textData()["u"],service->textData()["fullname"],
375 service->textData()["description"],service->serviceName()+service->domain());
378 void MainDialogWidget::removedService( DNSSD::RemoteService::Ptr service )
380 Q3ListViewItemIterator it( m_browsingView );
381 while ( it.current() ) {
382 if ( ((UrlListViewItem*)it.current())->serviceid() == service->serviceName()+service->domain() )
383 delete it.current();
384 else ++it;
389 void MainDialogWidget::lastSignalServices( bool success )
391 if ( !success )
393 errorScanning();
394 return;
397 if ( !m_locator->findScopes() )
399 kWarning() << "Failure in findScopes()" << endl;
400 errorScanning();
404 void MainDialogWidget::foundScopes( QStringList scopeList )
406 scopeList << DNSSD_SCOPE;
408 int di = scopeList.indexOf( DEFAULT_SCOPE );
409 if ( di >= 0 )
410 scopeList[ di ] = i18n( "default" );
412 int ct = scopeList.indexOf( m_scopeCombo->currentText() );
413 m_scopeCombo->clear();
414 m_scopeCombo->addItems( scopeList );
415 if ( ct >= 0 )
416 m_scopeCombo->setCurrentIndex( ct );
417 finishScanning();
420 #include "maindialogwidget.moc"