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