diff --git a/project_fs/ProjectFilesystemPlugin.json.in b/project_fs/ProjectFilesystemPlugin.json.in new file mode 100644 index 0000000..0d8ab6d --- /dev/null +++ b/project_fs/ProjectFilesystemPlugin.json.in @@ -0,0 +1,11 @@ +{ + \"Name\" : \"ProjectFilesystemPlugin\", + \"Version\" : \"1.0.0\", + \"CompatVersion\" : \"1.0.0\", + \"Vendor\" : \"Peri4\", + \"Copyright\" : \"(C) Peri4\", + \"License\" : \"LGPLv3\", + \"Description\" : \"LGPLv3\", + \"Url\" : \"\", + $$dependencyList +} diff --git a/project_fs/filterdialog.cpp b/project_fs/filterdialog.cpp new file mode 100644 index 0000000..2137cd1 --- /dev/null +++ b/project_fs/filterdialog.cpp @@ -0,0 +1,91 @@ +#include "filterdialog.h" +#include +#include + + +FilterDialog::FilterDialog(QWidget * parent): QDialog(parent) { + setupUi(this); + toolButton->setIcon(Utils::Icons::CLEAN.icon()); + toolButton_2->setIcon(Utils::Icons::CLEAN.icon()); + toolButton_3->setIcon(Utils::Icons::CLEAN.icon()); + toolButton_4->setIcon(Utils::Icons::CLEAN.icon()); +} + + +void FilterDialog::changeEvent(QEvent *e) { + QDialog::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + retranslateUi(this); + break; + default: + break; + } +} + + +FilterDialog::Filter FilterDialog::filter() const { + FilterDialog::Filter ret; + ret.files_show = getFilters(lineFilesShow); + ret.files_hide = getFilters(lineFilesHide); + ret.dirs_show = getFilters(lineDirsShow); + ret.dirs_hide = getFilters(lineDirsHide); + return ret; +} + +void FilterDialog::setFilter(const FilterDialog::Filter & f) { + setFilters(lineFilesShow, f.files_show); + setFilters(lineFilesHide, f.files_hide); + setFilters(lineDirsShow, f.dirs_show); + setFilters(lineDirsHide, f.dirs_hide); +} + + +QStringList FilterDialog::getFilters(QLineEdit * le) const { + if (!le) return QStringList(); + QStringList ret = le->text().split(","); + for (int i = 0; i < ret.size(); ++i) + ret[i] = ret[i].trimmed(); + ret.removeAll(""); + return ret; +} + + +void FilterDialog::setFilters(QLineEdit * le, QStringList f) { + if (!le) return; + le->setText(f.join(",")); +} + + +FilterDialog::Filter::Filter(const QVariant & v) { + QByteArray ba = v.toByteArray(); + if (ba.isEmpty()) return; + QDataStream s(ba); + s >> files_show >> files_hide >> dirs_show >> dirs_hide; +} + + +QVariant FilterDialog::Filter::toVariant() const { + QByteArray ba; + QDataStream s(&ba, QIODevice::ReadWrite); + s << files_show << files_hide << dirs_show << dirs_hide; + return QVariant(ba); +} + + +bool FilterDialog::Filter::filterLogic(const QStringList & fshow, const QStringList & fhide, const QString & path) const { + if (fshow.isEmpty() && fhide.isEmpty()) return true; + if (!fhide.isEmpty()) { + if (QDir::match(fhide, path)) + return false; + else { + if (fshow.isEmpty()) + return true; + else + return QDir::match(fshow, path); + } + } + if (!fshow.isEmpty()) + return QDir::match(fshow, path); + return true; +} diff --git a/project_fs/filterdialog.h b/project_fs/filterdialog.h new file mode 100644 index 0000000..0d1e2a3 --- /dev/null +++ b/project_fs/filterdialog.h @@ -0,0 +1,37 @@ +#ifndef FILTERDIALOG_H +#define FILTERDIALOG_H + +#include "ui_filterdialog.h" + +class FilterDialog: public QDialog, private Ui::FilterDialog +{ + Q_OBJECT +public: + explicit FilterDialog(QWidget *parent = 0); + + struct Filter { + Filter() {} + Filter(const QVariant & v); + QVariant toVariant() const; + bool filterFile(const QString & path) const {return filterLogic(files_show, files_hide, path);} + bool filterDir(const QString & path) const {return filterLogic(dirs_show, dirs_hide, path);} + QStringList files_show; + QStringList files_hide; + QStringList dirs_show; + QStringList dirs_hide; + private: + bool filterLogic(const QStringList & fshow, const QStringList & fhide, const QString & path) const; + }; + + Filter filter() const; + void setFilter(const Filter & f); + +protected: + void changeEvent(QEvent *e); + + QStringList getFilters(QLineEdit * le) const; + void setFilters(QLineEdit * le, QStringList f); + +}; + +#endif // FILTERDIALOG_H diff --git a/project_fs/filterdialog.ui b/project_fs/filterdialog.ui new file mode 100644 index 0000000..df38a3f --- /dev/null +++ b/project_fs/filterdialog.ui @@ -0,0 +1,226 @@ + + + FilterDialog + + + + 0 + 0 + 342 + 250 + + + + Project filesystem filters + + + + + + Input filters, separated by ",": + + + + + + + + + Show dirs: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + Hide files: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Show files: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + Hide dirs: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + lineFilesShow + lineFilesHide + lineDirsShow + lineDirsHide + toolButton + toolButton_2 + toolButton_3 + toolButton_4 + + + + + buttonBox + accepted() + FilterDialog + accept() + + + 259 + 238 + + + 157 + 274 + + + + + buttonBox + rejected() + FilterDialog + reject() + + + 327 + 238 + + + 286 + 274 + + + + + toolButton + clicked() + lineFilesShow + clear() + + + 329 + 60 + + + 269 + 58 + + + + + toolButton_2 + clicked() + lineFilesHide + clear() + + + 329 + 93 + + + 295 + 91 + + + + + toolButton_3 + clicked() + lineDirsShow + clear() + + + 329 + 126 + + + 295 + 124 + + + + + toolButton_4 + clicked() + lineDirsHide + clear() + + + 329 + 159 + + + 295 + 157 + + + + + diff --git a/project_fs/icons/edit-find.png b/project_fs/icons/edit-find.png new file mode 100644 index 0000000..9a462c0 Binary files /dev/null and b/project_fs/icons/edit-find.png differ diff --git a/project_fs/projectfilesystem.qrc b/project_fs/projectfilesystem.qrc new file mode 100644 index 0000000..49af6d4 --- /dev/null +++ b/project_fs/projectfilesystem.qrc @@ -0,0 +1,5 @@ + + + icons/edit-find.png + + diff --git a/project_fs/projectfilesystemplugin.cpp b/project_fs/projectfilesystemplugin.cpp new file mode 100644 index 0000000..d301ba1 --- /dev/null +++ b/project_fs/projectfilesystemplugin.cpp @@ -0,0 +1,83 @@ +#include "projectfilesystemplugin.h" +#include "projectfilesystempluginconstants.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace ProjectFilesystemPlugin { + namespace Internal { + + ProjectFilesystemPluginPlugin::ProjectFilesystemPluginPlugin() + { + // Create your members + } + + ProjectFilesystemPluginPlugin::~ProjectFilesystemPluginPlugin() + { + // Unregister objects from the plugin manager's object pool + // Delete members + } + + bool ProjectFilesystemPluginPlugin::initialize(const QStringList &arguments, QString *errorString) + { + // Register objects in the plugin manager's object pool + // Load settings + // Add actions to menus + // Connect to other plugins' signals + // In the initialize function, a plugin can be sure that the plugins it + // depends on have initialized their members. + + Q_UNUSED(arguments) + Q_UNUSED(errorString) + + /*auto action = new QAction(tr("ProjectFilesystemPlugin Action"), this); + Core::Command *cmd = Core::ActionManager::registerAction(action, Constants::ACTION_ID, + Core::Context(Core::Constants::C_GLOBAL)); + cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Meta+A"))); + connect(action, &QAction::triggered, this, &ProjectFilesystemPluginPlugin::triggerAction); + + Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::MENU_ID); + menu->menu()->setTitle(tr("ProjectFilesystemPlugin")); + menu->addAction(cmd); + Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu); + + qDebug() << Core::IContext::widget();*/ + addAutoReleasedObject(new ProjectFSWidgetFactory()); + + return true; + } + + void ProjectFilesystemPluginPlugin::extensionsInitialized() + { + // Retrieve objects from the plugin manager's object pool + // In the extensionsInitialized function, a plugin can be sure that all + // plugins that depend on it are completely initialized. + } + + ExtensionSystem::IPlugin::ShutdownFlag ProjectFilesystemPluginPlugin::aboutToShutdown() + { + // Save settings + // Disconnect from signals that are not needed during shutdown + // Hide UI (if you add UI that is not in the main window directly) + return SynchronousShutdown; + } + + void ProjectFilesystemPluginPlugin::triggerAction() + { + QMessageBox::information(Core::ICore::mainWindow(), + tr("Action Triggered"), + tr("This is an action from ProjectFilesystemPlugin.")); + } + + } // namespace Internal +} // namespace ProjectFilesystemPlugin diff --git a/project_fs/projectfilesystemplugin.h b/project_fs/projectfilesystemplugin.h new file mode 100644 index 0000000..4262865 --- /dev/null +++ b/project_fs/projectfilesystemplugin.h @@ -0,0 +1,29 @@ +#pragma once + +#include "projectfilesystemplugin_global.h" +#include "projectfilesystemwidgetplugin.h" + +#include + +namespace ProjectFilesystemPlugin { + namespace Internal { + + class ProjectFilesystemPluginPlugin : public ExtensionSystem::IPlugin + { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ProjectFilesystemPlugin.json") + + public: + ProjectFilesystemPluginPlugin(); + ~ProjectFilesystemPluginPlugin(); + + bool initialize(const QStringList &arguments, QString *errorString); + void extensionsInitialized(); + ShutdownFlag aboutToShutdown(); + + private: + void triggerAction(); + }; + + } // namespace Internal +} // namespace ProjectFilesystemPlugin diff --git a/project_fs/projectfilesystemplugin.pro b/project_fs/projectfilesystemplugin.pro new file mode 100644 index 0000000..a0bb479 --- /dev/null +++ b/project_fs/projectfilesystemplugin.pro @@ -0,0 +1,63 @@ +DEFINES += PROJECTFILESYSTEMPLUGIN_LIBRARY + +# ProjectFilesystemPlugin files + +SOURCES += projectfilesystemplugin.cpp \ + projectfilesystemwidget.cpp \ + projectfilesystemwidgetplugin.cpp \ + filterdialog.cpp + +HEADERS += projectfilesystemplugin.h \ + projectfilesystemplugin_global.h \ + projectfilesystempluginconstants.h \ + projectfilesystemwidget.h \ + projectfilesystemwidgetplugin.h \ + filterdialog.h + +FORMS += \ + projectfilesystemwidget.ui \ + filterdialog.ui + +RESOURCES += \ + projectfilesystem.qrc + +#QT += network + +# Qt Creator linking + +## Either set the IDE_SOURCE_TREE when running qmake, +## or set the QTC_SOURCE environment variable, to override the default setting +isEmpty(IDE_SOURCE_TREE): IDE_SOURCE_TREE = $$(QTC_SOURCE) +isEmpty(IDE_SOURCE_TREE): IDE_SOURCE_TREE = "D:/sdk/qt-creator-git/qt-creator" + +## Either set the IDE_BUILD_TREE when running qmake, +## or set the QTC_BUILD environment variable, to override the default setting +isEmpty(IDE_BUILD_TREE): IDE_BUILD_TREE = $$(QTC_BUILD) +isEmpty(IDE_BUILD_TREE): IDE_BUILD_TREE = "D:/sdk/qt-creator-git/build-qtcreator-Desktop_Qt_5_9_1_MinGW_32bit-Release" + +## uncomment to build plugin into user config directory +## /plugins/ +## where is e.g. +## "%LOCALAPPDATA%\QtProject\qtcreator" on Windows Vista and later +## "$XDG_DATA_HOME/data/QtProject/qtcreator" or "~/.local/share/data/QtProject/qtcreator" on Linux +## "~/Library/Application Support/QtProject/Qt Creator" on OS X +#USE_USER_DESTDIR = yes + +###### If the plugin can be depended upon by other plugins, this code needs to be outsourced to +###### _dependencies.pri, where is the name of the directory containing the +###### plugin's sources. + +QTC_PLUGIN_NAME = ProjectFilesystemPlugin +QTC_LIB_DEPENDS += \ + # nothing here at this time + +QTC_PLUGIN_DEPENDS += \ + coreplugin \ + projectexplorer + +QTC_PLUGIN_RECOMMENDS += \ + # optional plugin dependencies. nothing here at this time + +###### End _dependencies.pri contents ###### + +include($$IDE_SOURCE_TREE/src/qtcreatorplugin.pri) diff --git a/project_fs/projectfilesystemplugin_global.h b/project_fs/projectfilesystemplugin_global.h new file mode 100644 index 0000000..f2e22e8 --- /dev/null +++ b/project_fs/projectfilesystemplugin_global.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +#if defined(PROJECTFILESYSTEMPLUGIN_LIBRARY) +# define PROJECTFILESYSTEMPLUGINSHARED_EXPORT Q_DECL_EXPORT +#else +# define PROJECTFILESYSTEMPLUGINSHARED_EXPORT Q_DECL_IMPORT +#endif diff --git a/project_fs/projectfilesystempluginconstants.h b/project_fs/projectfilesystempluginconstants.h new file mode 100644 index 0000000..2fb2893 --- /dev/null +++ b/project_fs/projectfilesystempluginconstants.h @@ -0,0 +1,10 @@ +#pragma once + +namespace ProjectFilesystemPlugin { + namespace Constants { + + const char ACTION_ID[] = "ProjectFilesystemPlugin.Action"; + const char MENU_ID[] = "ProjectFilesystemPlugin.Menu"; + + } // namespace ProjectFilesystemPlugin +} // namespace Constants diff --git a/project_fs/projectfilesystemwidget.cpp b/project_fs/projectfilesystemwidget.cpp new file mode 100644 index 0000000..b2e2d01 --- /dev/null +++ b/project_fs/projectfilesystemwidget.cpp @@ -0,0 +1,380 @@ +#include "projectfilesystemwidget.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +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 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() << actionOpen_here << actionOpen_external << actionShow_external); + proj_plug = 0; + /*QList plugs = ExtensionSystem::PluginManager::allObjects(); + QStringList sl; + foreach (QObject * o, plugs) { + ExtensionSystem::IPlugin * p = qobject_cast(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 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(); + 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 ol = w->findChildren(); + 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()); +} + diff --git a/project_fs/projectfilesystemwidget.h b/project_fs/projectfilesystemwidget.h new file mode 100644 index 0000000..86c5b41 --- /dev/null +++ b/project_fs/projectfilesystemwidget.h @@ -0,0 +1,60 @@ +#ifndef PROJECTFILESYSTEMWIDGET_H +#define PROJECTFILESYSTEMWIDGET_H + +#include "ui_projectfilesystemwidget.h" +#include "filterdialog.h" +#include +#include +#include +#include + +class ProjectsModel; + +class ProjectFilesystemWidget: public QWidget, private Ui::ProjectFilesystemWidget +{ + Q_OBJECT +public: + explicit ProjectFilesystemWidget(QWidget * parent = 0); + + FilterDialog::Filter currentFilters() const {return cur_filter;} + QString currentSearch() const {return lineFilter->text();} + + void setCurrentFilter(const FilterDialog::Filter & v); + void setCurrentSearch(QString v) {lineFilter->setText(v);} + +protected: + void changeEvent(QEvent * e); + void createTree(QTreeWidgetItem * ti, const QString & dir); + bool filterTree(QTreeWidgetItem * ti, const QString & filter); + void filter(); + void rememberExpanded(QTreeWidgetItem * ti); + void restoreExpanded(QTreeWidgetItem * ti); + + ExtensionSystem::IPlugin * proj_plug; + //ProjectsModel * model; + QMenu popup_menu; + QFileInfo menu_target; + QMap item_map; + QSet last_expanded; + FilterDialog filter_dialog; + FilterDialog::Filter cur_filter; + +public slots: + void projectsChanged(); + void filterClicked(); + +private slots: + void fileChanged(); + void startupProjectChanged(); + + void on_tree_doubleClicked(const QModelIndex &index); + void on_tree_itemDoubleClicked(QTreeWidgetItem * item, int ); + void on_lineFilter_textChanged(const QString &); + void on_tree_customContextMenuRequested(const QPoint & pos); + void on_actionOpen_here_triggered(); + void on_actionOpen_external_triggered(); + void on_actionShow_external_triggered(); + +}; + +#endif // PROJECTFILESYSTEMWIDGET_H diff --git a/project_fs/projectfilesystemwidget.ui b/project_fs/projectfilesystemwidget.ui new file mode 100644 index 0000000..47c04a7 --- /dev/null +++ b/project_fs/projectfilesystemwidget.ui @@ -0,0 +1,161 @@ + + + ProjectFilesystemWidget + + + + 0 + 0 + 327 + 284 + + + + + + + + + :/icons/edit-find.png + + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 20 + 20 + + + + + + + + Expand tree + + + + + + + Collapse tree + + + + + + + + + Qt::CustomContextMenu + + + QAbstractItemView::NoEditTriggers + + + Qt::ElideMiddle + + + QAbstractItemView::ScrollPerPixel + + + true + + + true + + + false + + + + Path + + + + + + + + Open here + + + + + Open external ... + + + + + Show external ... + + + + + + + + + buttonClear + clicked() + lineFilter + clear() + + + 246 + 37 + + + 212 + 35 + + + + + buttonExpand + clicked() + tree + expandAll() + + + 263 + 28 + + + 251 + 58 + + + + + buttonCollapse + clicked() + tree + collapseAll() + + + 307 + 27 + + + 297 + 71 + + + + + diff --git a/project_fs/projectfilesystemwidgetplugin.cpp b/project_fs/projectfilesystemwidgetplugin.cpp new file mode 100644 index 0000000..48f619c --- /dev/null +++ b/project_fs/projectfilesystemwidgetplugin.cpp @@ -0,0 +1,57 @@ +#include "projectfilesystemwidgetplugin.h" +#include "projectfilesystemwidget.h" +#include +#include +#include +#include + + +ProjectFSWidgetFactory::ProjectFSWidgetFactory() { + setDisplayName(QString::fromLatin1("Project filesystem")); + setId("project_filesystem"); +} + + +Core::NavigationView ProjectFSWidgetFactory::createWidget() { + Core::NavigationView view; + view.widget = new ProjectFilesystemWidget(); + QToolButton * btn = new QToolButton(); + btn->setIcon(Utils::Icons::RELOAD.icon()); + btn->setToolTip(tr("Reload tree")); + view.dockToolBarWidgets << btn; + connect(btn, SIGNAL(clicked()), view.widget, SLOT(projectsChanged())); + btn = new QToolButton(); + btn->setIcon(Utils::Icons::FILTER.icon()); + btn->setToolTip(tr("Setup filters ...")); + view.dockToolBarWidgets << btn; + connect(btn, SIGNAL(clicked()), view.widget, SLOT(filterClicked())); + return view; +} + + +void ProjectFSWidgetFactory::saveSettings(QSettings * settings, int position, QWidget * widget) { + //QMessageBox::information(0, "", QString::fromLatin1(widget->metaObject()->className())); + ProjectFilesystemWidget * w = qobject_cast(widget); + if (!w) return; + settings->beginGroup("ProjectFilesystem"); + settings->beginWriteArray("widget"); + settings->setArrayIndex(position); + settings->setValue("filters", w->currentFilters().toVariant()); + settings->setValue("search", w->currentSearch()); + settings->endArray(); + settings->endGroup(); + settings->sync(); +} + + +void ProjectFSWidgetFactory::restoreSettings(QSettings * settings, int position, QWidget * widget) { + ProjectFilesystemWidget * w = qobject_cast(widget); + if (!w) return; + settings->beginGroup("ProjectFilesystem"); + settings->beginReadArray("widget"); + settings->setArrayIndex(position); + w->setCurrentFilter(FilterDialog::Filter(settings->value("filters", FilterDialog::Filter().toVariant()))); + w->setCurrentSearch(settings->value("search", QString()).toString()); + settings->endArray(); + settings->endGroup(); +} diff --git a/project_fs/projectfilesystemwidgetplugin.h b/project_fs/projectfilesystemwidgetplugin.h new file mode 100644 index 0000000..ccd652d --- /dev/null +++ b/project_fs/projectfilesystemwidgetplugin.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + + +class ProjectFSWidgetFactory: public Core::INavigationWidgetFactory +{ +public: + ProjectFSWidgetFactory(); + ~ProjectFSWidgetFactory() {} + + Core::NavigationView createWidget(); + + void saveSettings(QSettings * settings, int position, QWidget * widget); + void restoreSettings(QSettings * settings, int position, QWidget * widget); + +};