initial commit

This commit is contained in:
2020-08-25 22:04:16 +03:00
commit 3e3a3da5ed
20 changed files with 1240 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/.svn
CMakeLists.txt.user*

1
AUTHORS.txt Normal file
View File

@@ -0,0 +1 @@
peri4 = Пелипенко Иван <peri4ko@yandex.ru>

14
README.md Normal file
View File

@@ -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

View File

@@ -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
}

View File

@@ -0,0 +1,91 @@
#include "filterdialog.h"
#include <utils/utilsicons.h>
#include <QDir>
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;
}

37
project_fs/filterdialog.h Normal file
View File

@@ -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

226
project_fs/filterdialog.ui Normal file
View File

@@ -0,0 +1,226 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FilterDialog</class>
<widget class="QDialog" name="FilterDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>342</width>
<height>250</height>
</rect>
</property>
<property name="windowTitle">
<string>Project filesystem filters</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Input filters, separated by &quot;,&quot;:</string>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Show dirs:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineFilesHide"/>
</item>
<item row="1" column="2">
<widget class="QToolButton" name="toolButton_2"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Hide files:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Show files:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineFilesShow"/>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="toolButton"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Hide dirs:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="lineDirsShow"/>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="lineDirsHide"/>
</item>
<item row="2" column="2">
<widget class="QToolButton" name="toolButton_3"/>
</item>
<item row="3" column="2">
<widget class="QToolButton" name="toolButton_4"/>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>lineFilesShow</tabstop>
<tabstop>lineFilesHide</tabstop>
<tabstop>lineDirsShow</tabstop>
<tabstop>lineDirsHide</tabstop>
<tabstop>toolButton</tabstop>
<tabstop>toolButton_2</tabstop>
<tabstop>toolButton_3</tabstop>
<tabstop>toolButton_4</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>FilterDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>259</x>
<y>238</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>FilterDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>327</x>
<y>238</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>toolButton</sender>
<signal>clicked()</signal>
<receiver>lineFilesShow</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>329</x>
<y>60</y>
</hint>
<hint type="destinationlabel">
<x>269</x>
<y>58</y>
</hint>
</hints>
</connection>
<connection>
<sender>toolButton_2</sender>
<signal>clicked()</signal>
<receiver>lineFilesHide</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>329</x>
<y>93</y>
</hint>
<hint type="destinationlabel">
<x>295</x>
<y>91</y>
</hint>
</hints>
</connection>
<connection>
<sender>toolButton_3</sender>
<signal>clicked()</signal>
<receiver>lineDirsShow</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>329</x>
<y>126</y>
</hint>
<hint type="destinationlabel">
<x>295</x>
<y>124</y>
</hint>
</hints>
</connection>
<connection>
<sender>toolButton_4</sender>
<signal>clicked()</signal>
<receiver>lineDirsHide</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>329</x>
<y>159</y>
</hint>
<hint type="destinationlabel">
<x>295</x>
<y>157</y>
</hint>
</hints>
</connection>
</connections>
</ui>

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/">
<file>icons/edit-find.png</file>
<file>icons/utilities-terminal.png</file>
</qresource>
</RCC>

View File

@@ -0,0 +1,89 @@
#include "projectfilesystemplugin.h"
#include "projectfilesystempluginconstants.h"
#include "projectfilesystemwidget.h"
#include <coreplugin/icore.h>
#include <coreplugin/icontext.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/coreconstants.h>
#include <utils/macroexpander.h>
#include <QAction>
#include <QMessageBox>
#include <QMainWindow>
#include <QMenu>
#include <QDebug>
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

View File

@@ -0,0 +1,29 @@
#pragma once
#include "projectfilesystemplugin_global.h"
#include "projectfilesystemwidgetplugin.h"
#include <extensionsystem/iplugin.h>
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

View File

@@ -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
## <localappdata>/plugins/<ideversion>
## where <localappdata> 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
###### <dirname>_dependencies.pri, where <dirname> 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)

View File

@@ -0,0 +1,9 @@
#pragma once
#include <QtGlobal>
#if defined(PROJECTFILESYSTEMPLUGIN_LIBRARY)
# define PROJECTFILESYSTEMPLUGINSHARED_EXPORT Q_DECL_EXPORT
#else
# define PROJECTFILESYSTEMPLUGINSHARED_EXPORT Q_DECL_IMPORT
#endif

View File

@@ -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

View File

@@ -0,0 +1,328 @@
#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 <utils/macroexpander.h>
#include <QApplication>
#include <QDesktopServices>
#include <QMessageBox>
#include <QInputDialog>
#include <QScrollBar>
#include <QClipboard>
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<QAction*>() << actionOpen_here << actionOpen_external << actionShow_external << actionOpen_terminal);
popup_menu.addSeparator();
popup_menu.addActions(QList<QAction*>() << 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<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());
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());
}

View File

@@ -0,0 +1,68 @@
#ifndef PROJECTFILESYSTEMWIDGET_H
#define PROJECTFILESYSTEMWIDGET_H
#include "ui_projectfilesystemwidget.h"
#include "filterdialog.h"
#include <extensionsystem/iplugin.h>
#include <QSortFilterProxyModel>
#include <QFileSystemModel>
#include <QElapsedTimer>
#include <QMenu>
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<QString, QTreeWidgetItem*> item_map;
QSet<QString> 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

View File

@@ -0,0 +1,183 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ProjectFilesystemWidget</class>
<widget class="QWidget" name="ProjectFilesystemWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>386</width>
<height>390</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="pixmap">
<pixmap resource="projectfilesystem.qrc">:/icons/edit-find.png</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineFilter"/>
</item>
<item>
<widget class="QToolButton" name="buttonClear"/>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="buttonExpand">
<property name="toolTip">
<string>Expand tree</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonCollapse">
<property name="toolTip">
<string>Collapse tree</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTreeWidget" name="tree">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="textElideMode">
<enum>Qt::ElideMiddle</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="rootIsDecorated">
<bool>true</bool>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string>Path</string>
</property>
</column>
</widget>
</item>
</layout>
<action name="actionOpen_here">
<property name="text">
<string>Open as plain</string>
</property>
</action>
<action name="actionOpen_external">
<property name="text">
<string>Open external ...</string>
</property>
</action>
<action name="actionShow_external">
<property name="text">
<string>Show external ...</string>
</property>
</action>
<action name="actionCopy_name">
<property name="text">
<string>Copy name</string>
</property>
</action>
<action name="actionCopy_path">
<property name="text">
<string>Copy path</string>
</property>
</action>
<action name="actionOpen_terminal">
<property name="icon">
<iconset resource="projectfilesystem.qrc">
<normaloff>:/icons/utilities-terminal.png</normaloff>:/icons/utilities-terminal.png</iconset>
</property>
<property name="text">
<string>Open terminal ...</string>
</property>
</action>
</widget>
<resources>
<include location="projectfilesystem.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonClear</sender>
<signal>clicked()</signal>
<receiver>lineFilter</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>246</x>
<y>37</y>
</hint>
<hint type="destinationlabel">
<x>212</x>
<y>35</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonExpand</sender>
<signal>clicked()</signal>
<receiver>tree</receiver>
<slot>expandAll()</slot>
<hints>
<hint type="sourcelabel">
<x>263</x>
<y>28</y>
</hint>
<hint type="destinationlabel">
<x>251</x>
<y>58</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonCollapse</sender>
<signal>clicked()</signal>
<receiver>tree</receiver>
<slot>collapseAll()</slot>
<hints>
<hint type="sourcelabel">
<x>307</x>
<y>27</y>
</hint>
<hint type="destinationlabel">
<x>297</x>
<y>71</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,57 @@
#include "projectfilesystemwidgetplugin.h"
#include "projectfilesystemwidget.h"
#include <utils/utilsicons.h>
#include <QToolButton>
#include <QSettings>
#include <QMessageBox>
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<ProjectFilesystemWidget * >(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<ProjectFilesystemWidget * >(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();
}

View File

@@ -0,0 +1,18 @@
#pragma once
#include <coreplugin/inavigationwidgetfactory.h>
#include <QTableWidget>
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);
};