383 lines
13 KiB
C++
383 lines
13 KiB
C++
#include "projectfilesystemwidget.h"
|
|
#include <extensionsystem/pluginmanager.h>
|
|
#include <extensionsystem/pluginspec.h>
|
|
#include <coreplugin/icore.h>
|
|
#include <coreplugin/fileutils.h>
|
|
#include <coreplugin/navigationwidget.h>
|
|
#include <coreplugin/fileiconprovider.h>
|
|
#include <coreplugin/actionmanager/actioncontainer.h>
|
|
#include <coreplugin/actionmanager/actionmanager.h>
|
|
#include <coreplugin/editormanager/ieditor.h>
|
|
#include <coreplugin/editormanager/editormanager.h>
|
|
#include <projectexplorer/projectexplorer.h>
|
|
#include <projectexplorer/projecttreewidget.h>
|
|
#include <projectexplorer/projecttree.h>
|
|
#include <projectexplorer/project.h>
|
|
#include <projectexplorer/projectnodes.h>
|
|
#include <projectexplorer/session.h>
|
|
#include <utils/utilsicons.h>
|
|
#include <QApplication>
|
|
#include <QDesktopServices>
|
|
#include <QMessageBox>
|
|
#include <QInputDialog>
|
|
#include <QScrollBar>
|
|
|
|
/*
|
|
class ProjectsModel: public QAbstractItemModel
|
|
{
|
|
public:
|
|
ProjectsModel() {fsm.setRootPath(qApp->applicationDirPath());}
|
|
QFileInfo fileInfo(const QModelIndex & i) {return fsm.fileInfo(i);}
|
|
QModelIndex index(const QString & path, int column = 0) const {return fsm.index(path, column);}
|
|
QModelIndex index(int row, int column, const QModelIndex & parent) const {
|
|
return fsm.index(row, column, parent);
|
|
}
|
|
QModelIndex parent(const QModelIndex & child) const {
|
|
return fsm.parent(child);
|
|
}
|
|
int rowCount(const QModelIndex & parent) const {
|
|
return fsm.rowCount(parent);
|
|
}
|
|
int columnCount(const QModelIndex & parent) const {
|
|
return fsm.columnCount(parent);
|
|
}
|
|
QVariant data(const QModelIndex & index, int role) const {
|
|
return fsm.data(index, role);
|
|
}
|
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const {
|
|
return fsm.headerData(section, orientation, role);
|
|
}
|
|
Qt::ItemFlags flags(const QModelIndex & index) const {
|
|
return fsm.flags(index);
|
|
}
|
|
void sort(int column, Qt::SortOrder order) {
|
|
fsm.sort(column, order);
|
|
}
|
|
QHash<int, QByteArray> roleNames() const {
|
|
return fsm.roleNames();
|
|
}
|
|
QModelIndex sibling(int row, int column, const QModelIndex & idx) const {
|
|
return fsm.sibling(row, column, idx);
|
|
}
|
|
bool hasChildren(const QModelIndex & parent) const {
|
|
return fsm.hasChildren(parent);
|
|
}
|
|
private:
|
|
QFileSystemModel fsm;
|
|
|
|
};
|
|
*/
|
|
|
|
ProjectFilesystemWidget::ProjectFilesystemWidget(QWidget * parent): QWidget(parent) {
|
|
setupUi(this);
|
|
buttonClear->setIcon(Utils::Icons::CLEAN.icon());
|
|
buttonExpand->setIcon(Utils::Icons::EXPAND.icon());
|
|
buttonCollapse->setIcon(Utils::Icons::COLLAPSE.icon());
|
|
actionOpen_here->setIcon(Utils::Icons::OPENFILE.icon());
|
|
actionOpen_external->setIcon(Utils::Icons::OPENFILE.icon());
|
|
actionShow_external->setIcon(Utils::Icons::DIR.icon());
|
|
popup_menu.addActions(QList<QAction*>() << actionOpen_here << actionOpen_external << actionShow_external);
|
|
proj_plug = 0;
|
|
/*QList<QObject * > plugs = ExtensionSystem::PluginManager::allObjects();
|
|
QStringList sl;
|
|
foreach (QObject * o, plugs) {
|
|
ExtensionSystem::IPlugin * p = qobject_cast<ExtensionSystem::IPlugin * >(o);
|
|
if (!p) continue;
|
|
QString cn = QString::fromLatin1(o->metaObject()->className());
|
|
if (cn.startsWith("ProjectExplorer"))
|
|
sl << cn;
|
|
ExtensionSystem::PluginSpec * ps = p->pluginSpec();
|
|
if (!ps) continue;
|
|
if (ps->name() == "ProjectExplorer") {
|
|
proj_plug = p;
|
|
connect(p, SIGNAL(fileListChanged()), this, SLOT(projectsChanged()), Qt::UniqueConnection);
|
|
break;
|
|
}
|
|
}*/
|
|
//QMessageBox::information(this, "", sl.join("\n"));
|
|
//connect(ProjectExplorer::ProjectTree::instance(), SIGNAL(subtreeChanged(ProjectExplorer::FolderNode*)), this, SLOT(projectsChanged()));
|
|
connect(ProjectExplorer::SessionManager::instance(), SIGNAL(startupProjectChanged(ProjectExplorer::Project *)), this, SLOT(startupProjectChanged()));
|
|
connect(ProjectExplorer::SessionManager::instance(), SIGNAL(projectAdded(ProjectExplorer::Project*)), this, SLOT(projectsChanged()));
|
|
connect(ProjectExplorer::SessionManager::instance(), SIGNAL(projectDisplayNameChanged(ProjectExplorer::Project*)), this, SLOT(projectsChanged()));
|
|
connect(ProjectExplorer::SessionManager::instance(), SIGNAL(projectRemoved(ProjectExplorer::Project*)), this, SLOT(projectsChanged()));
|
|
//connect(ProjectExplorer::SessionManager::instance(), SIGNAL(), this, SLOT(startupProjectChanged()));
|
|
connect(Core::EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)), this, SLOT(fileChanged()));
|
|
//model = new ProjectsModel();
|
|
//tree->setModel(model);
|
|
//model.setNameFilterDisables(false);
|
|
/*for (int i = 1; i < tree->header()->count(); ++i)
|
|
tree->header()->setSectionHidden(i, true);
|
|
tree->setHeaderHidden(true);*/
|
|
projectsChanged();
|
|
}
|
|
|
|
|
|
void ProjectFilesystemWidget::setCurrentFilter(const FilterDialog::Filter & v) {
|
|
cur_filter = v;
|
|
projectsChanged();
|
|
}
|
|
|
|
|
|
void ProjectFilesystemWidget::changeEvent(QEvent *e) {
|
|
QWidget::changeEvent(e);
|
|
switch (e->type()) {
|
|
case QEvent::LanguageChange:
|
|
retranslateUi(this);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void ProjectFilesystemWidget::createTree(QTreeWidgetItem * ti, const QString & dir) {
|
|
/*int rc = model.rowCount(dir);
|
|
QTreeWidgetItem * ni = new QTreeWidgetItem(ti);
|
|
ni->setText(0, QString::number(rc));
|
|
ti->addChild(ni);
|
|
return;*/
|
|
QFileInfoList fl = QDir(dir).entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot, QDir::LocaleAware | QDir::DirsFirst);
|
|
for (QFileInfo i: fl) {
|
|
QString nit = i.fileName();
|
|
if (i.isDir()) {
|
|
if (!cur_filter.filterDir(nit))
|
|
continue;
|
|
} else {
|
|
if (!cur_filter.filterFile(nit))
|
|
continue;
|
|
}
|
|
QTreeWidgetItem * ni = new QTreeWidgetItem();
|
|
ni->setText(0, nit);
|
|
ni->setIcon(0, Core::FileIconProvider::icon(i));
|
|
ni->setData(0, Qt::UserRole, i.absoluteFilePath());
|
|
ni->setData(0, Qt::UserRole + 1, i.isDir());
|
|
item_map[i.absoluteFilePath()] = ni;
|
|
if (i.isDir()) {
|
|
createTree(ni, dir + QDir::separator() + i.fileName());
|
|
}
|
|
ti->addChild(ni);
|
|
}
|
|
//if (ti->childCount() == 0) delete ti;
|
|
}
|
|
|
|
|
|
bool ProjectFilesystemWidget::filterTree(QTreeWidgetItem * ti, const QString & filter) {
|
|
bool ret = false;
|
|
for (int i = 0; i < ti->childCount(); ++i) {
|
|
QTreeWidgetItem * ci = ti->child(i);
|
|
QString cit = ci->text(0);
|
|
if (ci->data(0, Qt::UserRole + 1).toBool()) {
|
|
if (!filterTree(ci, filter)) {
|
|
ci->setHidden(true);
|
|
continue;
|
|
}
|
|
ci->setHidden(false);
|
|
ret = true;
|
|
} else {
|
|
bool f = false;
|
|
if (filter.isEmpty()) {
|
|
f = true;
|
|
} else {
|
|
f = f || cit.contains(filter);
|
|
}
|
|
ci->setHidden(!f);
|
|
if (f) ret = true;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
void ProjectFilesystemWidget::filter() {
|
|
QString f = lineFilter->text();
|
|
/*QStringList nf;
|
|
if (!f.isEmpty()) {
|
|
if (!f.startsWith("*")) f.prepend('*');
|
|
if (!f.endsWith("*")) f.append('*');
|
|
nf << f;
|
|
}
|
|
model.setNameFilters(nf);*/
|
|
for (int i = 0; i < tree->topLevelItemCount(); ++i) {
|
|
QTreeWidgetItem * ti = tree->topLevelItem(i);
|
|
filterTree(ti, f);
|
|
}
|
|
}
|
|
|
|
|
|
void ProjectFilesystemWidget::rememberExpanded(QTreeWidgetItem * ti) {
|
|
//QMessageBox::information(0, ti->data(0, Qt::UserRole).toString(), QString::number(ti->childCount()));
|
|
for (int i = 0; i < ti->childCount(); ++i) {
|
|
QTreeWidgetItem * ci = ti->child(i);
|
|
if (ci->data(0, Qt::UserRole + 1).toBool()) {
|
|
if (ci->isExpanded())
|
|
last_expanded << ci->data(0, Qt::UserRole).toString();
|
|
rememberExpanded(ci);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void ProjectFilesystemWidget::restoreExpanded(QTreeWidgetItem * ti) {
|
|
for (int i = 0; i < ti->childCount(); ++i) {
|
|
QTreeWidgetItem * ci = ti->child(i);
|
|
if (ci->data(0, Qt::UserRole + 1).toBool()) {
|
|
if (last_expanded.contains(ci->data(0, Qt::UserRole).toString()))
|
|
ci->setExpanded(true);
|
|
restoreExpanded(ci);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void ProjectFilesystemWidget::projectsChanged() {
|
|
last_expanded.clear();
|
|
item_map.clear();
|
|
int spos = tree->verticalScrollBar()->value();
|
|
rememberExpanded(tree->invisibleRootItem());
|
|
tree->clear();
|
|
QList<ProjectExplorer::Project *> pl = ProjectExplorer::SessionManager::projects();
|
|
for (ProjectExplorer::Project * p: pl) {
|
|
QTreeWidgetItem * ri = new QTreeWidgetItem();
|
|
QString dir = p->projectDirectory().toString();
|
|
ri->setText(0, p->displayName());
|
|
ri->setIcon(0, Utils::Icons::DIR.icon());
|
|
ri->setData(0, Qt::UserRole, dir);
|
|
ri->setData(0, Qt::UserRole + 1, true);
|
|
createTree(ri, dir);
|
|
tree->addTopLevelItem(ri);
|
|
}
|
|
startupProjectChanged();
|
|
fileChanged();
|
|
filter();
|
|
restoreExpanded(tree->invisibleRootItem());
|
|
qApp->processEvents();
|
|
tree->verticalScrollBar()->setValue(spos);
|
|
}
|
|
|
|
|
|
void ProjectFilesystemWidget::filterClicked() {
|
|
filter_dialog.setFilter(cur_filter);
|
|
if (filter_dialog.exec() == QDialog::Rejected) return;
|
|
setCurrentFilter(filter_dialog.filter());
|
|
}
|
|
|
|
|
|
void ProjectFilesystemWidget::fileChanged() {
|
|
Core::IDocument * cd = Core::EditorManager::instance()->currentDocument();
|
|
if (!cd) return;
|
|
QString np = cd->filePath().toString();
|
|
QTreeWidgetItem * ti = item_map.value(np);
|
|
if (!ti) return;
|
|
tree->setCurrentItem(ti);
|
|
tree->expandItem(ti);
|
|
}
|
|
|
|
|
|
void ProjectFilesystemWidget::startupProjectChanged() {
|
|
ProjectExplorer::Project * sp = ProjectExplorer::SessionManager::startupProject();
|
|
QFont f(tree->font()), bf(f);
|
|
bf.setBold(true);
|
|
for (int i = 0; i < tree->topLevelItemCount(); ++i) {
|
|
QTreeWidgetItem * ti = tree->topLevelItem(i);
|
|
ti->setFont(0, f);
|
|
if (!sp) continue;
|
|
if (sp->projectDirectory().toString() == ti->data(0, Qt::UserRole).toString())
|
|
ti->setFont(0, bf);
|
|
}
|
|
}
|
|
|
|
|
|
void ProjectFilesystemWidget::on_tree_doubleClicked(const QModelIndex & index) {
|
|
/*if (!index.isValid()) return;
|
|
QFileInfo fi = model->fileInfo(index);
|
|
QStringList ext_ext;
|
|
ext_ext << "ui" << "ts";
|
|
if (ext_ext.contains(fi.suffix()))
|
|
QDesktopServices::openUrl(QUrl::fromLocalFile(fi.absoluteFilePath()));
|
|
else
|
|
Core::EditorManager::openEditor(fi.absoluteFilePath());*/
|
|
}
|
|
|
|
void ProjectFilesystemWidget::on_tree_itemDoubleClicked(QTreeWidgetItem * item, int) {
|
|
if (!item) return;
|
|
QString afp = item->data(0, Qt::UserRole).toString();
|
|
bool dir = item->data(0, Qt::UserRole + 1).toBool();
|
|
if (dir) return;
|
|
if (afp.isEmpty()) return;
|
|
Core::EditorManager::openEditor(afp);
|
|
}
|
|
|
|
|
|
void ProjectFilesystemWidget::on_lineFilter_textChanged(const QString & ) {
|
|
filter();
|
|
}
|
|
|
|
|
|
void ProjectFilesystemWidget::on_tree_customContextMenuRequested(const QPoint & pos) {
|
|
menu_target = QFileInfo();
|
|
QTreeWidgetItem * item = tree->itemAt(pos);
|
|
//QMessageBox::information(this, "", QString::number(index.row()));
|
|
if (!item) return;
|
|
menu_target = QFileInfo(item->data(0, Qt::UserRole).toString());
|
|
actionOpen_here->setEnabled(!menu_target.isDir());
|
|
actionOpen_external->setEnabled(!menu_target.isDir());
|
|
popup_menu.popup(tree->mapToGlobal(pos));
|
|
/*Utils::FileName fileName(menu_target);
|
|
//Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_FILECONTEXT)->menu()->popup(tree->mapToGlobal(pos));
|
|
ProjectExplorer::ProjectExplorerPlugin::updateContextMenuActions();
|
|
ProjectExplorer::Node * n = 0;//ProjectExplorer::Internal::ProjectTreeWidget::nodeForFile(Utils::FileName(menu_target));
|
|
for (ProjectExplorer::Project * project: ProjectExplorer::SessionManager::projects()) {
|
|
if (ProjectExplorer::ProjectNode * projectNode = project->rootProjectNode()) {
|
|
projectNode->forEachGenericNode([&](ProjectExplorer::Node *node) {
|
|
if (node->filePath() == fileName) {
|
|
if (!n) {
|
|
n = node;
|
|
}
|
|
}
|
|
});
|
|
if (n) break;
|
|
}
|
|
}
|
|
if (!n) return;
|
|
ProjectExplorer::Internal::ProjectTreeWidget * ptw = 0;
|
|
QString ss = QString::fromLatin1("ProjectTreeWidget");
|
|
QWidgetList wl = qApp->topLevelWidgets();
|
|
for (QWidget * w : wl) {
|
|
QList<QObject*> ol = w->findChildren<QObject*>();
|
|
if (QString::fromLatin1(w->metaObject()->className()).endsWith(ss)) {
|
|
ptw = (ProjectExplorer::Internal::ProjectTreeWidget *)w;
|
|
break;
|
|
}
|
|
for (QObject * o : ol) {
|
|
if (QString::fromLatin1(o->metaObject()->className()).endsWith(ss)) {
|
|
ptw = (ProjectExplorer::Internal::ProjectTreeWidget *)o;
|
|
break;
|
|
}
|
|
}
|
|
if (ptw) break;
|
|
}
|
|
if (!ptw) return;
|
|
ptw->setFocus();
|
|
qApp->processEvents();
|
|
ProjectExplorer::ProjectTree::showContextMenu(ptw, tree->mapToGlobal(pos), n);*/
|
|
}
|
|
|
|
|
|
void ProjectFilesystemWidget::on_actionOpen_here_triggered() {
|
|
if (menu_target.path().isEmpty()) return;
|
|
Core::EditorManager::openEditor(menu_target.absoluteFilePath());
|
|
}
|
|
|
|
|
|
void ProjectFilesystemWidget::on_actionOpen_external_triggered() {
|
|
if (menu_target.path().isEmpty()) return;
|
|
QDesktopServices::openUrl(QUrl::fromLocalFile(menu_target.absoluteFilePath()));
|
|
}
|
|
|
|
|
|
void ProjectFilesystemWidget::on_actionShow_external_triggered() {
|
|
if (menu_target.path().isEmpty()) return;
|
|
Core::FileUtils::showInGraphicalShell(Core::ICore::mainWindow(), menu_target.absoluteFilePath());
|
|
}
|
|
|