File indexing completed on 2024-04-28 16:26:33
0001 /**************************************************************************************** 0002 begin : Tue Aug 12 2003 0003 copyright : (C) 2003 by Jeroen Wijnhout (Jeroen.Wijnhout@kdemail.net) 0004 2006 - 2010 by Michel Ludwig (michel.ludwig@kdemail.net) 0005 ****************************************************************************************/ 0006 0007 /*************************************************************************** 0008 * * 0009 * This program is free software; you can redistribute it and/or modify * 0010 * it under the terms of the GNU General Public License as published by * 0011 * the Free Software Foundation; either version 2 of the License, or * 0012 * (at your option) any later version. * 0013 * * 0014 ***************************************************************************/ 0015 0016 #include "widgets/projectview.h" 0017 0018 #include <QHeaderView> 0019 #include <QIcon> 0020 #include <KLocalizedString> 0021 #include <QList> 0022 #include <QMenu> 0023 #include <QMimeData> 0024 #include <QMimeDatabase> 0025 #include <QMimeType> 0026 #include <QUrl> 0027 0028 #include <KActionMenu> 0029 #include <KIO/ApplicationLauncherJob> 0030 #include <KIO/JobUiDelegateFactory> 0031 #include <KIO/OpenUrlJob> 0032 #include <KApplicationTrader> 0033 #include <KJobUiDelegate> 0034 0035 #include "kileinfo.h" 0036 #include "documentinfo.h" 0037 #include "kiledocmanager.h" 0038 #include <iostream> 0039 #include <typeinfo> 0040 0041 const int KPV_ID_OPEN = 0, KPV_ID_SAVE = 1, KPV_ID_CLOSE = 2, 0042 KPV_ID_OPTIONS = 3, KPV_ID_ADD = 4, KPV_ID_REMOVE = 5, 0043 KPV_ID_BUILDTREE = 6, KPV_ID_ARCHIVE = 7, KPV_ID_ADDFILES = 8, 0044 KPV_ID_INCLUDE = 9, KPV_ID_OPENWITH = 10, KPV_ID_OPENALLFILES = 11; 0045 0046 namespace KileWidget { 0047 0048 /* 0049 * ProjectViewItem 0050 */ 0051 ProjectViewItem::ProjectViewItem(QTreeWidget *parent, KileProjectItem *item, bool ar) 0052 : QTreeWidgetItem(parent, QStringList(item->url().fileName())), m_docinfo(Q_NULLPTR), m_folder(-1), m_projectItem(item) 0053 { 0054 setArchiveState(ar); 0055 } 0056 0057 ProjectViewItem::ProjectViewItem(QTreeWidget *parent, QTreeWidgetItem *after, KileProjectItem *item, bool ar) 0058 : QTreeWidgetItem(parent, after), m_docinfo(Q_NULLPTR), m_folder(-1), m_projectItem(item) 0059 { 0060 setText(0, item->url().fileName()); 0061 setArchiveState(ar); 0062 } 0063 0064 ProjectViewItem::ProjectViewItem(QTreeWidgetItem *parent, KileProjectItem *item, bool ar) 0065 : QTreeWidgetItem(parent, QStringList(item->url().fileName())), m_docinfo(Q_NULLPTR), m_folder(-1), m_projectItem(item) 0066 { 0067 setArchiveState(ar); 0068 } 0069 0070 //use this to create folders 0071 ProjectViewItem::ProjectViewItem(QTreeWidgetItem *parent, const QString& name) 0072 : QTreeWidgetItem(parent, QStringList(name)), m_docinfo(Q_NULLPTR), m_folder(-1), m_projectItem(Q_NULLPTR) 0073 { 0074 } 0075 0076 //use this to create non-project files 0077 ProjectViewItem::ProjectViewItem(QTreeWidget *parent, const QString& name) 0078 : QTreeWidgetItem(parent, QStringList(name)), m_docinfo(Q_NULLPTR), m_folder(-1), m_projectItem(Q_NULLPTR) 0079 { 0080 } 0081 0082 ProjectViewItem::ProjectViewItem(QTreeWidget *parent, const KileProject *project) 0083 : QTreeWidgetItem(parent, QStringList(project->name())), m_docinfo(Q_NULLPTR), m_folder(-1), m_projectItem(Q_NULLPTR) 0084 { 0085 } 0086 0087 ProjectViewItem::~ProjectViewItem() 0088 { 0089 KILE_DEBUG_MAIN << "DELETING PROJVIEWITEM " << m_url.fileName(); 0090 } 0091 0092 KileProjectItem* ProjectViewItem::projectItem() 0093 { 0094 return m_projectItem; 0095 } 0096 0097 ProjectViewItem* ProjectViewItem::parent() 0098 { 0099 return dynamic_cast<ProjectViewItem*>(QTreeWidgetItem::parent()); 0100 } 0101 0102 ProjectViewItem* ProjectViewItem::firstChild() 0103 { 0104 return dynamic_cast<ProjectViewItem*>(QTreeWidgetItem::child(0)); 0105 } 0106 0107 void ProjectViewItem::setInfo(KileDocument::Info *docinfo) 0108 { 0109 m_docinfo = docinfo; 0110 } 0111 0112 KileDocument::Info* ProjectViewItem::getInfo() 0113 { 0114 return m_docinfo; 0115 } 0116 0117 void ProjectViewItem::setType(KileType::ProjectView type) 0118 { 0119 m_type = type; 0120 } 0121 0122 KileType::ProjectView ProjectViewItem::type() const 0123 { 0124 return m_type; 0125 } 0126 0127 void ProjectViewItem::urlChanged(const QUrl &url) 0128 { 0129 // don't allow empty URLs 0130 if(!url.isEmpty()) { 0131 setURL(url); 0132 setText(0, url.fileName()); 0133 } 0134 } 0135 0136 void ProjectViewItem::nameChanged(const QString & name) 0137 { 0138 setText(0, name); 0139 } 0140 0141 void ProjectViewItem::isrootChanged(bool isroot) 0142 { 0143 KILE_DEBUG_MAIN << "SLOT isrootChanged " << text(0) << " to " << isroot; 0144 if(isroot) { 0145 setIcon(0, QIcon::fromTheme("masteritem")); 0146 } 0147 else { 0148 if(m_projectItem && m_projectItem->type() == KileProjectItem::ProjectFile) { 0149 setIcon(0, QIcon::fromTheme("kile")); 0150 } 0151 else if(m_projectItem && m_projectItem->type() == KileProjectItem::Bibliography) { 0152 setIcon(0, QIcon::fromTheme("viewbib")); 0153 } 0154 else if(type() == KileType::ProjectItem) { 0155 setIcon(0, QIcon::fromTheme("projectitem")); 0156 } 0157 else { 0158 setIcon(0, QIcon::fromTheme("file")); 0159 } 0160 } 0161 } 0162 0163 void ProjectViewItem::slotURLChanged(KileDocument::Info*, const QUrl &url) 0164 { 0165 urlChanged(url); 0166 } 0167 0168 bool ProjectViewItem::operator<(const QTreeWidgetItem& other) const 0169 { 0170 try { 0171 const ProjectViewItem& otherItem = dynamic_cast<const ProjectViewItem&>(other); 0172 0173 // order in the tree: 0174 // - first, root items without container (sorted in ascending order) 0175 // - then, container items in fixed order (images, packages, other, projectfile) 0176 if(otherItem.type() == KileType::Folder) { 0177 if(type() != KileType::Folder) { 0178 return true; 0179 } 0180 else { 0181 // 'm_folder' is set to a type from 'KileProject::Type' 0182 // we want: Image < Package < Other < ProjectFile 0183 switch(m_folder) { 0184 case KileProjectItem::Image: 0185 return true; 0186 0187 case KileProjectItem::Package: 0188 return (otherItem.m_folder == KileProjectItem::Image) ? false : true; 0189 0190 case KileProjectItem::Other: 0191 return (otherItem.m_folder == KileProjectItem::Image 0192 || otherItem.m_folder == KileProjectItem::Package) ? false : true; 0193 0194 case KileProjectItem::ProjectFile: 0195 return false; 0196 0197 default: // dummy 0198 return false; 0199 } 0200 } 0201 } 0202 else if(type() == KileType::Folder) { 0203 return false; 0204 } 0205 else { 0206 return QTreeWidgetItem::operator<(other); 0207 } 0208 } 0209 catch(std::bad_cast&) { 0210 return QTreeWidgetItem::operator<(other); 0211 } 0212 } 0213 0214 void ProjectViewItem::setURL(const QUrl &url) 0215 { 0216 m_url = url; 0217 } 0218 0219 const QUrl &ProjectViewItem::url() 0220 { 0221 return m_url; 0222 } 0223 0224 void ProjectViewItem::setArchiveState(bool ar) 0225 { 0226 setText(1, ar ? "*" : ""); 0227 } 0228 0229 void ProjectViewItem::setFolder(int folder) 0230 { 0231 m_folder = folder; 0232 } 0233 0234 int ProjectViewItem::folder() const 0235 { 0236 return m_folder; 0237 } 0238 0239 /* 0240 * ProjectView 0241 */ 0242 ProjectView::ProjectView(QWidget *parent, KileInfo *ki) : QTreeWidget(parent), m_ki(ki), m_nProjects(0) 0243 { 0244 setColumnCount(2); 0245 QStringList labelList; 0246 labelList << i18n("Files & Projects") << i18n("Include in Archive"); 0247 setHeaderLabels(labelList); 0248 setColumnWidth(1, 10); 0249 0250 setFocusPolicy(Qt::ClickFocus); 0251 header()->hide(); 0252 header()->setSectionResizeMode(QHeaderView::ResizeToContents); 0253 setRootIsDecorated(true); 0254 setAllColumnsShowFocus(true); 0255 setSelectionMode(QTreeWidget::SingleSelection); 0256 0257 connect(this, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(slotClicked(QTreeWidgetItem*))); 0258 setAcceptDrops(true); 0259 } 0260 0261 void ProjectView::slotClicked(QTreeWidgetItem *item) 0262 { 0263 if(!item) { 0264 item = currentItem(); 0265 } 0266 0267 ProjectViewItem *itm = static_cast<ProjectViewItem*>(item); 0268 if(itm) { 0269 if(itm->type() == KileType::File) { 0270 emit(fileSelected(itm->url())); 0271 } 0272 else if(itm->type() == KileType::ProjectItem) { 0273 emit(fileSelected(itm->projectItem())); 0274 } 0275 else if(itm->type() != KileType::Folder) { 0276 // don't open project configuration files (*.kilepr) 0277 if(itm->url().toLocalFile().right(7) != ".kilepr") { 0278 //determine mimeType and open file with preferred application 0279 QMimeDatabase db; 0280 QMimeType pMime = db.mimeTypeForUrl(itm->url()); 0281 if(pMime.name().startsWith(QLatin1String("text/"))) { 0282 emit(fileSelected(itm->url())); 0283 } 0284 else { 0285 auto *job = new KIO::OpenUrlJob(itm->url(), pMime.name()); 0286 job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this)); 0287 job->start(); 0288 } 0289 } 0290 } 0291 clearSelection(); 0292 } 0293 } 0294 0295 void ProjectView::slotFile(int id) 0296 { 0297 ProjectViewItem *item = dynamic_cast<ProjectViewItem*>(currentItem()); 0298 if(item) { 0299 if(item->type() == KileType::File) { 0300 switch(id) { 0301 case KPV_ID_OPEN: 0302 emit(fileSelected(item->url())); 0303 break; 0304 case KPV_ID_SAVE: 0305 emit(saveURL(item->url())); 0306 break; 0307 case KPV_ID_ADD: 0308 emit(addToProject(item->url())); 0309 break; 0310 case KPV_ID_CLOSE: 0311 emit(closeURL(item->url())); 0312 return; //don't access "item" later on 0313 default: 0314 break; 0315 } 0316 } 0317 } 0318 } 0319 0320 void ProjectView::slotProjectItem(int id) 0321 { 0322 ProjectViewItem *item = dynamic_cast<ProjectViewItem*>(currentItem()); 0323 if(item) { 0324 if(item->type() == KileType::ProjectItem || item->type() == KileType::ProjectExtra) { 0325 switch(id) { 0326 case KPV_ID_OPEN: 0327 emit(fileSelected(item->projectItem())); 0328 break; 0329 case KPV_ID_SAVE: 0330 emit(saveURL(item->url())); 0331 break; 0332 case KPV_ID_REMOVE: 0333 emit(removeFromProject(item->projectItem())); 0334 break; 0335 case KPV_ID_INCLUDE : 0336 if(item->text(1) == "*") { 0337 item->setText(1, ""); 0338 } 0339 else { 0340 item->setText(1, "*"); 0341 } 0342 emit(toggleArchive(item->projectItem())); 0343 break; 0344 case KPV_ID_CLOSE: 0345 emit(closeURL(item->url())); 0346 break; //we can access "item" later as it isn't deleted 0347 case KPV_ID_OPENWITH: 0348 { 0349 auto *job = new KIO::ApplicationLauncherJob(); 0350 job->setUrls(QList<QUrl>() << item->url()); 0351 job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this)); 0352 job->start(); 0353 break; 0354 } 0355 default: 0356 break; 0357 } 0358 } 0359 } 0360 } 0361 0362 void ProjectView::slotProject(int id) 0363 { 0364 ProjectViewItem *item = dynamic_cast<ProjectViewItem*>(currentItem()); 0365 if(item) { 0366 if(item->type() == KileType::Project) { 0367 switch(id) { 0368 case KPV_ID_BUILDTREE: 0369 emit(buildProjectTree(item->url())); 0370 break; 0371 case KPV_ID_OPTIONS: 0372 emit(projectOptions(item->url())); 0373 break; 0374 case KPV_ID_CLOSE: 0375 emit(closeProject(item->url())); 0376 return; //don't access "item" later on 0377 case KPV_ID_ARCHIVE: 0378 emit(projectArchive(item->url())); 0379 break; 0380 case KPV_ID_ADDFILES: 0381 emit(addFiles(item->url())); 0382 break; 0383 case KPV_ID_OPENALLFILES: 0384 emit(openAllFiles(item->url())); 0385 break; 0386 default: 0387 break; 0388 } 0389 } 0390 } 0391 } 0392 0393 void ProjectView::slotRun(int id) 0394 { 0395 ProjectViewItem *itm = dynamic_cast<ProjectViewItem*>(currentItem()); 0396 0397 if(!itm) { 0398 return; 0399 } 0400 0401 if(id == 0) { 0402 // open with dialog 0403 auto *job = new KIO::ApplicationLauncherJob(); 0404 job->setUrls(QList<QUrl>() << itm->url()); 0405 job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this)); 0406 job->start(); 0407 } 0408 else { 0409 auto *job = new KIO::ApplicationLauncherJob(m_offerList[id - 1]); 0410 job->setUrls(QList<QUrl>() << itm->url()); 0411 job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this)); 0412 job->start(); 0413 } 0414 0415 itm->setSelected(false); 0416 } 0417 0418 void ProjectView::makeTheConnection(ProjectViewItem *item, KileDocument::TextInfo *textInfo) 0419 { 0420 KILE_DEBUG_MAIN << "\tmakeTheConnection " << item->text(0); 0421 0422 if (item->type() == KileType::Project) { 0423 KileProject *project = m_ki->docManager()->projectFor(item->url()); 0424 if (!project) { 0425 qWarning() << "makeTheConnection COULD NOT FIND AN PROJECT OBJECT FOR " << item->url().toLocalFile(); 0426 } 0427 else { 0428 connect(project, SIGNAL(nameChanged(QString)), item, SLOT(nameChanged(QString))); 0429 } 0430 } 0431 else { 0432 if(!textInfo) { 0433 textInfo = m_ki->docManager()->textInfoFor(item->url().toLocalFile()); 0434 if(!textInfo) { 0435 KILE_DEBUG_MAIN << "\tmakeTheConnection COULD NOT FIND A DOCINFO"; 0436 return; 0437 } 0438 } 0439 item->setInfo(textInfo); 0440 connect(textInfo, SIGNAL(urlChanged(KileDocument::Info*,QUrl)), item, SLOT(slotURLChanged(KileDocument::Info*,QUrl))); 0441 connect(textInfo, SIGNAL(isrootChanged(bool)), item, SLOT(isrootChanged(bool))); 0442 //set the pixmap 0443 item->isrootChanged(textInfo->isLaTeXRoot()); 0444 } 0445 } 0446 0447 ProjectViewItem* ProjectView::folder(const KileProjectItem *pi, ProjectViewItem *item) 0448 { 0449 ProjectViewItem *parent = parentFor(pi, item); 0450 0451 if(!parent) { 0452 qCritical() << "no parent for " << pi->url().toLocalFile(); 0453 return Q_NULLPTR; 0454 } 0455 0456 // we have already found the parent folder 0457 if(parent->type() == KileType::Folder) { 0458 return parent; 0459 } 0460 0461 // we are looking at the children, if there is an existing folder for this type 0462 ProjectViewItem *folder; 0463 0464 // determine the foldername for this type 0465 QString foldername; 0466 switch(pi->type()) { 0467 case (KileProjectItem::ProjectFile): 0468 foldername = i18n("Project File"); 0469 break; 0470 case (KileProjectItem::Package): 0471 foldername = i18n("Packages"); 0472 break; 0473 case (KileProjectItem::Image): 0474 foldername = i18n("Images"); 0475 break; 0476 case (KileProjectItem::Bibliography): 0477 foldername = i18n("Bibliography"); 0478 break; 0479 case (KileProjectItem::Other): 0480 default : 0481 foldername = i18n("Other"); 0482 break; 0483 } 0484 0485 // if there already a folder for this type on this level? 0486 bool found = false; 0487 QTreeWidgetItemIterator it(parent); 0488 ++it; // skip 'parent' 0489 while(*it) { 0490 folder = dynamic_cast<ProjectViewItem*>(*it); 0491 if(folder && folder->text(0) == foldername) { 0492 found = true; 0493 break; 0494 } 0495 ++it; 0496 } 0497 0498 // if no folder was found, we must create a new one 0499 if(!found) { 0500 folder = new ProjectViewItem(parent, foldername); 0501 KILE_DEBUG_MAIN << "new folder: parent=" << parent->url().url() 0502 << ", foldername=" << foldername; 0503 0504 folder->setFolder(pi->type()); 0505 folder->setType(KileType::Folder); 0506 } 0507 0508 return folder; 0509 } 0510 0511 void ProjectView::add(const KileProject *project) 0512 { 0513 ProjectViewItem *parent = new ProjectViewItem(this, project); 0514 0515 parent->setType(KileType::Project); 0516 parent->setURL(project->url()); 0517 parent->setExpanded(true); 0518 parent->setIcon(0, QIcon::fromTheme("relation")); 0519 makeTheConnection(parent); 0520 0521 //ProjectViewItem *nonsrc = new ProjectViewItem(parent, i18n("non-source")); 0522 //parent->setNonSrc(nonsrc); 0523 0524 refreshProjectTree(project); 0525 0526 ++m_nProjects; 0527 } 0528 0529 ProjectViewItem* ProjectView::projectViewItemFor(const QUrl &url) 0530 { 0531 ProjectViewItem *item = Q_NULLPTR; 0532 0533 //find project view item 0534 QTreeWidgetItemIterator it(this); 0535 while(*it) { 0536 item = dynamic_cast<ProjectViewItem*>(*it); 0537 if(item && (item->type() == KileType::Project) && (item->url() == url)) { 0538 break; 0539 } 0540 ++it; 0541 } 0542 0543 return item; 0544 } 0545 0546 ProjectViewItem* ProjectView::itemFor(const QUrl &url) 0547 { 0548 ProjectViewItem *item = Q_NULLPTR; 0549 0550 QTreeWidgetItemIterator it(this); 0551 while(*it) { 0552 item = static_cast<ProjectViewItem*>(*it); 0553 if (item->url() == url) { 0554 break; 0555 } 0556 ++it; 0557 } 0558 0559 return item; 0560 } 0561 0562 ProjectViewItem* ProjectView::parentFor(const KileProjectItem *projitem, ProjectViewItem *projvi) 0563 { 0564 //find parent projectviewitem of projitem 0565 KileProjectItem *parpi = projitem->parent(); 0566 ProjectViewItem *parpvi = projvi, *vi; 0567 0568 if (parpi) { 0569 //find parent viewitem that has an URL parpi->url() 0570 QTreeWidgetItemIterator it(projvi); 0571 KILE_DEBUG_MAIN << "\tlooking for " << parpi->url().toLocalFile(); 0572 while(*it) { 0573 vi = static_cast<ProjectViewItem*>(*it); 0574 KILE_DEBUG_MAIN << "\t\t" << vi->url().toLocalFile(); 0575 if (vi->url() == parpi->url()) { 0576 parpvi = vi; 0577 KILE_DEBUG_MAIN << "\t\tfound" << Qt::endl; 0578 break; 0579 } 0580 ++it; 0581 } 0582 0583 KILE_DEBUG_MAIN << "\t\tnot found"; 0584 } 0585 else { 0586 KILE_DEBUG_MAIN << "\tlooking for folder type " << projitem->type(); 0587 QTreeWidgetItemIterator it(projvi); 0588 ++it; // skip projvi 0589 while(*it) { 0590 ProjectViewItem *child = dynamic_cast<ProjectViewItem*>(*it); 0591 if(child && (child->type() == KileType::Folder) && (child->folder() == projitem->type())) { 0592 KILE_DEBUG_MAIN << "\t\tfound"; 0593 parpvi = child; 0594 break; 0595 } 0596 ++it; 0597 } 0598 } 0599 0600 return (!parpvi) ? projvi : parpvi; 0601 } 0602 0603 ProjectViewItem* ProjectView::add(KileProjectItem *projitem, ProjectViewItem *projvi /* = Q_NULLPTR */) 0604 { 0605 KILE_DEBUG_MAIN << "\tprojectitem=" << projitem->path() 0606 << " projvi=" << projvi; 0607 const KileProject *project = projitem->project(); 0608 0609 if (!projvi) { 0610 projvi = projectViewItemFor(project->url()); 0611 } 0612 0613 KILE_DEBUG_MAIN << "\tparent projectviewitem " << projvi->url().fileName(); 0614 0615 ProjectViewItem *item = Q_NULLPTR, *parent = Q_NULLPTR; 0616 0617 switch (projitem->type()) { 0618 case (KileProjectItem::Source): 0619 item = new ProjectViewItem(projvi, projitem); 0620 item->setType(KileType::ProjectItem); 0621 item->setIcon(0, QIcon::fromTheme("projectitem")); 0622 break; 0623 case (KileProjectItem::Package): 0624 parent = folder(projitem, projvi); 0625 item = new ProjectViewItem(parent, projitem); 0626 item->setType(KileType::ProjectItem); 0627 item->setIcon(0, QIcon::fromTheme("projectitem")); 0628 break; 0629 default: 0630 parent = folder(projitem, projvi); 0631 item = new ProjectViewItem(parent, projitem); 0632 item->setType(KileType::ProjectExtra); 0633 if(projitem->type() == KileProjectItem::ProjectFile) { 0634 item->setIcon(0, QIcon::fromTheme("kile")); 0635 } 0636 else if(projitem->type() == KileProjectItem::Bibliography) { 0637 item->setIcon(0, QIcon::fromTheme("viewbib")); 0638 } 0639 else { 0640 item->setIcon(0, QIcon::fromTheme("file")); 0641 } 0642 break; 0643 } 0644 0645 item->setArchiveState(projitem->archive()); 0646 item->setURL(projitem->url()); 0647 makeTheConnection(item, projitem->getInfo()); 0648 0649 projvi->sortChildren(0, Qt::AscendingOrder); 0650 // seems to be necessary to get a correct refreh (Qt 4.4.3) 0651 bool expanded = projvi->isExpanded(); 0652 projvi->setExpanded(!expanded); 0653 projvi->setExpanded(expanded); 0654 0655 return item; 0656 } 0657 0658 void ProjectView::addTree(KileProjectItem *projitem, ProjectViewItem *projvi) 0659 { 0660 KILE_DEBUG_MAIN << "projitem=" << projitem 0661 << "projvi=" << projvi; 0662 ProjectViewItem * item = add(projitem, projvi); 0663 0664 if(projitem->firstChild()) { 0665 addTree(projitem->firstChild(), item); 0666 } 0667 0668 if (projitem->sibling()) { 0669 addTree(projitem->sibling(), projvi); 0670 } 0671 } 0672 0673 void ProjectView::refreshProjectTree(const KileProject *project) 0674 { 0675 KILE_DEBUG_MAIN << "\tProjectView::refreshProjectTree(" << project->name() << ")"; 0676 ProjectViewItem *parent= projectViewItemFor(project->url()); 0677 0678 //clean the tree 0679 if(parent) { 0680 KILE_DEBUG_MAIN << "\tusing parent projectviewitem " << parent->url().fileName(); 0681 parent->setFolder(-1); 0682 QList<QTreeWidgetItem*> children = parent->takeChildren(); 0683 for(QList<QTreeWidgetItem*>::iterator it = children.begin(); 0684 it != children.end(); ++it) { 0685 delete(*it); 0686 } 0687 } 0688 else { 0689 return; 0690 } 0691 0692 //create the non-sources dir 0693 //ProjectViewItem *nonsrc = new ProjectViewItem(parent, i18n("non-sources")); 0694 //parent->setNonSrc(nonsrc); 0695 0696 QList<KileProjectItem*> list = project->rootItems(); 0697 for(QList<KileProjectItem*>::iterator it = list.begin(); it != list.end(); ++it) { 0698 addTree(*it, parent); 0699 } 0700 0701 parent->sortChildren(0, Qt::AscendingOrder); 0702 // seems to be necessary to get a correct refreh (Qt 4.4.3) 0703 bool expanded = parent->isExpanded(); 0704 parent->setExpanded(!expanded); 0705 parent->setExpanded(expanded); 0706 } 0707 0708 void ProjectView::add(const QUrl &url) 0709 { 0710 KILE_DEBUG_MAIN << "\tProjectView::adding item " << url.toLocalFile(); 0711 //check if file is already present 0712 QTreeWidgetItemIterator it(this); 0713 ProjectViewItem *item; 0714 while(*it) { 0715 item = static_cast<ProjectViewItem*>(*it); 0716 if((item->type() != KileType::Project) && (item->url() == url)) { 0717 return; 0718 } 0719 ++it; 0720 } 0721 0722 item = new ProjectViewItem(this, url.fileName()); 0723 item->setType(KileType::File); 0724 item->setURL(url); 0725 makeTheConnection(item); 0726 } 0727 0728 void ProjectView::remove(const KileProject *project) 0729 { 0730 for(int i = 0; i < topLevelItemCount(); ++i) { 0731 ProjectViewItem *item = static_cast<ProjectViewItem*>(topLevelItem(i)); 0732 0733 if(item->url() == project->url()) { 0734 item->setParent(Q_NULLPTR); 0735 delete item; 0736 --m_nProjects; 0737 break; 0738 } 0739 } 0740 } 0741 0742 /** 0743 * Removes a file from the projectview, does not remove project-items. Only files without a project. 0744 **/ 0745 void ProjectView::remove(const QUrl &url) 0746 { 0747 for(int i = 0; i < topLevelItemCount(); ++i) { 0748 ProjectViewItem *item = dynamic_cast<ProjectViewItem*>(topLevelItem(i)); 0749 0750 if(item && (item->type() == KileType::File) && (item->url() == url)) { 0751 item->setParent(Q_NULLPTR); 0752 delete item; 0753 break; 0754 } 0755 } 0756 } 0757 0758 void ProjectView::removeItem(const KileProjectItem *projitem, bool open) 0759 { 0760 QTreeWidgetItemIterator it(this); 0761 ProjectViewItem *item; 0762 while(*it) { 0763 item = dynamic_cast<ProjectViewItem*>(*it); 0764 if(item && (item->type() == KileType::ProjectItem) && (item->projectItem() == projitem)) { 0765 KILE_DEBUG_MAIN << "removing projectviewitem"; 0766 static_cast<QTreeWidgetItem*>(item->parent())->removeChild(item); 0767 delete item; 0768 } 0769 ++it; 0770 } 0771 0772 if(open) { 0773 item = new ProjectViewItem(this, projitem->url().fileName()); 0774 item->setType(KileType::File); 0775 item->setURL(projitem->url()); 0776 makeTheConnection(item); 0777 } 0778 0779 } 0780 0781 void ProjectView::contextMenuEvent(QContextMenuEvent *event) 0782 { 0783 QMenu popup; 0784 QAction *action = Q_NULLPTR; 0785 0786 QTreeWidgetItem* treeWidgetItem = itemAt(event->pos()); 0787 if(!treeWidgetItem) { 0788 return; 0789 } 0790 0791 ProjectViewItem *projectViewItem = dynamic_cast<ProjectViewItem*>(treeWidgetItem); 0792 if(!projectViewItem) { 0793 return; 0794 } 0795 0796 if(projectViewItem->type() == KileType::Folder) { 0797 return; 0798 } 0799 0800 bool insertsep = false; 0801 bool isKilePrFile = false; 0802 if(projectViewItem->type() != KileType::Project && projectViewItem->projectItem() 0803 && projectViewItem->projectItem()->project()) { 0804 isKilePrFile = projectViewItem->projectItem()->project()->url() == projectViewItem->url(); 0805 } 0806 0807 if(projectViewItem->type() == KileType::ProjectExtra && !isKilePrFile) { 0808 QMenu *servicesMenu = popup.addMenu(QIcon::fromTheme("fork"), i18n("&Open With")); 0809 QMimeDatabase db; 0810 m_offerList = KApplicationTrader::queryByMimeType(db.mimeTypeForUrl(projectViewItem->url()).name()); 0811 for (int i = 0; i < m_offerList.count(); ++i) { 0812 action = new QAction(servicesMenu); 0813 action->setIcon(QIcon::fromTheme(m_offerList[i]->icon())); 0814 action->setText(m_offerList[i]->name()); 0815 connect(action, &QAction::triggered, this, [this, i] { slotRun(i + 1); }); 0816 servicesMenu->addAction(action); 0817 } 0818 0819 servicesMenu->addSeparator(); 0820 servicesMenu->addAction(i18n("Other..."), this, [this] { slotRun(0); }); 0821 insertsep = true; 0822 } 0823 0824 if (projectViewItem->type() == KileType::File || projectViewItem->type() == KileType::ProjectItem) { 0825 if(!m_ki->isOpen(projectViewItem->url())) { 0826 popup.addAction(QIcon::fromTheme("document-open"), i18n("&Open"), this, [this] { slotProjectItem(KPV_ID_OPEN); }); 0827 } 0828 else { 0829 popup.addAction(QIcon::fromTheme("document-save"), i18n("&Save"), this, [this] { slotProjectItem(KPV_ID_SAVE); }); 0830 } 0831 insertsep = true; 0832 } 0833 0834 if(projectViewItem->type() == KileType::File) { 0835 if(m_nProjects > 0) { 0836 if(insertsep) { 0837 popup.addSeparator(); 0838 } 0839 popup.addAction(QIcon::fromTheme("project_add"), i18n("&Add to Project"), this, [this] { slotProjectItem(KPV_ID_ADD); }); 0840 insertsep = true; 0841 } 0842 } 0843 else if(projectViewItem->type() == KileType::ProjectItem || projectViewItem->type() == KileType::ProjectExtra) { 0844 KileProjectItem *pi = projectViewItem->projectItem(); 0845 if(pi) { 0846 if(insertsep) { 0847 popup.addSeparator(); 0848 } 0849 action = popup.addAction(i18n("&Include in Archive"), this, [this] { slotProjectItem(KPV_ID_INCLUDE); }); 0850 action->setCheckable(true); 0851 action->setChecked(pi->archive()); 0852 insertsep = true; 0853 } 0854 if(!isKilePrFile) { 0855 if(insertsep) { 0856 popup.addSeparator(); 0857 } 0858 popup.addAction(QIcon::fromTheme("project_remove"),i18n("&Remove From Project"), this, [this] { slotProjectItem(KPV_ID_REMOVE); }); 0859 insertsep = true; 0860 } 0861 } 0862 else if(projectViewItem->type() == KileType::Project) { 0863 if(insertsep) { 0864 popup.addSeparator(); 0865 } 0866 popup.addAction(i18n("A&dd Files..."), this, [this] { slotProject(KPV_ID_ADDFILES); }); 0867 popup.addSeparator(); 0868 popup.addAction(i18n("Open All &Project Files"), this, [this] { slotProject(KPV_ID_OPENALLFILES); }); 0869 popup.addSeparator(); 0870 popup.addAction(QIcon::fromTheme("view-refresh"),i18n("Refresh Project &Tree"), this, [this] { slotProject(KPV_ID_BUILDTREE); }); 0871 popup.addAction(QIcon::fromTheme("configure"), i18n("Project &Options"), this, [this] { slotProject(KPV_ID_OPTIONS); }); 0872 popup.addAction(i18n("&Archive"), this, [this] { slotProject(KPV_ID_ARCHIVE); }); 0873 insertsep = true; 0874 } 0875 0876 if((projectViewItem->type() == KileType::File) || (projectViewItem->type() == KileType::ProjectItem) 0877 || (projectViewItem->type()== KileType::Project)) { 0878 if(insertsep) { 0879 popup.addSeparator(); 0880 } 0881 if(projectViewItem->type() == KileType::Project) { 0882 popup.addAction(QIcon::fromTheme("view-close"), i18n("&Close"), this, [this] { slotProject(KPV_ID_CLOSE); }); 0883 } 0884 else { 0885 popup.addAction(QIcon::fromTheme("view-close"), i18n("&Close"), this, [this] { slotProjectItem(KPV_ID_CLOSE); }); 0886 } 0887 } 0888 0889 popup.exec(event->globalPos()); 0890 m_offerList.clear(); 0891 } 0892 0893 void ProjectView::dragEnterEvent(QDragEnterEvent *event) 0894 { 0895 if(event->mimeData()->hasUrls()) { // only accept URL drags 0896 event->acceptProposedAction(); 0897 } 0898 } 0899 0900 void ProjectView::dragMoveEvent(QDragMoveEvent *event) 0901 { 0902 if(event->mimeData()->hasUrls()) { // only accept URL drags 0903 event->acceptProposedAction(); 0904 } 0905 } 0906 0907 void ProjectView::dropEvent(QDropEvent *event) 0908 { 0909 m_ki->docManager()->openDroppedURLs(event); 0910 } 0911 0912 } 0913