delay a few things on startup, such as setting the visibility mode, which ensures...
[personal-kdebase.git] / runtime / kioclient / kioclient.cpp
blob7abbf55a91eddcfefd2c7262a6cc7590affae0e7
1 /* This file is part of the KDE project
2 Copyright (C) 1999-2006 David Faure <faure@kde.org>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
19 #include "kioclient.h"
21 #include <ktoolinvocation.h>
22 #include <kio/job.h>
23 #include <kio/copyjob.h>
24 #include <kio/jobuidelegate.h>
25 #include <kcmdlineargs.h>
26 #include <kpropertiesdialog.h>
27 #include <klocale.h>
28 #include <kstandarddirs.h>
29 #include <kurlrequesterdialog.h>
30 #include <kmessagebox.h>
31 #include <kmimetypetrader.h>
32 #include <kfiledialog.h>
33 #include <kdebug.h>
34 #include <kservice.h>
35 #include <QTimer>
36 #include <krun.h>
37 #include <QtDBus/QtDBus>
38 #include <kcomponentdata.h>
39 #include <iostream>
41 static const char appName[] = "kioclient";
42 static const char programName[] = I18N_NOOP("KIO Client");
43 static const char description[] = I18N_NOOP("Command-line tool for network-transparent operations");
44 static const char version[] = "2.0";
46 bool ClientApp::m_ok = true;
47 static bool s_interactive = true;
48 static KIO::JobFlags s_jobFlags = KIO::DefaultFlags;
50 #ifdef KIOCLIENT_AS_KIOCLIENT
51 static void usage()
53 KCmdLineArgs::enable_i18n();
54 puts(i18n("\nSyntax:\n").toLocal8Bit());
55 puts(i18n(" kioclient openProperties 'url'\n"
56 " # Opens a properties menu\n\n").toLocal8Bit());
57 puts(i18n(" kioclient exec 'url' ['mimetype']\n"
58 " # Tries to open the document pointed to by 'url', in the application\n"
59 " # associated with it in KDE. You may omit 'mimetype'.\n"
60 " # In this case the mimetype is determined\n"
61 " # automatically. Of course URL may be the URL of a\n"
62 " # document, or it may be a *.desktop file.\n").toLocal8Bit());
63 puts(i18n(" kioclient move 'src' 'dest'\n"
64 " # Moves the URL 'src' to 'dest'.\n"
65 " # 'src' may be a list of URLs.\n").toLocal8Bit());
66 //puts(i18n(" # 'dest' may be \"trash:/\" to move the files\n"
67 // " # in the trash bin.\n\n").toLocal8Bit());
68 puts(i18n(" kioclient download ['src']\n"
69 " # Copies the URL 'src' to a user-specified location'.\n"
70 " # 'src' may be a list of URLs, if not present then\n"
71 " # a URL will be requested.\n\n").toLocal8Bit());
72 puts(i18n(" kioclient copy 'src' 'dest'\n"
73 " # Copies the URL 'src' to 'dest'.\n"
74 " # 'src' may be a list of URLs.\n\n").toLocal8Bit());
75 puts(i18n(" kioclient cat 'url'\n"
76 " # Writes out the contents of 'url' to stdout\n\n").toLocal8Bit());
78 puts(i18n("*** Examples:\n"
79 " kioclient exec file:/root/Desktop/cdrom.desktop \"Mount default\"\n"
80 " // Mounts the CDROM\n\n").toLocal8Bit());
81 puts(i18n(" kioclient exec file:/home/weis/data/test.html\n"
82 " // Opens the file with default binding\n\n").toLocal8Bit());
83 puts(i18n(" kioclient exec file:/home/weis/data/test.html Netscape\n"
84 " // Opens the file with netscape\n\n").toLocal8Bit());
85 puts(i18n(" kioclient exec ftp://localhost/\n"
86 " // Opens new window with URL\n\n").toLocal8Bit());
87 puts(i18n(" kioclient exec file:/root/Desktop/emacs.desktop\n"
88 " // Starts emacs\n\n").toLocal8Bit());
89 puts(i18n(" kioclient exec file:/root/Desktop/cdrom.desktop\n"
90 " // Opens the CDROM's mount directory\n\n").toLocal8Bit());
91 puts(i18n(" kioclient exec .\n"
92 " // Opens the current directory. Very convenient.\n\n").toLocal8Bit());
94 #endif
96 int main( int argc, char **argv )
98 KCmdLineArgs::init(argc, argv, appName, 0, ki18n(programName), version, ki18n(description), false);
101 KCmdLineOptions options;
102 options.add("noninteractive", ki18n("Non-interactive use: no message boxes"));
103 #if defined(KIOCLIENT_AS_KDEOPEN)
104 options.add("+urls", ki18n("URL or URLs"));
105 #elif defined(KIOCLIENT_AS_KDECP)
106 options.add("+src", ki18n("Source URL or URLs"));
107 options.add("+dest", ki18n("Destination URL"));
108 #elif defined(KIOCLIENT_AS_KDEMV)
109 options.add("+src", ki18n("Source URL or URLs"));
110 options.add("+dest", ki18n("Destination URL"));
111 #elif defined(KIOCLIENT_AS_KIOCLIENT)
112 options.add("commands", ki18n("Show available commands"));
113 options.add("+command", ki18n("Command (see --commands)"));
114 options.add("+[URL(s)]", ki18n("Arguments for command"));
115 #endif
117 KCmdLineArgs::addCmdLineOptions( options );
118 KCmdLineArgs::addTempFileOption();
120 #ifdef KIOCLIENT_AS_KIOCLIENT
121 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
123 if ( argc == 1 || args->isSet("commands") )
125 usage();
126 return 0;
128 #endif
130 return ClientApp::doIt() ? 0 /*no error*/ : 1 /*error*/;
133 bool krun_has_error = false;
135 void ClientApp::delayedQuit()
137 // Quit in 2 seconds. This leaves time for KRun to pop up
138 // "app not found" in KProcessRunner, if that was the case.
139 QTimer::singleShot( 2000, this, SLOT(deref()) );
140 // don't access the KRun instance later, it will be deleted after calling slots
141 if( static_cast< const KRun* >( sender())->hasError())
142 krun_has_error = true;
145 static void checkArgumentCount(int count, int min, int max)
147 if (count < min)
149 fputs( i18n("Syntax Error: Not enough arguments\n").toLocal8Bit(), stderr );
150 ::exit(1);
152 if (max && (count > max))
154 fputs( i18n("Syntax Error: Too many arguments\n").toLocal8Bit(), stderr );
155 ::exit(1);
159 bool ClientApp::kde_open( const KUrl& url, const QString& mimeType )
161 if ( mimeType.isEmpty() ) {
162 kDebug() << url;
163 KRun * run = new KRun( url, 0 );
164 QObject::connect( run, SIGNAL( finished() ), this, SLOT( delayedQuit() ));
165 QObject::connect( run, SIGNAL( error() ), this, SLOT( delayedQuit() ));
166 this->exec();
167 return !krun_has_error;
168 } else {
169 KUrl::List urls;
170 urls.append( url );
171 const KService::List offers = KMimeTypeTrader::self()->query(
172 mimeType, QLatin1String( "Application" ) );
173 if (offers.isEmpty()) return 1;
174 KService::Ptr serv = offers.first();
175 return KRun::run( *serv, urls, 0 );
179 bool ClientApp::doCopy( int firstArg )
181 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
182 int argc = args->count();
183 KUrl::List srcLst;
184 for ( int i = firstArg; i <= argc - 2; i++ )
185 srcLst.append( args->url(i) );
186 KIO::Job * job = KIO::copy( srcLst, args->url(argc - 1), s_jobFlags );
187 if ( !s_interactive )
188 job->setUiDelegate( 0 );
189 connect( job, SIGNAL( result( KJob * ) ), this, SLOT( slotResult( KJob * ) ) );
190 this->exec();
191 return m_ok;
194 bool ClientApp::doMove( int firstArg )
196 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
197 int argc = args->count();
198 KUrl::List srcLst;
199 for ( int i = firstArg; i <= argc - 2; i++ )
200 srcLst.append( args->url(i) );
202 KIO::Job * job = KIO::move( srcLst, args->url(argc - 1), s_jobFlags );
203 if ( !s_interactive )
204 job->setUiDelegate( 0 );
205 connect( job, SIGNAL( result( KJob * ) ), this, SLOT( slotResult( KJob * ) ) );
206 this->exec();
207 return m_ok;
210 bool ClientApp::doIt()
212 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
213 int argc = args->count();
214 checkArgumentCount(argc, 1, 0);
216 if ( !args->isSet( "ninteractive" ) ) {
217 s_interactive = false;
218 s_jobFlags = KIO::HideProgressInfo;
221 kDebug() << "Creating ClientApp";
222 int fake_argc = 0;
223 char** fake_argv = 0;
224 ClientApp app( fake_argc, fake_argv );
225 KComponentData componentData("kioclient"); // needed by KIO's internal use of KConfig
226 app.setApplicationName(componentData.componentName());
227 KGlobal::ref();
228 KGlobal::setAllowQuit(true);
230 // KIO needs dbus (for uiserver communication)
231 extern void qDBusBindToApplication();
232 qDBusBindToApplication();
233 if (!QDBusConnection::sessionBus().isConnected())
234 kFatal(101) << "Session bus not found" ;
237 #ifdef KIOCLIENT_AS_KDEOPEN
238 app.kde_open( args->url(0), QByteArray() );
239 return true;
240 #elif defined(KIOCLIENT_AS_KDECP)
241 checkArgumentCount(argc, 2, 0);
242 return app.doCopy(0);
243 #elif defined(KIOCLIENT_AS_KDEMV)
244 checkArgumentCount(argc, 2, 0);
245 return app.doMove(0);
246 #else
247 // Normal kioclient mode
248 const QByteArray command = args->arg(0).toLocal8Bit();
249 if ( command == "openProperties" )
251 checkArgumentCount(argc, 2, 2);
252 KPropertiesDialog * p = new KPropertiesDialog( args->url(1), 0 /*no parent*/ );
253 QObject::connect( p, SIGNAL( destroyed() ), &app, SLOT( quit() ));
254 QObject::connect( p, SIGNAL( canceled() ), &app, SLOT( slotDialogCanceled() ));
255 p->show();
256 app.exec();
257 return m_ok;
259 else if ( command == "cat" )
261 checkArgumentCount(argc, 2, 2);
262 KIO::TransferJob* job = KIO::get(args->url(1), KIO::NoReload, s_jobFlags);
263 if ( !s_interactive )
264 job->setUiDelegate( 0 );
265 connect(job, SIGNAL(data(KIO::Job*,QByteArray) ), &app, SLOT(slotPrintData(KIO::Job*,QByteArray)));
266 connect( job, SIGNAL( result( KJob * ) ), &app, SLOT( slotResult( KJob * ) ) );
267 app.exec();
268 return m_ok;
270 else if ( command == "exec" )
272 checkArgumentCount(argc, 2, 3);
273 app.kde_open( args->url( 1 ),
274 argc == 3 ? args->arg( 2 ) : QString() );
276 else if ( command == "download" )
278 checkArgumentCount(argc, 0, 0);
279 KUrl::List srcLst;
280 if (argc == 1) {
281 while(true) {
282 KUrl src = KUrlRequesterDialog::getUrl();
283 if (!src.isEmpty()) {
284 if (!src.isValid()) {
285 KMessageBox::error(0, i18n("Unable to download from an invalid URL."));
286 continue;
288 srcLst.append(src);
290 break;
292 } else {
293 for ( int i = 1; i <= argc - 1; i++ )
294 srcLst.append( args->url(i) );
296 if (srcLst.count() == 0)
297 return m_ok;
298 QString dst =
299 KFileDialog::getSaveFileName( (argc<2) ? QString() : (args->url(1).fileName()) );
300 if (dst.isEmpty()) // canceled
301 return m_ok; // AK - really okay?
302 KUrl dsturl;
303 dsturl.setPath( dst );
304 KIO::Job * job = KIO::copy( srcLst, dsturl, s_jobFlags );
305 if ( !s_interactive )
306 job->setUiDelegate( 0 );
307 connect( job, SIGNAL( result( KJob * ) ), &app, SLOT( slotResult( KJob * ) ) );
308 app.exec();
309 return m_ok;
311 else if ( command == "copy" )
313 checkArgumentCount(argc, 2, 0);
314 return app.doCopy( 1 );
316 else if ( command == "move" )
318 checkArgumentCount(argc, 2, 0);
319 return app.doMove( 1 );
321 else
323 fprintf( stderr, "%s", i18n("Syntax Error: Unknown command '%1'\n", QString::fromLocal8Bit(command)).toLocal8Bit().data() );
324 return false;
326 return true;
327 #endif
330 void ClientApp::slotResult( KJob * job )
332 if (job->error() && s_interactive)
333 static_cast<KIO::Job*>(job)->ui()->showErrorMessage();
334 m_ok = !job->error();
335 quit();
338 void ClientApp::slotDialogCanceled()
340 m_ok = false;
341 quit();
344 void ClientApp::deref()
346 KGlobal::deref();
349 void ClientApp::slotPrintData(KIO::Job*, const QByteArray &data)
351 if (!data.isEmpty())
352 std::cout << data.constData();
355 #include "kioclient.moc"