• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdevelop API Reference
  • KDE Home
  • Contact Us
 

kdevplatform/project

  • sources
  • kfour-appscomplete
  • kdevelop
  • kdevplatform
  • project
abstractfilemanagerplugin.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * This file is part of KDevelop *
3  * Copyright 2010-2012 Milian Wolff <[email protected]> *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU Library General Public License as *
7  * published by the Free Software Foundation; either version 2 of the *
8  * License, or (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU Library General Public *
16  * License along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19  ***************************************************************************/
20 
21 #include "abstractfilemanagerplugin.h"
22 
23 #include "filemanagerlistjob.h"
24 #include "projectmodel.h"
25 #include "helper.h"
26 
27 #include <QHashIterator>
28 #include <QFileInfo>
29 #include <QApplication>
30 #include <QTimer>
31 #ifdef TIME_IMPORT_JOB
32 #include <QElapsedTimer>
33 #endif
34 
35 #include <KMessageBox>
36 #include <KLocalizedString>
37 #include <KDirWatch>
38 
39 #include <interfaces/iproject.h>
40 #include <interfaces/icore.h>
41 #include <interfaces/iprojectcontroller.h>
42 #include <serialization/indexedstring.h>
43 
44 #include "projectfiltermanager.h"
45 #include "debug.h"
46 
47 #define ifDebug(x)
48 
49 using namespace KDevelop;
50 
51 //BEGIN Helper
52 
53 namespace {
54 
58 ProjectFolderItem* parentFolder(ProjectBaseItem* item)
59 {
60  if ( item->parent() ) {
61  return static_cast<ProjectFolderItem*>(item->parent());
62  } else {
63  return item->project()->projectItem();
64  }
65 }
66 
67 }
68 
69 //END Helper
70 
71 //BEGIN Private
72 
73 class KDevelop::AbstractFileManagerPluginPrivate
74 {
75 public:
76  explicit AbstractFileManagerPluginPrivate(AbstractFileManagerPlugin* qq)
77  : q(qq)
78  {
79  }
80 
81  AbstractFileManagerPlugin* q;
82 
87  Q_REQUIRED_RESULT KIO::Job* eventuallyReadFolder(ProjectFolderItem* item);
88  void addJobItems(FileManagerListJob* job,
89  ProjectFolderItem* baseItem,
90  const KIO::UDSEntryList& entries);
91 
92  void deleted(const QString &path);
93  void created(const QString &path);
94 
95  void projectClosing(IProject* project);
96  void jobFinished(KJob* job);
97 
99  void stopWatcher(ProjectFolderItem* folder);
101  void continueWatcher(ProjectFolderItem* folder);
103  bool rename(ProjectBaseItem* item, const Path& newPath);
104 
105  QHash<IProject*, KDirWatch*> m_watchers;
106  QHash<IProject*, QList<FileManagerListJob*> > m_projectJobs;
107  QVector<QString> m_stoppedFolders;
108  ProjectFilterManager m_filters;
109 };
110 
111 void AbstractFileManagerPluginPrivate::projectClosing(IProject* project)
112 {
113  const auto projectJobIt = m_projectJobs.constFind(project);
114  if (projectJobIt != m_projectJobs.constEnd()) {
115  // make sure the import job does not live longer than the project
116  // see also addLotsOfFiles test
117  for (FileManagerListJob* job : *projectJobIt) {
118  qCDebug(FILEMANAGER) << "killing project job:" << job;
119  job->abort();
120  }
121  m_projectJobs.remove(project);
122  }
123 #ifdef TIME_IMPORT_JOB
124  QElapsedTimer timer;
125  if (m_watchers.contains(project)) {
126  timer.start();
127  }
128 #endif
129  delete m_watchers.take(project);
130 #ifdef TIME_IMPORT_JOB
131  if (timer.isValid()) {
132  qCDebug(FILEMANAGER) << "Deleting dir watcher took" << timer.elapsed() / 1000.0 << "seconds for project" << project->name();
133  }
134 #endif
135  m_filters.remove(project);
136 }
137 
138 KIO::Job* AbstractFileManagerPluginPrivate::eventuallyReadFolder(ProjectFolderItem* item)
139 {
140  auto* listJob = new FileManagerListJob( item );
141  m_projectJobs[ item->project() ] << listJob;
142  qCDebug(FILEMANAGER) << "adding job" << listJob << item << item->path() << "for project" << item->project();
143 
144  q->connect( listJob, &FileManagerListJob::finished,
145  q, [&] (KJob* job) { jobFinished(job); } );
146 
147  q->connect( listJob, &FileManagerListJob::entries,
148  q, [&] (FileManagerListJob* job, ProjectFolderItem* baseItem, const KIO::UDSEntryList& entries) {
149  addJobItems(job, baseItem, entries); } );
150 
151  return listJob;
152 }
153 
154 void AbstractFileManagerPluginPrivate::jobFinished(KJob* job)
155 {
156  // ensure we don't keep a dangling point in our list
157  // NOTE: job is potentially emitting its finished signal from its destructor
158  // or the item that was used internally may have been deleted already
159  for (auto& jobs : m_projectJobs) {
160  if (jobs.removeOne(reinterpret_cast<FileManagerListJob*>(job))) {
161  break;
162  }
163  }
164 }
165 
166 void AbstractFileManagerPluginPrivate::addJobItems(FileManagerListJob* job,
167  ProjectFolderItem* baseItem,
168  const KIO::UDSEntryList& entries)
169 {
170  qCDebug(FILEMANAGER) << "reading entries of" << baseItem->path();
171 
172  // build lists of valid files and folders with paths relative to the project folder
173  Path::List files;
174  Path::List folders;
175  for (const KIO::UDSEntry& entry : entries) {
176  QString name = entry.stringValue( KIO::UDSEntry::UDS_NAME );
177  if (name == QLatin1String(".") || name == QLatin1String("..")) {
178  continue;
179  }
180 
181  Path path(baseItem->path(), name);
182 
183  if ( !q->isValid( path, entry.isDir(), baseItem->project() ) ) {
184  continue;
185  } else {
186  if ( entry.isDir() ) {
187  if( entry.isLink() ) {
188  const Path linkedPath = baseItem->path().cd(entry.stringValue( KIO::UDSEntry::UDS_LINK_DEST ));
189  // make sure we don't end in an infinite loop
190  if( linkedPath.isParentOf( baseItem->project()->path() ) ||
191  baseItem->project()->path().isParentOf( linkedPath ) ||
192  linkedPath == baseItem->project()->path() )
193  {
194  continue;
195  }
196  }
197  folders << path;
198  } else {
199  files << path;
200  }
201  }
202  }
203 
204  ifDebug(qCDebug(FILEMANAGER) << "valid folders:" << folders;)
205  ifDebug(qCDebug(FILEMANAGER) << "valid files:" << files;)
206 
207  // remove obsolete rows
208  for ( int j = 0; j < baseItem->rowCount(); ++j ) {
209  if ( ProjectFolderItem* f = baseItem->child(j)->folder() ) {
210  // check if this is still a valid folder
211  int index = folders.indexOf( f->path() );
212  if ( index == -1 ) {
213  // folder got removed or is now invalid
214  delete f;
215  --j;
216  } else {
217  // this folder already exists in the view
218  folders.remove( index );
219  // no need to add this item, but we still want to recurse into it
220  job->addSubDir( f );
221  emit q->reloadedFolderItem( f );
222  }
223  } else if ( ProjectFileItem* f = baseItem->child(j)->file() ) {
224  // check if this is still a valid file
225  int index = files.indexOf( f->path() );
226  if ( index == -1 ) {
227  // file got removed or is now invalid
228  ifDebug(qCDebug(FILEMANAGER) << "removing file:" << f << f->path();)
229  delete f;
230  --j;
231  } else {
232  // this file already exists in the view
233  files.remove( index );
234  emit q->reloadedFileItem( f );
235  }
236  }
237  }
238 
239  // add new rows
240  for (const Path& path : qAsConst(files)) {
241  ProjectFileItem* file = q->createFileItem( baseItem->project(), path, baseItem );
242  if (file) {
243  emit q->fileAdded( file );
244  }
245  }
246  for (const Path& path : qAsConst(folders)) {
247  ProjectFolderItem* folder = q->createFolderItem( baseItem->project(), path, baseItem );
248  if (folder) {
249  emit q->folderAdded( folder );
250  job->addSubDir( folder );
251  }
252  }
253 }
254 
255 void AbstractFileManagerPluginPrivate::created(const QString& path_)
256 {
257  qCDebug(FILEMANAGER) << "created:" << path_;
258  QFileInfo info(path_);
259  if (!info.exists()) {
260  // we delay handling of the signal, so maybe the path actually got removed again
261  return;
262  }
263 
265  const Path path(path_);
266  const IndexedString indexedPath(path.pathOrUrl());
267  const IndexedString indexedParent(path.parent().pathOrUrl());
268 
269  QHashIterator<IProject*, KDirWatch*> it(m_watchers);
270  while (it.hasNext()) {
271  const auto p = it.next().key();
272  if ( !p->projectItem()->model() ) {
273  // not yet finished with loading
274  // FIXME: how should this be handled? see unit test
275  continue;
276  }
277  if ( !q->isValid(path, info.isDir(), p) ) {
278  continue;
279  }
280  if ( info.isDir() ) {
281  bool found = false;
282  const auto folderItems = p->foldersForPath(indexedPath);
283  for (ProjectFolderItem* folder : folderItems) {
284  // exists already in this project, happens e.g. when we restart the dirwatcher
285  // or if we delete and remove folders consecutively https://bugs.kde.org/show_bug.cgi?id=260741
286  qCDebug(FILEMANAGER) << "force reload of" << path << folder;
287  auto job = eventuallyReadFolder( folder );
288  job->start();
289  found = true;
290  }
291  if ( found ) {
292  continue;
293  }
294  } else if (!p->filesForPath(indexedPath).isEmpty()) {
295  // also gets triggered for kate's backup files
296  continue;
297  }
298  const auto parentItems = p->foldersForPath(indexedParent);
299  for (ProjectFolderItem* parentItem : parentItems) {
300  if ( info.isDir() ) {
301  ProjectFolderItem* folder = q->createFolderItem( p, path, parentItem );
302  if (folder) {
303  emit q->folderAdded( folder );
304  auto job = eventuallyReadFolder( folder );
305  job->start();
306  }
307  } else {
308  ProjectFileItem* file = q->createFileItem( p, path, parentItem );
309  if (file) {
310  emit q->fileAdded( file );
311  }
312  }
313  }
314  }
315 }
316 
317 void AbstractFileManagerPluginPrivate::deleted(const QString& path_)
318 {
319  if ( QFile::exists(path_) ) {
320  // we delay handling of the signal, so maybe the path actually exists again
321  return;
322  }
323  // ensure that the path is not inside a stopped folder
324  for (const QString& folder : qAsConst(m_stoppedFolders)) {
325  if (path_.startsWith(folder)) {
326  return;
327  }
328  }
329  qCDebug(FILEMANAGER) << "deleted:" << path_;
330 
331  const Path path(QUrl::fromLocalFile(path_));
332  const IndexedString indexed(path.pathOrUrl());
333 
334  QHashIterator<IProject*, KDirWatch*> it(m_watchers);
335  while (it.hasNext()) {
336  const auto p = it.next().key();
337  if (path == p->path()) {
338  KMessageBox::error(qApp->activeWindow(),
339  i18n("The base folder of project <b>%1</b>"
340  " got deleted or moved outside of KDevelop.\n"
341  "The project has to be closed.", p->name()),
342  i18nc("@title:window", "Project Folder Deleted") );
343  ICore::self()->projectController()->closeProject(p);
344  continue;
345  }
346  if ( !p->projectItem()->model() ) {
347  // not yet finished with loading
348  // FIXME: how should this be handled? see unit test
349  continue;
350  }
351  const auto folderItems = p->foldersForPath(indexed);
352  for (ProjectFolderItem* item : folderItems) {
353  delete item;
354  }
355  const auto fileItems = p->filesForPath(indexed);
356  for (ProjectFileItem* item : fileItems) {
357  emit q->fileRemoved(item);
358  ifDebug(qCDebug(FILEMANAGER) << "removing file" << item;)
359  delete item;
360  }
361  }
362 }
363 
364 bool AbstractFileManagerPluginPrivate::rename(ProjectBaseItem* item, const Path& newPath)
365 {
366  if ( !q->isValid(newPath, true, item->project()) ) {
367  int cancel = KMessageBox::warningContinueCancel( qApp->activeWindow(),
368  i18n("You tried to rename '%1' to '%2', but the latter is filtered and will be hidden.\n"
369  "Do you want to continue?", item->text(), newPath.lastPathSegment()),
370  QString(), KStandardGuiItem::cont(), KStandardGuiItem::cancel(), QStringLiteral("GenericManagerRenameToFiltered")
371  );
372  if ( cancel == KMessageBox::Cancel ) {
373  return false;
374  }
375  }
376  const auto parentItems = item->project()->foldersForPath(IndexedString(newPath.parent().pathOrUrl()));
377  for (ProjectFolderItem* parent : parentItems) {
378  if ( parent->folder() ) {
379  stopWatcher(parent);
380  const Path source = item->path();
381  bool success = renameUrl( item->project(), source.toUrl(), newPath.toUrl() );
382  if ( success ) {
383  item->setPath( newPath );
384  item->parent()->takeRow( item->row() );
385  parent->appendRow( item );
386  if (item->file()) {
387  emit q->fileRenamed(source, item->file());
388  } else {
389  Q_ASSERT(item->folder());
390  emit q->folderRenamed(source, item->folder());
391  }
392  }
393  continueWatcher(parent);
394  return success;
395  }
396  }
397  return false;
398 }
399 
400 void AbstractFileManagerPluginPrivate::stopWatcher(ProjectFolderItem* folder)
401 {
402  if ( !folder->path().isLocalFile() ) {
403  return;
404  }
405  Q_ASSERT(m_watchers.contains(folder->project()));
406  const QString path = folder->path().toLocalFile();
407  m_watchers[folder->project()]->stopDirScan(path);
408  m_stoppedFolders.append(path);
409 }
410 
411 void AbstractFileManagerPluginPrivate::continueWatcher(ProjectFolderItem* folder)
412 {
413  if ( !folder->path().isLocalFile() ) {
414  return;
415  }
416  auto watcher = m_watchers.value(folder->project(), nullptr);
417  Q_ASSERT(watcher);
418  const QString path = folder->path().toLocalFile();
419  if (!watcher->restartDirScan(path)) {
420  // path wasn't being watched yet - can we be 100% certain of that will never happen?
421  qCWarning(FILEMANAGER) << "Folder" << path << "in project" << folder->project()->name() << "wasn't yet being watched";
422  watcher->addDir(path);
423  }
424  const int idx = m_stoppedFolders.indexOf(path);
425  if (idx != -1) {
426  m_stoppedFolders.remove(idx);
427  }
428 }
429 //END Private
430 
431 //BEGIN Plugin
432 
433 AbstractFileManagerPlugin::AbstractFileManagerPlugin( const QString& componentName,
434  QObject *parent,
435  const QVariantList & /*args*/ )
436  : IProjectFileManager(),
437  IPlugin( componentName, parent ),
438  d_ptr(new AbstractFileManagerPluginPrivate(this))
439 {
440  connect(core()->projectController(), &IProjectController::projectClosing,
441  this, [this] (IProject* project) { Q_D(AbstractFileManagerPlugin); d->projectClosing(project); });
442  connect(core()->projectController()->projectModel(), &ProjectModel::rowsAboutToBeRemoved,
443  this, [this] (const QModelIndex& parent, int first, int last) {
444  Q_D(AbstractFileManagerPlugin);
445  // cleanup list jobs to remove about-to-be-dangling pointers
446  auto* model = core()->projectController()->projectModel();
447  for (int i = first; i <= last; ++i) {
448  const auto index = model->index(i, 0, parent);
449  auto* item = index.data(ProjectModel::ProjectItemRole).value<ProjectBaseItem*>();
450  Q_ASSERT(item);
451  for (auto* job : d->m_projectJobs.value(item->project())) {
452  job->handleRemovedItem(item);
453  }
454  }
455  });
456 }
457 
458 AbstractFileManagerPlugin::~AbstractFileManagerPlugin() = default;
459 
460 IProjectFileManager::Features AbstractFileManagerPlugin::features() const
461 {
462  return Features( Folders | Files );
463 }
464 
465 QList<ProjectFolderItem*> AbstractFileManagerPlugin::parse( ProjectFolderItem *item )
466 {
467  // we are async, can't return anything here
468  qCDebug(FILEMANAGER) << "note: parse will always return an empty list";
469  Q_UNUSED(item);
470  return QList<ProjectFolderItem*>();
471 }
472 
473 ProjectFolderItem *AbstractFileManagerPlugin::import( IProject *project )
474 {
475  Q_D(AbstractFileManagerPlugin);
476 
477  ProjectFolderItem *projectRoot = createFolderItem( project, project->path(), nullptr );
478  emit folderAdded( projectRoot );
479  qCDebug(FILEMANAGER) << "imported new project" << project->name() << "at" << projectRoot->path();
480 
482  if ( project->path().isLocalFile() ) {
483  auto watcher = new KDirWatch( project );
484 
485  // set up the signal handling
486  // NOTE: We delay handling of the creation/deletion events here by one second to prevent
487  // useless or even outright wrong handling of events during common git workflows.
488  // I.e. sometimes we used to get a 'delete' event during a rebase which was never
489  // followed up by a 'created' signal, even though the file actually exists after
490  // the rebase.
491  // see also: https://bugs.kde.org/show_bug.cgi?id=404184
492  connect(watcher, &KDirWatch::created,
493  this, [this] (const QString& path) {
494  QTimer::singleShot(1000, this, [this, path]() {
495  Q_D(AbstractFileManagerPlugin);
496  d->created(path);
497  });
498  });
499  connect(watcher, &KDirWatch::deleted,
500  this, [this] (const QString& path) {
501  QTimer::singleShot(1000, this, [this, path]() {
502  Q_D(AbstractFileManagerPlugin);
503  d->deleted(path);
504  });
505  });
506  watcher->addDir(project->path().toLocalFile(), KDirWatch::WatchSubDirs | KDirWatch:: WatchFiles );
507  d->m_watchers[project] = watcher;
508  }
509 
510  d->m_filters.add(project);
511 
512  return projectRoot;
513 }
514 
515 KJob* AbstractFileManagerPlugin::createImportJob(ProjectFolderItem* item)
516 {
517  Q_D(AbstractFileManagerPlugin);
518 
519  return d->eventuallyReadFolder(item);
520 }
521 
522 bool AbstractFileManagerPlugin::reload( ProjectFolderItem* item )
523 {
524  Q_D(AbstractFileManagerPlugin);
525 
526  qCDebug(FILEMANAGER) << "reloading item" << item->path();
527  auto job = d->eventuallyReadFolder( item->folder() );
528  job->start();
529  return true;
530 }
531 
532 ProjectFolderItem* AbstractFileManagerPlugin::addFolder( const Path& folder,
533  ProjectFolderItem * parent )
534 {
535  Q_D(AbstractFileManagerPlugin);
536 
537  qCDebug(FILEMANAGER) << "adding folder" << folder << "to" << parent->path();
538  ProjectFolderItem* created = nullptr;
539  d->stopWatcher(parent);
540  if ( createFolder(folder.toUrl()) ) {
541  created = createFolderItem( parent->project(), folder, parent );
542  if (created) {
543  emit folderAdded(created);
544  }
545  }
546  d->continueWatcher(parent);
547  return created;
548 }
549 
550 
551 ProjectFileItem* AbstractFileManagerPlugin::addFile( const Path& file,
552  ProjectFolderItem * parent )
553 {
554  Q_D(AbstractFileManagerPlugin);
555 
556  qCDebug(FILEMANAGER) << "adding file" << file << "to" << parent->path();
557  ProjectFileItem* created = nullptr;
558  d->stopWatcher(parent);
559  if ( createFile(file.toUrl()) ) {
560  created = createFileItem( parent->project(), file, parent );
561  if (created) {
562  emit fileAdded(created);
563  }
564  }
565  d->continueWatcher(parent);
566  return created;
567 }
568 
569 bool AbstractFileManagerPlugin::renameFolder(ProjectFolderItem* folder, const Path& newPath)
570 {
571  Q_D(AbstractFileManagerPlugin);
572 
573  qCDebug(FILEMANAGER) << "trying to rename a folder:" << folder->path() << newPath;
574  return d->rename(folder, newPath);
575 }
576 
577 bool AbstractFileManagerPlugin::renameFile(ProjectFileItem* file, const Path& newPath)
578 {
579  Q_D(AbstractFileManagerPlugin);
580 
581  qCDebug(FILEMANAGER) << "trying to rename a file:" << file->path() << newPath;
582  return d->rename(file, newPath);
583 }
584 
585 bool AbstractFileManagerPlugin::removeFilesAndFolders(const QList<ProjectBaseItem*> &items)
586 {
587  Q_D(AbstractFileManagerPlugin);
588 
589  bool success = true;
590  for (ProjectBaseItem* item : items) {
591  Q_ASSERT(item->folder() || item->file());
592 
593  ProjectFolderItem* parent = parentFolder(item);
594  d->stopWatcher(parent);
595 
596  success &= removeUrl(parent->project(), item->path().toUrl(), true);
597  if ( success ) {
598  if (item->file()) {
599  emit fileRemoved(item->file());
600  } else {
601  Q_ASSERT(item->folder());
602  emit folderRemoved(item->folder());
603  }
604  delete item;
605  }
606 
607  d->continueWatcher(parent);
608  if ( !success )
609  break;
610  }
611  return success;
612 }
613 
614 bool AbstractFileManagerPlugin::moveFilesAndFolders(const QList< ProjectBaseItem* >& items, ProjectFolderItem* newParent)
615 {
616  Q_D(AbstractFileManagerPlugin);
617 
618  bool success = true;
619  for (ProjectBaseItem* item : items) {
620  Q_ASSERT(item->folder() || item->file());
621 
622  ProjectFolderItem* oldParent = parentFolder(item);
623  d->stopWatcher(oldParent);
624  d->stopWatcher(newParent);
625 
626  const Path oldPath = item->path();
627  const Path newPath(newParent->path(), item->baseName());
628 
629  success &= renameUrl(oldParent->project(), oldPath.toUrl(), newPath. toUrl());
630  if ( success ) {
631  if (item->file()) {
632  emit fileRemoved(item->file());
633  } else {
634  emit folderRemoved(item->folder());
635  }
636  delete item;
637  KIO::Job *readJob = d->eventuallyReadFolder(newParent);
638  // reload first level synchronously, deeper levels will run async
639  // this is required for code that expects the new item to exist after
640  // this method finished
641  readJob->exec();
642  }
643 
644  d->continueWatcher(oldParent);
645  d->continueWatcher(newParent);
646  if ( !success )
647  break;
648  }
649  return success;
650 }
651 
652 bool AbstractFileManagerPlugin::copyFilesAndFolders(const Path::List& items, ProjectFolderItem* newParent)
653 {
654  Q_D(AbstractFileManagerPlugin);
655 
656  bool success = true;
657  for (const Path& item : items) {
658  d->stopWatcher(newParent);
659 
660  success &= copyUrl(newParent->project(), item.toUrl(), newParent->path().toUrl());
661  if ( success ) {
662  KIO::Job *readJob = d->eventuallyReadFolder(newParent);
663  // reload first level synchronously, deeper levels will run async
664  // this is required for code that expects the new item to exist after
665  // this method finished
666  readJob->exec();
667  }
668 
669  d->continueWatcher(newParent);
670  if ( !success )
671  break;
672  }
673  return success;
674 }
675 
676 bool AbstractFileManagerPlugin::isValid( const Path& path, const bool isFolder,
677  IProject* project ) const
678 {
679  Q_D(const AbstractFileManagerPlugin);
680 
681  return d->m_filters.isValid( path, isFolder, project );
682 }
683 
684 ProjectFileItem* AbstractFileManagerPlugin::createFileItem( IProject* project, const Path& path,
685  ProjectBaseItem* parent )
686 {
687  return new ProjectFileItem( project, path, parent );
688 }
689 
690 ProjectFolderItem* AbstractFileManagerPlugin::createFolderItem( IProject* project, const Path& path,
691  ProjectBaseItem* parent )
692 {
693  return new ProjectFolderItem( project, path, parent );
694 }
695 
696 KDirWatch* AbstractFileManagerPlugin::projectWatcher( IProject* project ) const
697 {
698  Q_D(const AbstractFileManagerPlugin);
699 
700  return d->m_watchers.value( project, nullptr );
701 }
702 
703 //END Plugin
704 
705 #include "moc_abstractfilemanagerplugin.cpp"
KDevelop::ProjectFolderItem
Implementation of the ProjectBaseItem interface that is specific to a folder.
Definition: projectmodel.h:268
KDevelop::ProjectBaseItem::parent
virtual ProjectBaseItem * parent() const
Definition: projectmodel.cpp:309
KDevelop::ProjectFileItem
Object which represents a file.
Definition: projectmodel.h:383
KDevelop::AbstractFileManagerPlugin::copyFilesAndFolders
bool copyFilesAndFolders(const Path::List &items, ProjectFolderItem *newParent) override
Copy files and folders within a given project.
Definition: abstractfilemanagerplugin.cpp:652
abstractfilemanagerplugin.h
KDevelop::ProjectBaseItem::text
QString text() const
Definition: projectmodel.cpp:324
KDevelop::AbstractFileManagerPlugin::createImportJob
KJob * createImportJob(ProjectFolderItem *item) override
This method creates an import job for the given item.
Definition: abstractfilemanagerplugin.cpp:515
KDevelop::FileManagerListJob::addSubDir
void addSubDir(ProjectFolderItem *item)
Definition: filemanagerlistjob.cpp:89
KDevelop::AbstractFileManagerPlugin::fileAdded
void fileAdded(KDevelop::ProjectFileItem *file)
QTimer::singleShot
singleShot
KDevelop::AbstractFileManagerPlugin::renameFolder
bool renameFolder(ProjectFolderItem *folder, const Path &newPath) override
Rename a folder in the project.
Definition: abstractfilemanagerplugin.cpp:569
KDevelop::ProjectBaseItem
Interface that allows a developer to implement the three basic types of items you would see in a mult...
Definition: projectmodel.h:101
KDevelop::ProjectBaseItem::file
virtual ProjectFileItem * file() const
Definition: projectmodel.cpp:521
KDevelop::ProjectFilterManager::remove
void remove(IProject *project)
Remove the managed filters of the given project.
Definition: projectfiltermanager.cpp:169
KDevelop::ProjectFilterManager
A helper class to manage project filtering in file managers.
Definition: projectfiltermanager.h:52
KDevelop::AbstractFileManagerPlugin::isValid
virtual bool isValid(const Path &path, const bool isFolder, IProject *project) const
Filter interface making it possible to hide files and folders from a project.
Definition: abstractfilemanagerplugin.cpp:676
KDevelop::AbstractFileManagerPlugin::renameFile
bool renameFile(ProjectFileItem *file, const Path &newPath) override
Rename a file in the project.
Definition: abstractfilemanagerplugin.cpp:577
KDevelop::FileManagerListJob::start
void start() override
Definition: filemanagerlistjob.cpp:215
KDevelop::ProjectBaseItem::baseName
QString baseName() const
Definition: projectmodel.cpp:460
IPlugin
KDevelop::ProjectBaseItem::folder
virtual ProjectFolderItem * folder() const
Definition: projectmodel.cpp:506
KDevelop::ProjectBaseItem::row
int row() const
Definition: projectmodel.cpp:318
filemanagerlistjob.h
KDevelop::AbstractFileManagerPlugin::folderRemoved
void folderRemoved(KDevelop::ProjectFolderItem *folder)
QList
Definition: projectmodel.h:31
QFile::exists
bool exists() const
KDevelop::ProjectBaseItem::child
ProjectBaseItem * child(int row) const
Definition: projectmodel.cpp:198
KDevelop::AbstractFileManagerPlugin::AbstractFileManagerPlugin
AbstractFileManagerPlugin(const QString &componentName, QObject *parent=nullptr, const QVariantList &args=QVariantList())
Definition: abstractfilemanagerplugin.cpp:433
KDevelop::FileManagerListJob
Definition: filemanagerlistjob.h:40
KDevelop::AbstractFileManagerPlugin::removeFilesAndFolders
bool removeFilesAndFolders(const QList< ProjectBaseItem * > &items) override
Remove files or folders from the project and delete them from disk.
Definition: abstractfilemanagerplugin.cpp:585
KDevelop::createFile
bool KDEVPLATFORMPROJECT_EXPORT createFile(const QUrl &file)
Creates a file at url.
Definition: helper.cpp:99
KDevelop::IProjectFileManager::Files
Files are supported by the manager.
Definition: iprojectfilemanager.h:66
KDevelop::ProjectBaseItem::project
IProject * project() const
Definition: projectmodel.cpp:416
KDevelop::FileManagerListJob::entries
void entries(FileManagerListJob *job, ProjectFolderItem *baseItem, const KIO::UDSEntryList &entries)
KDevelop::AbstractFileManagerPlugin::projectWatcher
KDirWatch * projectWatcher(IProject *project) const
Definition: abstractfilemanagerplugin.cpp:696
projectmodel.h
QObject
KDevelop::copyUrl
bool KDEVPLATFORMPROJECT_EXPORT copyUrl(const KDevelop::IProject *project, const QUrl &source, const QUrl &target)
Copies anything at source to target.
Definition: helper.cpp:211
KDevelop::IProjectFileManager::Folders
Folders are supported by the manager.
Definition: iprojectfilemanager.h:64
QString
KJob
KDevelop::AbstractFileManagerPlugin
This class can be used as a common base for file managers.
Definition: abstractfilemanagerplugin.h:43
KDevelop::ProjectBaseItem::setPath
virtual void setPath(const Path &)
Set the path of this item.
Definition: projectmodel.cpp:465
KDevelop::AbstractFileManagerPlugin::folderAdded
void folderAdded(KDevelop::ProjectFolderItem *folder)
KDevelop::AbstractFileManagerPlugin::createFolderItem
virtual ProjectFolderItem * createFolderItem(IProject *project, const Path &path, ProjectBaseItem *parent=nullptr)
Customization hook enabling you to create custom FolderItems if required.
Definition: abstractfilemanagerplugin.cpp:690
QUrl::fromLocalFile
QUrl fromLocalFile(const QString &localFile)
projectfiltermanager.h
KDevelop::ProjectBaseItem::takeRow
ProjectBaseItem * takeRow(int row)
Returns and removes the item at the given row if there is one.
Definition: projectmodel.cpp:213
KDevelop::AbstractFileManagerPlugin::moveFilesAndFolders
bool moveFilesAndFolders(const QList< ProjectBaseItem * > &items, ProjectFolderItem *newParent) override
Move files and folders within a given project.
Definition: abstractfilemanagerplugin.cpp:614
KDevelop::AbstractFileManagerPlugin::fileRemoved
void fileRemoved(KDevelop::ProjectFileItem *file)
QElapsedTimer
QElapsedTimer::elapsed
qint64 elapsed() const
QHashIterator
KDevelop::IProjectFileManager
An interface to project file management.
Definition: iprojectfilemanager.h:55
QLatin1String
QString::startsWith
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
KDevelop::AbstractFileManagerPlugin::features
Features features() const override
Definition: abstractfilemanagerplugin.cpp:460
QAbstractItemModel::rowsAboutToBeRemoved
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
ifDebug
#define ifDebug(x)
Definition: abstractfilemanagerplugin.cpp:47
KDevelop::AbstractFileManagerPlugin::reload
bool reload(ProjectFolderItem *item) override
Reload an item in the project.
Definition: abstractfilemanagerplugin.cpp:522
KDevelop::FileManagerListJob::handleRemovedItem
void handleRemovedItem(ProjectBaseItem *item)
Definition: filemanagerlistjob.cpp:97
QFileInfo
KDevelop::AbstractFileManagerPlugin::addFile
ProjectFileItem * addFile(const Path &file, ProjectFolderItem *parent) override
Add a file to a folder and create it on disk.
Definition: abstractfilemanagerplugin.cpp:551
KDevelop::createFolder
bool KDEVPLATFORMPROJECT_EXPORT createFolder(const QUrl &folder)
Creates a folder at url.
Definition: helper.cpp:132
KDevelop::ProjectFolderItem::folder
ProjectFolderItem * folder() const override
Definition: projectmodel.cpp:618
KDevelop
Definition: abstractfilemanagerplugin.h:33
KDevelop::ProjectBaseItem::rowCount
int rowCount() const
Definition: projectmodel.cpp:292
QModelIndex
KDevelop::AbstractFileManagerPlugin::addFolder
ProjectFolderItem * addFolder(const Path &folder, ProjectFolderItem *parent) override
Add a folder to the project and create it on disk.
Definition: abstractfilemanagerplugin.cpp:532
QVector< QString >
KDevelop::renameUrl
bool KDEVPLATFORMPROJECT_EXPORT renameUrl(const KDevelop::IProject *project, const QUrl &oldname, const QUrl &newname)
Renames anything at oldname to oldname.
Definition: helper.cpp:150
helper.h
KDevelop::AbstractFileManagerPlugin::parse
QList< ProjectFolderItem * > parse(ProjectFolderItem *item) override
This method initialize the model item.
Definition: abstractfilemanagerplugin.cpp:465
QHash< IProject *, KDirWatch * >
KDevelop::AbstractFileManagerPlugin::import
ProjectFolderItem * import(IProject *project) override
This method creates the root item from the file.
Definition: abstractfilemanagerplugin.cpp:473
KDevelop::removeUrl
bool KDEVPLATFORMPROJECT_EXPORT removeUrl(const KDevelop::IProject *project, const QUrl &url, const bool isFolder)
Deletes the url at url.
Definition: helper.cpp:50
KDevelop::ProjectBaseItem::path
Path path() const
Definition: projectmodel.cpp:449
KDevelop::AbstractFileManagerPlugin::~AbstractFileManagerPlugin
~AbstractFileManagerPlugin() override
KDevelop::ProjectModel::ProjectItemRole
Definition: projectmodel.h:426
QElapsedTimer::isValid
bool isValid() const
KDevelop::AbstractFileManagerPlugin::createFileItem
virtual ProjectFileItem * createFileItem(IProject *project, const Path &path, ProjectBaseItem *parent)
Customization hook enabling you to create custom FileItems if required.
Definition: abstractfilemanagerplugin.cpp:684
debug.h
QElapsedTimer::start
void start()
KDevelop::ProjectBaseItem::appendRow
void appendRow(ProjectBaseItem *item)
Adds a new child item to this item.
Definition: projectmodel.cpp:422
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Wed Mar 3 2021 00:37:59 by doxygen 1.8.16 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kdevplatform/project

Skip menu "kdevplatform/project"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdevelop API Reference

Skip menu "kdevelop API Reference"
  • kdevplatform
  •   debugger
  •   documentation
  •   interfaces
  •   language
  •     assistant
  •     backgroundparser
  •     checks
  •     classmodel
  •     codecompletion
  •     codegen
  •     duchain
  •     editor
  •     highlighting
  •     interfaces
  •     util
  •   outputview
  •   project
  •   serialization
  •   shell
  •   sublime
  •   tests
  •   util
  •   vcs

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal