commit 3e3a3da5ed81aa288bc11a01a7df3263137949bb Author: Ivan Pelipenko Date: Tue Aug 25 22:04:16 2020 +0300 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a2cb3e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.svn +CMakeLists.txt.user* diff --git a/AUTHORS.txt b/AUTHORS.txt new file mode 100644 index 0000000..aaa3740 --- /dev/null +++ b/AUTHORS.txt @@ -0,0 +1 @@ +peri4 = Пелипенко Иван diff --git a/README.md b/README.md new file mode 100644 index 0000000..552dee3 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# Qt Creator plugins + +## Introduction + +This repo now contains only one plugin: +* project_fs - panel that show filesystem tree for all opened projects + +## Compile + +To compile plugin you should set these environment variables: +* SDK_QTCREATOR_SRC - path to "qtcreator" sources root +* SDK_QTCREATOR_BUILD - path to "qtcreator" build root + +Plugin library link into SDK_QTCREATOR_BUILD, so no need to install diff --git a/project_fs/ProjectFilesystemPlugin.json.in b/project_fs/ProjectFilesystemPlugin.json.in new file mode 100644 index 0000000..017dcd1 --- /dev/null +++ b/project_fs/ProjectFilesystemPlugin.json.in @@ -0,0 +1,11 @@ +{ + \"Name\" : \"ProjectFilesystemPlugin\", + \"Version\" : \"1.1.0\", + \"CompatVersion\" : \"1.1.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..84e540a --- /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..5113f09 --- /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..2327935 --- /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..140e581 Binary files /dev/null and b/project_fs/icons/edit-find.png differ diff --git a/project_fs/icons/utilities-terminal.png b/project_fs/icons/utilities-terminal.png new file mode 100644 index 0000000..9c8effe Binary files /dev/null and b/project_fs/icons/utilities-terminal.png differ diff --git a/project_fs/projectfilesystem.qrc b/project_fs/projectfilesystem.qrc new file mode 100644 index 0000000..b85c3a6 --- /dev/null +++ b/project_fs/projectfilesystem.qrc @@ -0,0 +1,6 @@ + + + icons/edit-find.png + icons/utilities-terminal.png + + diff --git a/project_fs/projectfilesystemplugin.cpp b/project_fs/projectfilesystemplugin.cpp new file mode 100644 index 0000000..6588643 --- /dev/null +++ b/project_fs/projectfilesystemplugin.cpp @@ -0,0 +1,89 @@ +#include "projectfilesystemplugin.h" +#include "projectfilesystempluginconstants.h" +#include "projectfilesystemwidget.h" + +#include +#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()); + (new ProjectFSWidgetFactory())->setParent(this); + + return true; + } + + void ProjectFilesystemPluginPlugin::extensionsInitialized() + { + Utils::globalMacroExpander()->registerPrefix("ProjectFilesystem", "Project filesystem plugin", [](QString v) -> QString {return v;} ); + Utils::globalMacroExpander()->registerFileVariables("ProjectFilesystem", "Selected item", + []() -> QString { return projectfs_menu_target.absoluteFilePath();}); + // 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..b04970e --- /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..aeb9f8c --- /dev/null +++ b/project_fs/projectfilesystemplugin.pro @@ -0,0 +1,61 @@ +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 = $$(SDK_QTCREATOR_SRC) + +## 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 = $$(SDK_QTCREATOR_BUILD) + +## 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..064c4d2 --- /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..2b2b7a8 --- /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..9520696 --- /dev/null +++ b/project_fs/projectfilesystemwidget.cpp @@ -0,0 +1,328 @@ +#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 +#include +#include + +QFileInfo projectfs_menu_target; + + +ProjectFilesystemWidget::ProjectFilesystemWidget(QWidget * parent): QWidget(parent) { + setupUi(this); + in_proc = need_rebuild = false; + int is = style()->pixelMetric(QStyle::PM_ButtonIconSize, 0, this); + label->setFixedSize(is, is); + 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(Core::FileIconProvider::icon(QFileIconProvider::Folder)); + actionCopy_name->setIcon(Utils::Icons::COPY.icon()); + actionCopy_path->setIcon(Utils::Icons::COPY.icon()); + popup_menu.addActions(QList() << actionOpen_here << actionOpen_external << actionShow_external << actionOpen_terminal); + popup_menu.addSeparator(); + popup_menu.addActions(QList() << actionCopy_name << actionCopy_path); + proj_plug = 0; + //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())); + 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) { + QFileInfoList fl = QDir(dir).entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot, QDir::LocaleAware | QDir::DirsFirst); + checkProcEvents(); + 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(); + 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::setExtVariable() { +} + + +void ProjectFilesystemWidget::checkProcEvents() { + if (tm.elapsed() < 10) return; + QApplication::processEvents(); + tm.start(); +} + + +void ProjectFilesystemWidget::projectsChanged() { + if (in_proc) { + need_rebuild = true; + return; + } + in_proc = true; + tm.start(); + last_expanded.clear(); + item_map.clear(); + int spos = tree->verticalScrollBar()->value(); + rememberExpanded(tree->invisibleRootItem()); + tree->clear(); + QApplication::setOverrideCursor(Qt::WaitCursor); + QList pl = ProjectExplorer::SessionManager::projects(); + for (ProjectExplorer::Project * p: pl) { + QTreeWidgetItem * ri = new QTreeWidgetItem(); + QString dir = p->projectDirectory().toString(); + ri->setText(0, p->displayName()); + QFile logo(dir + "/logo.png"); + if (logo.exists()) + ri->setIcon(0, QIcon(logo.fileName())); + else + ri->setIcon(0, Core::FileIconProvider::icon(QFileIconProvider::Folder)); + 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()); + QApplication::restoreOverrideCursor(); + qApp->processEvents(); + tree->verticalScrollBar()->setValue(spos); + in_proc = false; + if (need_rebuild) { + need_rebuild = false; + projectsChanged(); + } +} + + +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_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_itemClicked(QTreeWidgetItem * item, int column) { + projectfs_menu_target = QFileInfo(); + if (!item) { + setExtVariable(); + return; + } + projectfs_menu_target = QFileInfo(item->data(0, Qt::UserRole).toString()); + setExtVariable(); +} + + +void ProjectFilesystemWidget::on_tree_customContextMenuRequested(const QPoint & pos) { + projectfs_menu_target = QFileInfo(); + QTreeWidgetItem * item = tree->itemAt(pos); + //QMessageBox::information(this, "", QString::number(index.row())); + if (!item) { + setExtVariable(); + return; + } + projectfs_menu_target = QFileInfo(item->data(0, Qt::UserRole).toString()); + setExtVariable(); + actionOpen_here->setEnabled(!projectfs_menu_target.isDir()); + actionOpen_external->setEnabled(!projectfs_menu_target.isDir()); + popup_menu.popup(tree->mapToGlobal(pos)); +} + + +void ProjectFilesystemWidget::on_actionOpen_here_triggered() { + if (projectfs_menu_target.path().isEmpty()) return; + Core::EditorManager::openEditor(projectfs_menu_target.absoluteFilePath(), Core::Constants::K_DEFAULT_TEXT_EDITOR_ID); +} + + +void ProjectFilesystemWidget::on_actionOpen_external_triggered() { + if (projectfs_menu_target.path().isEmpty()) return; + QString wd = QDir::current().absolutePath(); + QDir::setCurrent(projectfs_menu_target.absoluteDir().path()); + QDesktopServices::openUrl(QUrl::fromLocalFile(projectfs_menu_target.absoluteFilePath())); + QDir::setCurrent(wd); +} + + +void ProjectFilesystemWidget::on_actionShow_external_triggered() { + if (projectfs_menu_target.path().isEmpty()) return; + Core::FileUtils::showInGraphicalShell(Core::ICore::mainWindow(), projectfs_menu_target.absoluteFilePath()); +} + + +void ProjectFilesystemWidget::on_actionOpen_terminal_triggered() { + if (projectfs_menu_target.path().isEmpty()) return; + Core::FileUtils::openTerminal(QDir(projectfs_menu_target.absoluteFilePath()).path()); +} + + +void ProjectFilesystemWidget::on_actionCopy_name_triggered() { + if (projectfs_menu_target.path().isEmpty()) return; + QApplication::clipboard()->setText(projectfs_menu_target.fileName()); +} + + +void ProjectFilesystemWidget::on_actionCopy_path_triggered() { + if (projectfs_menu_target.path().isEmpty()) return; + QApplication::clipboard()->setText(projectfs_menu_target.absoluteFilePath()); +} diff --git a/project_fs/projectfilesystemwidget.h b/project_fs/projectfilesystemwidget.h new file mode 100644 index 0000000..f9634f0 --- /dev/null +++ b/project_fs/projectfilesystemwidget.h @@ -0,0 +1,68 @@ +#ifndef PROJECTFILESYSTEMWIDGET_H +#define PROJECTFILESYSTEMWIDGET_H + +#include "ui_projectfilesystemwidget.h" +#include "filterdialog.h" +#include +#include +#include +#include +#include + +extern QFileInfo projectfs_menu_target; + +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); + void setExtVariable(); + void checkProcEvents(); + + bool in_proc, need_rebuild; + ExtensionSystem::IPlugin * proj_plug; + QMenu popup_menu; + QMap item_map; + QSet last_expanded; + FilterDialog filter_dialog; + FilterDialog::Filter cur_filter; + QElapsedTimer tm; + +public slots: + void projectsChanged(); + void filterClicked(); + +private slots: + void fileChanged(); + void startupProjectChanged(); + + void on_tree_itemDoubleClicked(QTreeWidgetItem * item, int ); + void on_lineFilter_textChanged(const QString &); + void on_tree_itemClicked(QTreeWidgetItem *item, int column); + void on_tree_customContextMenuRequested(const QPoint & pos); + void on_actionOpen_here_triggered(); + void on_actionOpen_external_triggered(); + void on_actionShow_external_triggered(); + void on_actionOpen_terminal_triggered(); + void on_actionCopy_name_triggered(); + void on_actionCopy_path_triggered(); + +}; + +#endif // PROJECTFILESYSTEMWIDGET_H diff --git a/project_fs/projectfilesystemwidget.ui b/project_fs/projectfilesystemwidget.ui new file mode 100644 index 0000000..06dbeb2 --- /dev/null +++ b/project_fs/projectfilesystemwidget.ui @@ -0,0 +1,183 @@ + + + ProjectFilesystemWidget + + + + 0 + 0 + 386 + 390 + + + + + + + + + :/icons/edit-find.png + + + true + + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 20 + 20 + + + + + + + + Expand tree + + + + + + + Collapse tree + + + + + + + + + Qt::CustomContextMenu + + + QAbstractItemView::NoEditTriggers + + + Qt::ElideMiddle + + + QAbstractItemView::ScrollPerPixel + + + true + + + true + + + false + + + + Path + + + + + + + + Open as plain + + + + + Open external ... + + + + + Show external ... + + + + + Copy name + + + + + Copy path + + + + + + :/icons/utilities-terminal.png:/icons/utilities-terminal.png + + + Open terminal ... + + + + + + + + + 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..4e28125 --- /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..0cf213a --- /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); + +};