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>
26 #include <kcombobox.h>
28 #include <klineedit.h>
29 #include <k3listview.h>
31 #include <kmessagebox.h>
32 #include <kpushbutton.h>
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
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
)
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" ) );
62 if ( ( !userid
.isEmpty() ) && ( !fullname
.isEmpty() ) )
63 setText( 0, QString( "%1 (%2)" ).arg( fullname
).arg( userid
) );
64 else if ( !userid
.isNull() )
66 else if ( !fullname
.isNull() )
67 setText( 0, fullname
);
74 const QString
& serviceid() const
84 MainDialogWidget::MainDialogWidget( QWidget
*parent
)
85 : QWidget( parent
), m_scanning( false ), m_locator_dnssd_rfb(0),m_locator_dnssd_vnc(0)
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();
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
& ) ),
126 bool showBrowse
= hp
->showBrowsingPanel();
127 enableBrowsingArea( showBrowse
);
133 * Sets the strings of the subwidgets using the current
136 void MainDialogWidget::languageChange()
141 void MainDialogWidget::save()
143 HostPreferences
*hp
= HostPreferences::instance();
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 );
189 kDebug() << "got unexpected whatsThis link: " << link
<< endl
;
193 void MainDialogWidget::enableBrowsingArea( bool enable
)
198 m_browsingPanel
->show();
199 m_browsingPanel
->setMaximumSize(1000, 1000);
200 m_browsingPanel
->setEnabled(true);
201 m_browseButton
->setText(m_browseButton
->text().replace(">>", "<<"));
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() ) );
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() );
228 m_serverInput
->setItemText( m_serverInput
->currentIndex(), rx
.cap( 1 ) );
231 void MainDialogWidget::itemDoubleClicked( Q3ListViewItem
*item
)
233 itemSelected( item
);
237 void MainDialogWidget::scopeSelected( const QString
&scope
)
240 if ( s
== i18n( "default" ) )
249 void MainDialogWidget::rescan()
251 QStringList scopeList
;
256 m_rescanButton
->setEnabled( false );
257 m_scopeCombo
->setEnabled( false );
258 if ( !ensureLocatorOpen() )
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();
286 lastSignalServices(true);
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
;
304 bool MainDialogWidget::ensureLocatorOpen()
309 m_locator
= new KServiceLocator();
311 if ( !m_locator
->available() ) {
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 );
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
) ) );
330 void MainDialogWidget::errorScanning()
332 KMessageBox::error( 0,
333 i18n( "An error occurred while scanning the network." ),
334 i18n( "Error While Scanning" ), false );
338 void MainDialogWidget::finishScanning()
340 m_rescanButton
->setEnabled( true );
341 m_scopeCombo
->setEnabled( true );
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 )
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() )
389 void MainDialogWidget::lastSignalServices( bool success
)
397 if ( !m_locator
->findScopes() )
399 kWarning() << "Failure in findScopes()" << endl
;
404 void MainDialogWidget::foundScopes( QStringList scopeList
)
406 scopeList
<< DNSSD_SCOPE
;
408 int di
= scopeList
.indexOf( DEFAULT_SCOPE
);
410 scopeList
[ di
] = i18n( "default" );
412 int ct
= scopeList
.indexOf( m_scopeCombo
->currentText() );
413 m_scopeCombo
->clear();
414 m_scopeCombo
->addItems( scopeList
);
416 m_scopeCombo
->setCurrentIndex( ct
);
420 #include "maindialogwidget.moc"