paste.cpp
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2000 David Faure <faure@kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License version 2 as published by the Free Software Foundation. 00007 00008 This library is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00011 Library General Public License for more details. 00012 00013 You should have received a copy of the GNU Library General Public License 00014 along with this library; see the file COPYING.LIB. If not, write to 00015 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00016 Boston, MA 02110-1301, USA. 00017 */ 00018 00019 #include "paste.h" 00020 #include "pastedialog.h" 00021 00022 #include "kio/job.h" 00023 #include "kio/global.h" 00024 #include "kio/netaccess.h" 00025 #include "kio/observer.h" 00026 #include "kio/renamedlg.h" 00027 #include "kio/kprotocolmanager.h" 00028 00029 #include <kurl.h> 00030 #include <kurldrag.h> 00031 #include <kdebug.h> 00032 #include <klocale.h> 00033 #include <kinputdialog.h> 00034 #include <kmessagebox.h> 00035 #include <kmimetype.h> 00036 #include <ktempfile.h> 00037 00038 #include <tqapplication.h> 00039 #include <tqclipboard.h> 00040 #include <tqdragobject.h> 00041 #include <tqtextstream.h> 00042 #include <tqvaluevector.h> 00043 00044 static KURL getNewFileName( const KURL &u, const TQString& text ) 00045 { 00046 bool ok; 00047 TQString dialogText( text ); 00048 if ( dialogText.isEmpty() ) 00049 dialogText = i18n( "Filename for clipboard content:" ); 00050 TQString file = KInputDialog::getText( TQString::null, dialogText, TQString::null, &ok ); 00051 if ( !ok ) 00052 return KURL(); 00053 00054 KURL myurl(u); 00055 myurl.addPath( file ); 00056 00057 if (KIO::NetAccess::exists(myurl, false, 0)) 00058 { 00059 kdDebug(7007) << "Paste will overwrite file. Prompting..." << endl; 00060 KIO::RenameDlg_Result res = KIO::R_OVERWRITE; 00061 00062 TQString newPath; 00063 // Ask confirmation about resuming previous transfer 00064 res = Observer::self()->open_RenameDlg( 00065 0L, i18n("File Already Exists"), 00066 u.pathOrURL(), 00067 myurl.pathOrURL(), 00068 (KIO::RenameDlg_Mode) (KIO::M_OVERWRITE | KIO::M_SINGLE), newPath); 00069 00070 if ( res == KIO::R_RENAME ) 00071 { 00072 myurl = newPath; 00073 } 00074 else if ( res == KIO::R_CANCEL ) 00075 { 00076 return KURL(); 00077 } 00078 } 00079 00080 return myurl; 00081 } 00082 00083 // The finaly step: write _data to tempfile and move it to neW_url 00084 static KIO::CopyJob* pasteDataAsyncTo( const KURL& new_url, const TQByteArray& _data ) 00085 { 00086 KTempFile tempFile; 00087 tempFile.dataStream()->writeRawBytes( _data.data(), _data.size() ); 00088 tempFile.close(); 00089 00090 KURL orig_url; 00091 orig_url.setPath(tempFile.name()); 00092 00093 return KIO::move( orig_url, new_url ); 00094 } 00095 00096 #ifndef QT_NO_MIMECLIPBOARD 00097 static KIO::CopyJob* chooseAndPaste( const KURL& u, TQMimeSource* data, 00098 const TQValueVector<TQCString>& formats, 00099 const TQString& text, 00100 TQWidget* widget, 00101 bool clipboard ) 00102 { 00103 TQStringList formatLabels; 00104 for ( uint i = 0; i < formats.size(); ++i ) { 00105 const TQCString& fmt = formats[i]; 00106 KMimeType::Ptr mime = KMimeType::mimeType( fmt ); 00107 if ( mime != KMimeType::defaultMimeTypePtr() ) 00108 formatLabels.append( i18n( "%1 (%2)" ).arg( mime->comment() ).arg( fmt.data() ) ); 00109 else 00110 formatLabels.append( fmt ); 00111 } 00112 00113 TQString dialogText( text ); 00114 if ( dialogText.isEmpty() ) 00115 dialogText = i18n( "Filename for clipboard content:" ); 00116 KIO::PasteDialog dlg( TQString::null, dialogText, TQString::null, formatLabels, widget, clipboard ); 00117 00118 if ( dlg.exec() != KDialogBase::Accepted ) 00119 return 0; 00120 00121 if ( clipboard && dlg.clipboardChanged() ) { 00122 KMessageBox::sorry( widget, 00123 i18n( "The clipboard has changed since you used 'paste': " 00124 "the chosen data format is no longer applicable. " 00125 "Please copy again what you wanted to paste." ) ); 00126 return 0; 00127 } 00128 00129 const TQString result = dlg.lineEditText(); 00130 const TQCString chosenFormat = formats[ dlg.comboItem() ]; 00131 00132 kdDebug() << " result=" << result << " chosenFormat=" << chosenFormat << endl; 00133 KURL new_url( u ); 00134 new_url.addPath( result ); 00135 // if "data" came from TQClipboard, then it was deleted already - by a nice 0-seconds timer 00136 // In that case, get it again. Let's hope the user didn't copy something else meanwhile :/ 00137 if ( clipboard ) { 00138 data = TQApplication::clipboard()->data(); 00139 } 00140 const TQByteArray ba = data->encodedData( chosenFormat ); 00141 return pasteDataAsyncTo( new_url, ba ); 00142 } 00143 #endif 00144 00145 // KDE4: remove 00146 KIO_EXPORT bool KIO::isClipboardEmpty() 00147 { 00148 #ifndef QT_NO_MIMECLIPBOARD 00149 TQMimeSource *data = TQApplication::clipboard()->data(); 00150 if ( data->provides( "text/uri-list" ) && data->encodedData( "text/uri-list" ).size() > 0 ) 00151 return false; 00152 #else 00153 // Happens with some versions of Qt Embedded... :/ 00154 // Guess. 00155 TQString data = TQApplication::clipboard()->text(); 00156 if(data.contains("://")) 00157 return false; 00158 #endif 00159 return true; 00160 } 00161 00162 #ifndef QT_NO_MIMECLIPBOARD 00163 // The main method for dropping 00164 KIO::CopyJob* KIO::pasteMimeSource( TQMimeSource* data, const KURL& dest_url, 00165 const TQString& dialogText, TQWidget* widget, bool clipboard ) 00166 { 00167 TQByteArray ba; 00168 00169 // Now check for plain text 00170 // We don't want to display a mimetype choice for a TQTextDrag, those mimetypes look ugly. 00171 TQString text; 00172 if ( TQTextDrag::canDecode( data ) && TQTextDrag::decode( data, text ) ) 00173 { 00174 TQTextStream txtStream( ba, IO_WriteOnly ); 00175 txtStream << text; 00176 } 00177 else 00178 { 00179 TQValueVector<TQCString> formats; 00180 const char* fmt; 00181 for ( int i = 0; ( fmt = data->format( i ) ); ++i ) { 00182 if ( qstrcmp( fmt, "application/x-qiconlist" ) == 0 ) // see QIconDrag 00183 continue; 00184 if ( qstrcmp( fmt, "application/x-kde-cutselection" ) == 0 ) // see KonqDrag 00185 continue; 00186 if ( strchr( fmt, '/' ) == 0 ) // e.g. TARGETS, MULTIPLE, TIMESTAMP 00187 continue; 00188 formats.append( fmt ); 00189 } 00190 00191 if ( formats.size() == 0 ) 00192 return 0; 00193 00194 if ( formats.size() > 1 ) { 00195 return chooseAndPaste( dest_url, data, formats, dialogText, widget, clipboard ); 00196 } 00197 ba = data->encodedData( formats.first() ); 00198 } 00199 if ( ba.size() == 0 ) 00200 { 00201 KMessageBox::sorry(0, i18n("The clipboard is empty")); 00202 return 0; 00203 } 00204 00205 return pasteDataAsync( dest_url, ba, dialogText ); 00206 } 00207 #endif 00208 00209 // The main method for pasting 00210 KIO_EXPORT KIO::Job *KIO::pasteClipboard( const KURL& dest_url, bool move ) 00211 { 00212 if ( !dest_url.isValid() ) { 00213 KMessageBox::error( 0L, i18n( "Malformed URL\n%1" ).arg( dest_url.url() ) ); 00214 return 0; 00215 } 00216 00217 #ifndef QT_NO_MIMECLIPBOARD 00218 TQMimeSource *data = TQApplication::clipboard()->data(); 00219 00220 // First check for URLs. 00221 KURL::List urls; 00222 if ( KURLDrag::canDecode( data ) && KURLDrag::decode( data, urls ) ) { 00223 if ( urls.count() == 0 ) { 00224 KMessageBox::error( 0L, i18n("The clipboard is empty")); 00225 return 0; 00226 } 00227 00228 KIO::Job *res = 0; 00229 if ( move ) 00230 res = KIO::move( urls, dest_url ); 00231 else 00232 res = KIO::copy( urls, dest_url ); 00233 00234 // If moving, erase the clipboard contents, the original files don't exist anymore 00235 if ( move ) 00236 TQApplication::clipboard()->clear(); 00237 return res; 00238 } 00239 return pasteMimeSource( data, dest_url, TQString::null, 0 /*TODO parent widget*/, true /*clipboard*/ ); 00240 #else 00241 TQByteArray ba; 00242 TQTextStream txtStream( ba, IO_WriteOnly ); 00243 TQStringList data = TQStringList::split("\n", TQApplication::clipboard()->text()); 00244 KURL::List urls; 00245 KURLDrag::decode(data, urls); 00246 TQStringList::Iterator end(data.end()); 00247 for(TQStringList::Iterator it=data.begin(); it!=end; ++it) 00248 txtStream << *it; 00249 if ( ba.size() == 0 ) 00250 { 00251 KMessageBox::sorry(0, i18n("The clipboard is empty")); 00252 return 0; 00253 } 00254 return pasteDataAsync( dest_url, ba ); 00255 #endif 00256 } 00257 00258 00259 KIO_EXPORT void KIO::pasteData( const KURL& u, const TQByteArray& _data ) 00260 { 00261 KURL new_url = getNewFileName( u, TQString::null ); 00262 // We could use KIO::put here, but that would require a class 00263 // for the slotData call. With NetAccess, we can do a synchronous call. 00264 00265 if (new_url.isEmpty()) 00266 return; 00267 00268 KTempFile tempFile; 00269 tempFile.setAutoDelete( true ); 00270 tempFile.dataStream()->writeRawBytes( _data.data(), _data.size() ); 00271 tempFile.close(); 00272 00273 (void) KIO::NetAccess::upload( tempFile.name(), new_url, 0 ); 00274 } 00275 00276 KIO_EXPORT KIO::CopyJob* KIO::pasteDataAsync( const KURL& u, const TQByteArray& _data ) 00277 { 00278 return pasteDataAsync( u, _data, TQString::null ); 00279 } 00280 00281 KIO_EXPORT KIO::CopyJob* KIO::pasteDataAsync( const KURL& u, const TQByteArray& _data, const TQString& text ) 00282 { 00283 KURL new_url = getNewFileName( u, text ); 00284 00285 if (new_url.isEmpty()) 00286 return 0; 00287 00288 return pasteDataAsyncTo( new_url, _data ); 00289 } 00290 00291 KIO_EXPORT TQString KIO::pasteActionText() 00292 { 00293 TQMimeSource *data = TQApplication::clipboard()->data(); 00294 KURL::List urls; 00295 if ( KURLDrag::canDecode( data ) && KURLDrag::decode( data, urls ) ) { 00296 if ( urls.isEmpty() ) 00297 return TQString::null; // nothing to paste 00298 else if ( urls.first().isLocalFile() ) 00299 return i18n( "&Paste File", "&Paste %n Files", urls.count() ); 00300 else 00301 return i18n( "&Paste URL", "&Paste %n URLs", urls.count() ); 00302 } else if ( data->format(0) != 0 ) { 00303 return i18n( "&Paste Clipboard Contents" ); 00304 } else { 00305 return TQString::null; 00306 } 00307 } 00308