25 #include <QVBoxLayout>
59 if (!name.isEmpty() && (!isfile || name[0] ==
'\\'))
64 if (!expandedName.isEmpty())
72 class KNewFileMenuSingleton
75 KNewFileMenuSingleton()
83 ~KNewFileMenuSingleton()
103 enum EntryType {
Unknown, LinkToTemplate = 1, Template, Separator };
129 EntryList * templatesList;
136 int templatesVersion;
139 void KNewFileMenuSingleton::parseFiles()
143 QMutableListIterator<KNewFileMenuSingleton::Entry> templIter(*templatesList);
144 while (templIter.hasNext()) {
145 KNewFileMenuSingleton::Entry& templ = templIter.next();
146 const QString filePath = templ.filePath;
147 if (!filePath.isEmpty())
155 if (desktopFile.noDisplay()) {
159 text = desktopFile.readName();
160 templ.icon = desktopFile.readIcon();
161 templ.comment = desktopFile.readComment();
162 QString type = desktopFile.readType();
165 templatePath = desktopFile.desktopGroup().readPathEntry(
"URL",
QString());
166 if (templatePath[0] !=
'/' && !templatePath.startsWith(
"__"))
168 if (templatePath.startsWith(
"file:/"))
173 QString linkDir = filePath.left(filePath.lastIndexOf(
'/') + 1 );
175 templatePath = linkDir + templatePath;
179 if (templatePath.isEmpty())
182 templ.entryType = KNewFileMenuSingleton::Template;
183 templ.templatePath = templ.filePath;
185 templ.entryType = KNewFileMenuSingleton::LinkToTemplate;
186 templ.templatePath = templatePath;
193 if (text.endsWith(
".desktop"))
194 text.truncate(text.length() - 8);
202 templ.entryType = KNewFileMenuSingleton::Separator;
209 class KNewFileMenuCopyData
212 KNewFileMenuCopyData() { m_isSymlink =
false;}
213 ~KNewFileMenuCopyData() {}
214 QString chosenFileName()
const {
return m_chosenFileName; }
217 QString sourceFileToCopy()
const {
return m_src; }
218 QString tempFileToDelete()
const {
return m_tempFileToDelete; }
227 class KNewFileMenuPrivate
231 : m_menuItemsVersion(0),
233 m_viewShowsHiddenFiles(false),
237 bool checkSourceExists(
const QString& src);
242 void confirmCreatingHiddenDir(
const QString& name);
247 void executeOtherDesktopFile(
const KNewFileMenuSingleton::Entry& entry);
252 void executeRealFileOrDir(
const KNewFileMenuSingleton::Entry& entry);
257 void executeStrategy();
262 void executeSymLink(
const KNewFileMenuSingleton::Entry& entry);
267 void executeUrlDesktopFile(
const KNewFileMenuSingleton::Entry& entry);
277 void _k_slotAbortDialog();
282 void _k_slotActionTriggered(
QAction* action);
287 void _k_slotCreateDirectory(
bool writeHiddenDir =
false);
293 void _k_slotCreateHiddenDirectory();
298 void _k_slotFillTemplates();
304 void _k_slotOtherDesktopFile();
310 void _k_slotRealFileOrDir();
316 void _k_slotTextChanged(
const QString & text);
322 void _k_slotSymLink();
328 void _k_slotUrlDesktopFile();
335 int m_menuItemsVersion;
342 QActionGroup* m_newMenuGroup;
354 bool m_viewShowsHiddenFiles;
358 KNewFileMenuCopyData m_copyData;
361 bool KNewFileMenuPrivate::checkSourceExists(
const QString& src)
363 if (!QFile::exists(src)) {
364 kWarning(1203) << src <<
"doesn't exist" ;
367 dialog->setCaption(
i18n(
"Sorry") );
368 dialog->setButtons( KDialog::Ok );
369 dialog->setObjectName(
"sorry" );
370 dialog->setModal(q->isModal());
371 dialog->setAttribute(Qt::WA_DeleteOnClose);
372 dialog->setDefaultButton( KDialog::Ok );
373 dialog->setEscapeButton( KDialog::Ok );
376 i18n(
"<qt>The template file <b>%1</b> does not exist.</qt>", src),
387 void KNewFileMenuPrivate::confirmCreatingHiddenDir(
const QString& name)
390 _k_slotCreateHiddenDirectory();
395 continueGuiItem.setText(
i18nc(
"@action:button",
"Create directory"));
397 cancelGuiItem.setText(
i18nc(
"@action:button",
"Enter a different name"));
400 confirmDialog->setCaption(
i18n(
"Create hidden directory?"));
401 confirmDialog->setModal(m_modal);
402 confirmDialog->setAttribute(Qt::WA_DeleteOnClose);
404 i18n(
"The name \"%1\" starts with a dot, so the directory will be hidden by default.", name),
406 i18n(
"Do not ask again"),
410 confirmDialog->setButtonGuiItem(KDialog::Ok, continueGuiItem);
411 confirmDialog->setButtonGuiItem(KDialog::Cancel, cancelGuiItem);
413 QObject::connect(confirmDialog, SIGNAL(accepted()), q, SLOT(_k_slotCreateHiddenDirectory()));
414 QObject::connect(confirmDialog, SIGNAL(rejected()), q, SLOT(createDirectory()));
416 m_fileDialog = confirmDialog;
417 confirmDialog->show();
421 void KNewFileMenuPrivate::executeOtherDesktopFile(
const KNewFileMenuSingleton::Entry& entry)
423 if (!checkSourceExists(entry.templatePath)) {
427 KUrl::List::const_iterator it = m_popupFiles.constBegin();
428 for (; it != m_popupFiles.constEnd(); ++it)
432 text = text.trimmed();
436 KUrl defaultFile(*it);
438 if (defaultFile.isLocalFile() && QFile::exists(defaultFile.toLocalFile()))
441 const KUrl templateUrl(entry.templatePath);
444 dlg->setModal(q->isModal());
445 dlg->setAttribute(Qt::WA_DeleteOnClose);
446 QObject::connect(dlg, SIGNAL(applied()), q, SLOT(_k_slotOtherDesktopFile()));
452 void KNewFileMenuPrivate::executeRealFileOrDir(
const KNewFileMenuSingleton::Entry& entry)
458 text = text.trimmed();
459 m_copyData.m_src = entry.templatePath;
461 KUrl defaultFile(m_popupFiles.first());
463 if (defaultFile.isLocalFile() && QFile::exists(defaultFile.toLocalFile()))
467 fileDialog->setAttribute(Qt::WA_DeleteOnClose);
468 fileDialog->setModal(q->isModal());
469 fileDialog->setButtons(KDialog::Ok | KDialog::Cancel);
472 QVBoxLayout *layout =
new QVBoxLayout(mainWidget);
482 _k_slotTextChanged(text);
483 QObject::connect(lineEdit, SIGNAL(textChanged(
QString)), q, SLOT(_k_slotTextChanged(
QString)));
485 layout->addWidget(label);
486 layout->addWidget(lineEdit);
488 fileDialog->setMainWidget(mainWidget);
489 QObject::connect(fileDialog, SIGNAL(accepted()), q, SLOT(_k_slotRealFileOrDir()));
490 QObject::connect(fileDialog, SIGNAL(rejected()), q, SLOT(_k_slotAbortDialog()));
493 lineEdit->selectAll();
494 lineEdit->setFocus();
497 void KNewFileMenuPrivate::executeSymLink(
const KNewFileMenuSingleton::Entry& entry)
500 dlg->setModal(q->isModal());
501 dlg->setAttribute(Qt::WA_DeleteOnClose);
502 dlg->setCaption(
i18n(
"Create Symlink"));
504 QObject::connect(dlg, SIGNAL(accepted()), q, SLOT(_k_slotSymLink()));
508 void KNewFileMenuPrivate::executeStrategy()
510 m_tempFileToDelete = m_copyData.tempFileToDelete();
511 const QString src = m_copyData.sourceFileToCopy();
517 if (uSrc.isLocalFile()) {
522 uSrc.setPath(item.linkDest());
524 if (!m_copyData.m_isSymlink) {
527 QFile srcFile(uSrc.toLocalFile());
528 if (srcFile.open(QIODevice::ReadOnly)) {
529 KMimeType::Ptr wantedMime = KMimeType::findByUrl(uSrc);
530 KMimeType::Ptr mime = KMimeType::findByNameAndContent(m_copyData.m_chosenFileName, srcFile.read(1024));
532 if (!mime->is(wantedMime->name()))
533 chosenFileName += wantedMime->mainExtension();
540 KUrl::List::const_iterator it = m_popupFiles.constBegin();
541 for (; it != m_popupFiles.constEnd(); ++it)
549 if (m_copyData.m_isSymlink) {
561 kjob->ui()->setWindow(m_parentWidget);
562 QObject::connect(kjob, SIGNAL(result(
KJob*)), q, SLOT(slotResult(
KJob*)));
566 void KNewFileMenuPrivate::executeUrlDesktopFile(
const KNewFileMenuSingleton::Entry& entry)
569 m_copyData.m_templatePath = entry.templatePath;
570 dlg->setModal(q->isModal());
571 dlg->setAttribute(Qt::WA_DeleteOnClose);
572 dlg->setCaption(
i18n(
"Create link to URL"));
574 QObject::connect(dlg, SIGNAL(accepted()), q, SLOT(_k_slotUrlDesktopFile()));
578 void KNewFileMenuPrivate::fillMenu()
580 QMenu* menu = q->menu();
582 m_menuDev->menu()->clear();
591 KNewFileMenuSingleton* s = kNewMenuGlobals;
593 KNewFileMenuSingleton::EntryList::iterator templ = s->templatesList->begin();
594 const KNewFileMenuSingleton::EntryList::iterator templ_end = s->templatesList->end();
595 for (; templ != templ_end; ++templ, ++i)
597 KNewFileMenuSingleton::Entry& entry = *templ;
598 if (entry.entryType != KNewFileMenuSingleton::Separator) {
605 const bool bSkip = seenTexts.contains(entry.text);
607 kDebug(1203) <<
"skipping" << entry.filePath;
609 seenTexts.insert(entry.text);
612 const QString templatePath = entry.templatePath;
614 if (templatePath.endsWith(
"emptydir")) {
616 m_newDirAction = act;
617 act->setIcon(
KIcon(entry.icon));
618 act->setText(
i18nc(
"@item:inmenu Create New",
"%1", entry.text));
619 act->setActionGroup(m_newMenuGroup);
620 menu->addAction(act);
623 sep->setSeparator(
true);
624 menu->addAction(sep);
627 if (!m_supportedMimeTypes.isEmpty()) {
631 const bool createSymlink = entry.templatePath ==
"__CREATE_SYMLINK__";
638 if (entry.mimeType.isEmpty()) {
639 mime = KMimeType::findByPath(entry.templatePath);
642 entry.mimeType = mime->name();
644 entry.mimeType = KMimeType::defaultMimeType();
647 mime = KMimeType::mimeType(entry.mimeType);
649 Q_FOREACH(
const QString& supportedMime, m_supportedMimeTypes) {
650 if (mime && mime->is(supportedMime)) {
665 act->setIcon(
KIcon(entry.icon));
666 act->setText(
i18nc(
"@item:inmenu Create New",
"%1", entry.text));
667 act->setActionGroup(m_newMenuGroup);
671 if (templatePath.endsWith(
"/URL.desktop")) {
673 }
else if (templatePath.endsWith(
"/Program.desktop")) {
675 }
else if (entry.filePath.endsWith(
"/linkPath.desktop")) {
679 if (df.readType() ==
"FSDevice")
680 m_menuDev->menu()->addAction(act);
682 menu->addAction(act);
686 menu->addAction(act);
691 Q_ASSERT(entry.entryType != 0);
694 sep->setSeparator(
true);
695 menu->addAction(sep);
699 if (m_supportedMimeTypes.isEmpty()) {
701 sep->setSeparator(
true);
702 menu->addAction(sep);
703 if (linkURL) menu->addAction(linkURL);
704 if (linkPath) menu->addAction(linkPath);
705 if (linkApp) menu->addAction(linkApp);
707 menu->addAction(m_menuDev);
711 void KNewFileMenuPrivate::_k_slotAbortDialog()
716 void KNewFileMenuPrivate::_k_slotActionTriggered(
QAction* action)
720 if (action == m_newDirAction) {
721 q->createDirectory();
724 const int id = action->data().toInt();
727 KNewFileMenuSingleton* s = kNewMenuGlobals;
728 const KNewFileMenuSingleton::Entry entry = s->templatesList->at(
id - 1);
730 const bool createSymlink = entry.templatePath ==
"__CREATE_SYMLINK__";
732 m_copyData = KNewFileMenuCopyData();
735 m_copyData.m_isSymlink =
true;
736 executeSymLink(entry);
740 if (df.readType() ==
"Link") {
741 executeUrlDesktopFile(entry);
743 executeOtherDesktopFile(entry);
747 executeRealFileOrDir(entry);
752 void KNewFileMenuPrivate::_k_slotCreateDirectory(
bool writeHiddenDir)
755 KUrl baseUrl = m_popupFiles.first();
756 bool askAgain =
false;
760 if (!name.isEmpty()) {
761 if ((name[0] ==
'/'))
764 if (!m_viewShowsHiddenFiles && name.startsWith(
'.')) {
765 if (!writeHiddenDir) {
766 confirmCreatingHiddenDir(name);
778 job->setProperty(
"isMkdirJob",
true);
779 job->ui()->setWindow(m_parentWidget);
780 job->ui()->setAutoErrorHandlingEnabled(
true);
785 job->ui()->setAutoErrorHandlingEnabled(
false);
786 QObject::connect(job, SIGNAL(result(
KJob*)), q, SLOT(slotResult(
KJob*)));
790 q->createDirectory();
792 _k_slotAbortDialog();
795 void KNewFileMenuPrivate::_k_slotCreateHiddenDirectory()
797 _k_slotCreateDirectory(
true);
800 void KNewFileMenuPrivate::_k_slotFillTemplates()
802 KNewFileMenuSingleton* s = kNewMenuGlobals;
808 for (QStringList::const_iterator it = dirs.constBegin() ; it != dirs.constEnd() ; ++it) {
810 s->dirWatch->addDir(*it);
812 QObject::connect(s->dirWatch, SIGNAL(dirty(
QString)),
813 q, SLOT(_k_slotFillTemplates()));
814 QObject::connect(s->dirWatch, SIGNAL(created(
QString)),
815 q, SLOT(_k_slotFillTemplates()));
816 QObject::connect(s->dirWatch, SIGNAL(deleted(
QString)),
817 q, SLOT(_k_slotFillTemplates()));
820 ++s->templatesVersion;
821 s->filesParsed =
false;
823 s->templatesList->clear();
826 const QStringList files = m_actionCollection->componentData().dirs()->findAllResources(
"templates");
828 Q_FOREACH(
const QString& file, files) {
830 if (file[0] !=
'.') {
831 KNewFileMenuSingleton::Entry e;
833 e.entryType = KNewFileMenuSingleton::Unknown;
841 if (file.endsWith(
"Directory.desktop")) {
843 }
else if (file.endsWith(
"TextFile.desktop")) {
848 slist.insert(key, e);
851 (*s->templatesList) += slist.values();
854 void KNewFileMenuPrivate::_k_slotOtherDesktopFile()
859 void KNewFileMenuPrivate::_k_slotRealFileOrDir()
861 m_copyData.m_chosenFileName = m_text;
862 _k_slotAbortDialog();
866 void KNewFileMenuPrivate::_k_slotSymLink()
870 m_copyData.m_chosenFileName = dlg->
name();
873 if (m_copyData.m_chosenFileName.isEmpty() || linkUrl.isEmpty())
876 if (linkUrl.isRelative())
877 m_copyData.m_src =
QUrl(linkUrl).toString();
882 dialog->setCaption(
i18n(
"Sorry") );
883 dialog->setButtons( KDialog::Ok );
884 dialog->setObjectName(
"sorry" );
885 dialog->setModal(m_modal);
886 dialog->setAttribute(Qt::WA_DeleteOnClose);
887 dialog->setDefaultButton( KDialog::Ok );
888 dialog->setEscapeButton( KDialog::Ok );
889 m_fileDialog = dialog;
892 i18n(
"Basic links can only point to local files or directories.\nPlease use \"Link to Location\" for remote URLs."),
902 void KNewFileMenuPrivate::_k_slotTextChanged(
const QString & text)
907 void KNewFileMenuPrivate::_k_slotUrlDesktopFile()
911 m_copyData.m_chosenFileName = dlg->
name();
923 linkUrl = uriData.
uri();
926 if (m_copyData.m_chosenFileName.isEmpty() || linkUrl.isEmpty())
932 tmpFile.setAutoRemove(
false);
933 if (!tmpFile.open()) {
934 kError() <<
"Couldn't create temp file!";
938 if (!checkSourceExists(m_copyData.m_templatePath)) {
943 QFile file(m_copyData.m_templatePath);
944 if (!file.open(QIODevice::ReadOnly)) {
945 kError() <<
"Couldn't open template" << m_copyData.m_templatePath;
948 const QByteArray data = file.readAll();
950 const QString tempFileName = tmpFile.fileName();
951 Q_ASSERT(!tempFileName.isEmpty());
961 m_copyData.m_src = tempFileName;
962 m_copyData.m_tempFileToDelete = tempFileName;
969 d(new KNewFileMenuPrivate(this))
973 d->m_newMenuGroup =
new QActionGroup(
this);
975 d->m_actionCollection = collection;
976 d->m_parentWidget = qobject_cast<
QWidget*>(parent);
977 d->m_newDirAction = 0;
979 d->m_actionCollection->addAction(name,
this);
992 KNewFileMenuSingleton* s = kNewMenuGlobals;
995 if (d->m_menuItemsVersion < s->templatesVersion || s->templatesVersion == 0) {
999 foreach (
QAction* action, d->m_newMenuGroup->actions())
1002 if (!s->templatesList) {
1004 d->_k_slotFillTemplates();
1010 if (!s->filesParsed) {
1016 d->m_menuItemsVersion = s->templatesVersion;
1022 if (d->m_popupFiles.isEmpty())
1025 KUrl baseUrl = d->m_popupFiles.first();
1026 QString name = d->m_text.isEmpty()?
i18nc(
"Default name for a new folder",
"New Folder") :
1033 fileDialog->setModal(
isModal());
1034 fileDialog->setAttribute(Qt::WA_DeleteOnClose);
1035 fileDialog->setButtons(KDialog::Ok | KDialog::Cancel);
1036 fileDialog->setCaption(
i18nc(
"@title:window",
"New Folder"));
1039 QVBoxLayout *layout =
new QVBoxLayout(mainWidget);
1049 d->_k_slotTextChanged(name);
1050 connect(lineEdit, SIGNAL(textChanged(
QString)),
this, SLOT(_k_slotTextChanged(
QString)));
1051 layout->addWidget(label);
1052 layout->addWidget(lineEdit);
1054 fileDialog->setMainWidget(mainWidget);
1055 connect(fileDialog, SIGNAL(accepted()),
this, SLOT(_k_slotCreateDirectory()));
1056 connect(fileDialog, SIGNAL(rejected()),
this, SLOT(_k_slotAbortDialog()));
1058 d->m_fileDialog = fileDialog;
1061 lineEdit->selectAll();
1062 lineEdit->setFocus();
1072 return d->m_popupFiles;
1082 d->m_popupFiles = files;
1083 if (files.isEmpty()) {
1084 d->m_newMenuGroup->setEnabled(
false);
1086 KUrl firstUrl = files.first();
1088 d->m_newMenuGroup->setEnabled(
true);
1089 if (d->m_newDirAction) {
1093 d->m_newMenuGroup->setEnabled(
true);
1101 d->m_parentWidget = parentWidget;
1106 d->m_supportedMimeTypes = mime;
1111 d->m_viewShowsHiddenFiles = b;
1117 static_cast<KIO::Job*
>(job)->ui()->showErrorMessage();
1129 }
else if (
KIO::SimpleJob* simpleJob = ::qobject_cast<KIO::SimpleJob*>(job)) {
1131 if (simpleJob->property(
"isMkdirJob").toBool() ==
true) {
1132 kDebug() <<
"Emit directoryCreated" << simpleJob->url();
1139 if (!d->m_tempFileToDelete.isEmpty())
1140 QFile::remove(d->m_tempFileToDelete);
1146 return d->m_supportedMimeTypes;
1150 #include "knewfilemenu.moc"
QString i18n(const char *text)
void writePathEntry(const QString &pKey, const QString &path, WriteConfigFlags pFlags=Normal)
QString label(StandardShortcut id)
SimpleJob * mkdir(const KUrl &url, int permissions=-1)
static QDebug kError(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
void writeEntry(const QString &key, const QVariant &value, WriteConfigFlags pFlags=Normal)
QString toLocalFile(AdjustPathOption trailing=LeaveTrailingSlash) const
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
static int createKMessageBox(KDialog *dialog, QMessageBox::Icon icon, const QString &text, const QStringList &strlist, const QString &ask, bool *checkboxReturn, Options options, const QString &details=QString())
static bool shouldBeShownContinue(const QString &dontShowAgainName)
CopyJob * copyAs(const KUrl &src, const KUrl &dest, JobFlags flags=DefaultFlags)
QString i18nc(const char *ctxt, const char *text)
KSharedConfigPtr config()
void setPath(const QString &path)
void setData(const KUrl &url)
void addPath(const QString &txt)
static QString icon(const QString &protocol)
QString encodeFileName(const QString &str)
static bool supportsMakeDir(const KUrl &url)
QString pathOrUrl() const
void setDefaultPermissions(bool b)
SimpleJob * symlink(const QString &target, const KUrl &dest, JobFlags flags=DefaultFlags)
static KUriFilter * self()
QStringList resourceDirs(const char *type) const
static KUrl mostLocalUrl(const KUrl &url, QWidget *window)
void triggered(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
static bool isDesktopFile(const QString &path)
QString fileName(const DirectoryOptions &options=IgnoreTrailingSlash) const
QString tildeExpand(const QString &path)
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
void setClearButtonShown(bool show)
static FileUndoManager * self()
virtual void setText(const QString &)
int utime(const QString &filename, struct utimbuf *buf)
static bool supportsWriting(const KUrl &url)
QString prettyUrl(AdjustPathOption trailing=LeaveTrailingSlash) const
void setCheckForExecutables(bool check)
void recordJob(CommandType op, const KUrl::List &src, const KUrl &dst, KIO::Job *job)