00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <qdir.h>
00021
00022 #include <kdebug.h>
00023 #include <kdesktopfile.h>
00024 #include <kdirwatch.h>
00025 #include <kinstance.h>
00026 #include <kinputdialog.h>
00027 #include <klocale.h>
00028 #include <kmessagebox.h>
00029 #include <kstandarddirs.h>
00030 #include <kprotocolinfo.h>
00031 #include <kpopupmenu.h>
00032 #include <krun.h>
00033
00034 #include <kio/job.h>
00035 #include <kio/renamedlg.h>
00036
00037 #include <kpropertiesdialog.h>
00038 #include "konq_operations.h"
00039 #include "konq_undo.h"
00040 #include "knewmenu.h"
00041 #include <utime.h>
00042
00043
00044 #include <qlayout.h>
00045 #include <qhbox.h>
00046 #include <klineedit.h>
00047 #include <kurlrequester.h>
00048 #include <qlabel.h>
00049 #include <qpopupmenu.h>
00050
00051 QValueList<KNewMenu::Entry> * KNewMenu::s_templatesList = 0L;
00052 int KNewMenu::s_templatesVersion = 0;
00053 bool KNewMenu::s_filesParsed = false;
00054 KDirWatch * KNewMenu::s_pDirWatch = 0L;
00055
00056 class KNewMenu::KNewMenuPrivate
00057 {
00058 public:
00059 KNewMenuPrivate() : m_parentWidget(0) {}
00060 KActionCollection * m_actionCollection;
00061 QString m_destPath;
00062 QWidget *m_parentWidget;
00063 KActionMenu *m_menuDev;
00064 };
00065
00066 KNewMenu::KNewMenu( KActionCollection * _collec, const char *name ) :
00067 KActionMenu( i18n( "Create New" ), "filenew", _collec, name ),
00068 menuItemsVersion( 0 )
00069 {
00070
00071
00072
00073 d = new KNewMenuPrivate;
00074 d->m_actionCollection = _collec;
00075 makeMenus();
00076 }
00077
00078 KNewMenu::KNewMenu( KActionCollection * _collec, QWidget *parentWidget, const char *name ) :
00079 KActionMenu( i18n( "Create New" ), "filenew", _collec, name ),
00080 menuItemsVersion( 0 )
00081 {
00082 d = new KNewMenuPrivate;
00083 d->m_actionCollection = _collec;
00084 d->m_parentWidget = parentWidget;
00085 makeMenus();
00086 }
00087
00088 KNewMenu::~KNewMenu()
00089 {
00090
00091 delete d;
00092 }
00093
00094 void KNewMenu::makeMenus()
00095 {
00096 d->m_menuDev = new KActionMenu( i18n( "Link to Device" ), "kcmdevices", d->m_actionCollection, "devnew" );
00097 }
00098
00099 void KNewMenu::slotCheckUpToDate( )
00100 {
00101
00102
00103
00104 if (menuItemsVersion < s_templatesVersion || s_templatesVersion == 0)
00105 {
00106
00107
00108
00109 QValueList<KAction*> actions = d->m_actionCollection->actions( "KNewMenu" );
00110 for( QValueListIterator<KAction*> it = actions.begin(); it != actions.end(); ++it )
00111 {
00112 remove( *it );
00113 d->m_actionCollection->remove( *it );
00114 }
00115
00116 if (!s_templatesList) {
00117 s_templatesList = new QValueList<Entry>();
00118 slotFillTemplates();
00119 parseFiles();
00120 }
00121
00122
00123
00124 if ( !s_filesParsed )
00125 parseFiles();
00126
00127 fillMenu();
00128
00129 menuItemsVersion = s_templatesVersion;
00130 }
00131 }
00132
00133 void KNewMenu::parseFiles()
00134 {
00135
00136 s_filesParsed = true;
00137 QValueList<Entry>::Iterator templ = s_templatesList->begin();
00138 for ( ; templ != s_templatesList->end(); ++templ)
00139 {
00140 QString iconname;
00141 QString filePath = (*templ).filePath;
00142 if ( !filePath.isEmpty() )
00143 {
00144 QString text;
00145 QString templatePath;
00146
00147
00148 if ( KDesktopFile::isDesktopFile( filePath ) ) {
00149 KSimpleConfig config( filePath, true );
00150 config.setDesktopGroup();
00151 text = config.readEntry("Name");
00152 (*templ).icon = config.readEntry("Icon");
00153 (*templ).comment = config.readEntry("Comment");
00154 QString type = config.readEntry( "Type" );
00155 if ( type == "Link" )
00156 {
00157 templatePath = config.readPathEntry("URL");
00158 if ( templatePath[0] != '/' )
00159 {
00160 if ( templatePath.startsWith("file:/") )
00161 templatePath = KURL(templatePath).path();
00162 else
00163 {
00164
00165 QString linkDir = filePath.left( filePath.findRev( '/' ) + 1 );
00166
00167 templatePath = linkDir + templatePath;
00168 }
00169 }
00170 }
00171 if ( templatePath.isEmpty() )
00172 {
00173
00174 (*templ).entryType = TEMPLATE;
00175 (*templ).templatePath = (*templ).filePath;
00176 } else {
00177 (*templ).entryType = LINKTOTEMPLATE;
00178 (*templ).templatePath = templatePath;
00179 }
00180
00181 }
00182 if (text.isEmpty())
00183 {
00184 text = KURL(filePath).fileName();
00185 if ( text.endsWith(".desktop") )
00186 text.truncate( text.length() - 8 );
00187 else if ( text.endsWith(".kdelnk") )
00188 text.truncate( text.length() - 7 );
00189 }
00190 (*templ).text = text;
00191
00192
00193
00194 }
00195 else {
00196 (*templ).entryType = SEPARATOR;
00197 }
00198 }
00199 }
00200
00201 void KNewMenu::fillMenu()
00202 {
00203
00204 popupMenu()->clear();
00205 d->m_menuDev->popupMenu()->clear();
00206
00207 KAction *linkURL = 0, *linkApp = 0;
00208
00209 int i = 1;
00210 QValueList<Entry>::Iterator templ = s_templatesList->begin();
00211 for ( ; templ != s_templatesList->end(); ++templ, ++i)
00212 {
00213 if ( (*templ).entryType != SEPARATOR )
00214 {
00215
00216
00217
00218
00219
00220
00221 bool bSkip = false;
00222
00223 QValueList<KAction*> actions = d->m_actionCollection->actions();
00224 QValueListIterator<KAction*> it = actions.begin();
00225 for( ; it != actions.end() && !bSkip; ++it )
00226 {
00227 if ( (*it)->text() == (*templ).text )
00228 {
00229 kdDebug(1203) << "KNewMenu: skipping " << (*templ).filePath << endl;
00230 bSkip = true;
00231 }
00232 }
00233
00234 if ( !bSkip )
00235 {
00236 Entry entry = *(s_templatesList->at( i-1 ));
00237
00238
00239 if ( (*templ).templatePath.endsWith( "emptydir" ) )
00240 {
00241 KAction * act = new KAction( (*templ).text, (*templ).icon, 0, this, SLOT( slotNewDir() ),
00242 d->m_actionCollection, QCString().sprintf("newmenu%d", i ) );
00243 act->setGroup( "KNewMenu" );
00244 act->plug( popupMenu() );
00245
00246 KActionSeparator *sep = new KActionSeparator();
00247 sep->plug( popupMenu() );
00248 }
00249 else
00250 {
00251 KAction * act = new KAction( (*templ).text, (*templ).icon, 0, this, SLOT( slotNewFile() ),
00252 d->m_actionCollection, QCString().sprintf("newmenu%d", i ) );
00253 act->setGroup( "KNewMenu" );
00254
00255 if ( (*templ).templatePath.endsWith( "URL.desktop" ) )
00256 {
00257 linkURL = act;
00258 }
00259 else if ( (*templ).templatePath.endsWith( "Program.desktop" ) )
00260 {
00261 linkApp = act;
00262 }
00263 else if ( KDesktopFile::isDesktopFile( entry.templatePath ) )
00264 {
00265 KDesktopFile df( entry.templatePath );
00266 if(df.readType() == "FSDevice")
00267 act->plug( d->m_menuDev->popupMenu() );
00268 else
00269 act->plug( popupMenu() );
00270 }
00271 else
00272 {
00273 act->plug( popupMenu() );
00274 }
00275 }
00276 }
00277 } else {
00278 Q_ASSERT( (*templ).entryType != 0 );
00279
00280 KActionSeparator * act = new KActionSeparator();
00281 act->plug( popupMenu() );
00282 }
00283 }
00284
00285 KActionSeparator * act = new KActionSeparator();
00286 act->plug( popupMenu() );
00287 if ( linkURL ) linkURL->plug( popupMenu() );
00288 if ( linkApp ) linkApp->plug( popupMenu() );
00289 d->m_menuDev->plug( popupMenu() );
00290 }
00291
00292 void KNewMenu::slotFillTemplates()
00293 {
00294
00295
00296 if ( ! s_pDirWatch )
00297 {
00298 s_pDirWatch = new KDirWatch;
00299 QStringList dirs = d->m_actionCollection->instance()->dirs()->resourceDirs("templates");
00300 for ( QStringList::Iterator it = dirs.begin() ; it != dirs.end() ; ++it )
00301 {
00302
00303 s_pDirWatch->addDir( *it );
00304 }
00305 connect ( s_pDirWatch, SIGNAL( dirty( const QString & ) ),
00306 this, SLOT ( slotFillTemplates() ) );
00307 connect ( s_pDirWatch, SIGNAL( created( const QString & ) ),
00308 this, SLOT ( slotFillTemplates() ) );
00309 connect ( s_pDirWatch, SIGNAL( deleted( const QString & ) ),
00310 this, SLOT ( slotFillTemplates() ) );
00311
00312 }
00313 s_templatesVersion++;
00314 s_filesParsed = false;
00315
00316 s_templatesList->clear();
00317
00318
00319 QStringList files = d->m_actionCollection->instance()->dirs()->findAllResources("templates");
00320 KSortableValueList<Entry,QString> slist;
00321 for ( QStringList::Iterator it = files.begin() ; it != files.end() ; ++it )
00322 {
00323
00324 if ( (*it)[0] != '.' )
00325 {
00326 Entry e;
00327 e.filePath = *it;
00328 e.entryType = 0;
00329
00330 if ( (*it).endsWith( "Directory.desktop" ) ||
00331 (*it).endsWith( "linkProgram.desktop" ) ||
00332 (*it).endsWith( "linkURL.desktop" ) )
00333 s_templatesList->prepend( e );
00334 else
00335 {
00336 KSimpleConfig config( *it, true );
00337 config.setDesktopGroup();
00338
00339
00340
00341 QString key = config.readEntry("Name");
00342 if ( (*it).endsWith( "TextFile.desktop" ) )
00343 key = "1_" + key;
00344 else
00345 key = "2_" + key;
00346
00347 slist.insert( key, e );
00348 }
00349 }
00350 }
00351 slist.sort();
00352 for(KSortableValueList<Entry, QString>::ConstIterator it = slist.begin(); it != slist.end(); ++it)
00353 {
00354 s_templatesList->append( (*it).value() );
00355 }
00356
00357 }
00358
00359 void KNewMenu::slotNewDir()
00360 {
00361 emit activated();
00362
00363 if (popupFiles.isEmpty())
00364 return;
00365
00366 KonqOperations::newDir(d->m_parentWidget, popupFiles.first());
00367 }
00368
00369 void KNewMenu::slotNewFile()
00370 {
00371 int id = QString( sender()->name() + 7 ).toInt();
00372 if (id == 0)
00373 {
00374
00375 KRun::runCommand(QString(sender()->name()));
00376 return;
00377 }
00378
00379 emit activated();
00380
00381 Entry entry = *(s_templatesList->at( id - 1 ));
00382
00383
00384 if ( !QFile::exists( entry.templatePath ) ) {
00385 kdWarning(1203) << entry.templatePath << " doesn't exist" << endl;
00386 KMessageBox::sorry( 0L, i18n("<qt>The template file <b>%1</b> does not exist.</qt>").arg(entry.templatePath));
00387 return;
00388 }
00389 m_isURLDesktopFile = false;
00390 QString name;
00391 if ( KDesktopFile::isDesktopFile( entry.templatePath ) )
00392 {
00393 KDesktopFile df( entry.templatePath );
00394
00395 if ( df.readType() == "Link" )
00396 {
00397 m_isURLDesktopFile = true;
00398
00399 KURLDesktopFileDlg dlg( i18n("File name:"), entry.comment, d->m_parentWidget );
00400
00401 if ( dlg.exec() )
00402 {
00403 name = dlg.fileName();
00404 m_linkURL = dlg.url();
00405 if ( name.isEmpty() || m_linkURL.isEmpty() )
00406 return;
00407 if ( !name.endsWith( ".desktop" ) )
00408 name += ".desktop";
00409 }
00410 else
00411 return;
00412 }
00413 else
00414 {
00415 KURL::List::Iterator it = popupFiles.begin();
00416 for ( ; it != popupFiles.end(); ++it )
00417 {
00418
00419
00420
00421 QString text = entry.text;
00422 text.replace( "...", QString::null );
00423
00424 KURL defaultFile( *it );
00425 defaultFile.addPath( KIO::encodeFileName( text ) );
00426 if ( defaultFile.isLocalFile() && QFile::exists( defaultFile.path() ) )
00427 text = KIO::RenameDlg::suggestName( *it, text);
00428
00429 KURL templateURL;
00430 templateURL.setPath( entry.templatePath );
00431 (void) new KPropertiesDialog( templateURL, *it, text, d->m_parentWidget );
00432 }
00433 return;
00434 }
00435 }
00436 else
00437 {
00438
00439
00440 bool ok;
00441 QString text = entry.text;
00442 text.replace( "...", QString::null );
00443
00444 KURL defaultFile( *(popupFiles.begin()) );
00445 defaultFile.addPath( KIO::encodeFileName( text ) );
00446 if ( defaultFile.isLocalFile() && QFile::exists( defaultFile.path() ) )
00447 text = KIO::RenameDlg::suggestName( *(popupFiles.begin()), text);
00448
00449 name = KInputDialog::getText( QString::null, entry.comment,
00450 text, &ok, d->m_parentWidget );
00451 if ( !ok )
00452 return;
00453 }
00454
00455
00456
00457 KURL::List::Iterator it = popupFiles.begin();
00458
00459 QString src = entry.templatePath;
00460 for ( ; it != popupFiles.end(); ++it )
00461 {
00462 KURL dest( *it );
00463 dest.addPath( KIO::encodeFileName(name) );
00464 d->m_destPath = dest.path();
00465
00466 KURL uSrc;
00467 uSrc.setPath( src );
00468
00469 KIO::CopyJob * job = KIO::copyAs( uSrc, dest );
00470 job->setDefaultPermissions( true );
00471 connect( job, SIGNAL( result( KIO::Job * ) ),
00472 SLOT( slotResult( KIO::Job * ) ) );
00473 if ( m_isURLDesktopFile )
00474 connect( job, SIGNAL( renamed( KIO::Job *, const KURL&, const KURL& ) ),
00475 SLOT( slotRenamed( KIO::Job *, const KURL&, const KURL& ) ) );
00476 KURL::List lst;
00477 lst.append( uSrc );
00478 (void)new KonqCommandRecorder( KonqCommand::COPY, lst, dest, job );
00479 }
00480 }
00481
00482
00483
00484 void KNewMenu::slotRenamed( KIO::Job *, const KURL& from , const KURL& to )
00485 {
00486 if ( from.isLocalFile() )
00487 {
00488 kdDebug() << k_funcinfo << from.prettyURL() << " -> " << to.prettyURL() << " ( m_destPath=" << d->m_destPath << ")" << endl;
00489 Q_ASSERT( from.path() == d->m_destPath );
00490 d->m_destPath = to.path();
00491 }
00492 }
00493
00494 void KNewMenu::slotResult( KIO::Job * job )
00495 {
00496 if (job->error())
00497 job->showErrorDialog();
00498 else
00499 {
00500 KURL destURL = static_cast<KIO::CopyJob*>(job)->destURL();
00501 if ( destURL.isLocalFile() )
00502 {
00503 if ( m_isURLDesktopFile )
00504 {
00505
00506
00507 kdDebug(1203) << " destURL=" << destURL.path() << " " << " d->m_destPath=" << d->m_destPath << endl;
00508 KDesktopFile df( d->m_destPath );
00509 df.writeEntry( "Icon", KProtocolInfo::icon( KURL(m_linkURL).protocol() ) );
00510 df.writePathEntry( "URL", m_linkURL );
00511 df.sync();
00512 }
00513 else
00514 {
00515
00516 (void) ::utime( QFile::encodeName( destURL.path() ), 0 );
00517 }
00518 }
00519 }
00520 }
00521
00523
00524 KURLDesktopFileDlg::KURLDesktopFileDlg( const QString& textFileName, const QString& textUrl )
00525 : KDialogBase( Plain, QString::null, Ok|Cancel|User1, Ok, 0L , 0L, true,
00526 true, KStdGuiItem::clear() )
00527 {
00528 initDialog( textFileName, QString::null, textUrl, QString::null );
00529 }
00530
00531 KURLDesktopFileDlg::KURLDesktopFileDlg( const QString& textFileName, const QString& textUrl, QWidget *parent )
00532 : KDialogBase( Plain, QString::null, Ok|Cancel|User1, Ok, parent, 0L, true,
00533 true, KStdGuiItem::clear() )
00534 {
00535 initDialog( textFileName, QString::null, textUrl, QString::null );
00536 }
00537
00538 void KURLDesktopFileDlg::initDialog( const QString& textFileName, const QString& defaultName, const QString& textUrl, const QString& defaultUrl )
00539 {
00540 QVBoxLayout * topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() );
00541
00542
00543 QHBox * fileNameBox = new QHBox( plainPage() );
00544 topLayout->addWidget( fileNameBox );
00545
00546 QLabel * label = new QLabel( textFileName, fileNameBox );
00547 m_leFileName = new KLineEdit( fileNameBox, 0L );
00548 m_leFileName->setMinimumWidth(m_leFileName->sizeHint().width() * 3);
00549 label->setBuddy(m_leFileName);
00550 m_leFileName->setText( defaultName );
00551 m_leFileName->setSelection(0, m_leFileName->text().length());
00552 connect( m_leFileName, SIGNAL(textChanged(const QString&)),
00553 SLOT(slotNameTextChanged(const QString&)) );
00554
00555
00556 QHBox * urlBox = new QHBox( plainPage() );
00557 topLayout->addWidget( urlBox );
00558 label = new QLabel( textUrl, urlBox );
00559 m_urlRequester = new KURLRequester( defaultUrl, urlBox, "urlRequester" );
00560 m_urlRequester->setMode( KFile::File | KFile::Directory );
00561
00562 m_urlRequester->setMinimumWidth( m_urlRequester->sizeHint().width() * 3 );
00563 connect( m_urlRequester->lineEdit(), SIGNAL(textChanged(const QString&)),
00564 SLOT(slotURLTextChanged(const QString&)) );
00565 label->setBuddy(m_urlRequester);
00566
00567 m_urlRequester->setFocus();
00568 enableButtonOK( !defaultName.isEmpty() && !defaultUrl.isEmpty() );
00569 connect( this, SIGNAL(user1Clicked()), this, SLOT(slotClear()) );
00570 m_fileNameEdited = false;
00571 }
00572
00573 QString KURLDesktopFileDlg::url() const
00574 {
00575 if ( result() == QDialog::Accepted )
00576 return m_urlRequester->url();
00577 else
00578 return QString::null;
00579 }
00580
00581 QString KURLDesktopFileDlg::fileName() const
00582 {
00583 if ( result() == QDialog::Accepted )
00584 return m_leFileName->text();
00585 else
00586 return QString::null;
00587 }
00588
00589 void KURLDesktopFileDlg::slotClear()
00590 {
00591 m_leFileName->setText( QString::null );
00592 m_urlRequester->clear();
00593 m_fileNameEdited = false;
00594 }
00595
00596 void KURLDesktopFileDlg::slotNameTextChanged( const QString& )
00597 {
00598 kdDebug() << k_funcinfo << endl;
00599 m_fileNameEdited = true;
00600 enableButtonOK( !m_leFileName->text().isEmpty() && !m_urlRequester->url().isEmpty() );
00601 }
00602
00603 void KURLDesktopFileDlg::slotURLTextChanged( const QString& )
00604 {
00605 if ( !m_fileNameEdited )
00606 {
00607
00608
00609
00610 KURL url( m_urlRequester->url() );
00611 if ( KProtocolInfo::supportsListing( url ) )
00612 m_leFileName->setText( url.fileName() );
00613 else
00614 m_leFileName->setText( url.url() );
00615 m_fileNameEdited = false;
00616 }
00617 enableButtonOK( !m_leFileName->text().isEmpty() && !m_urlRequester->url().isEmpty() );
00618 }
00619
00620
00621 #include "knewmenu.moc"