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