Qt Creator Plugin HOWTO documentation first and second cut

Signed-off-by: Abhishek Patil <abhishek.patil@vcreatelogic.com>

Merge-request: 145
Reviewed-by: con <qtc-committer@nokia.com>
This commit is contained in:
Abhishek Patil
2010-06-21 15:27:59 +02:00
committed by con
parent cdbe93285b
commit abcb9358c2
155 changed files with 7841 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
<plugin name="DirModelPlugin" version="0.0.1">
<vendor>FooCompany</vendor>
<copyright>(C) 2009-2010 FooCompanyInc Pvt. Ltd.</copyright>
<license>GPL</license>
<description>Dir Model</description>
<url>http://www.FooCompanyInc.com</url>
<dependencyList>
<dependency name="Core"/>
</dependencyList>
</plugin>

View File

@@ -0,0 +1,35 @@
#include "dirmodelpluginplugin.h"
#include <QtPlugin>
#include <QStringList>
#include "DirNavigationFactory.h"
DirModelPluginPlugin::DirModelPluginPlugin()
{
// Do nothing
}
DirModelPluginPlugin::~DirModelPluginPlugin()
{
// Do notning
}
void DirModelPluginPlugin::extensionsInitialized()
{
// Do nothing
}
bool DirModelPluginPlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
addAutoReleasedObject(new DirNavigationFactory);
return true;
}
void DirModelPluginPlugin::shutdown()
{
// Do nothing
}
Q_EXPORT_PLUGIN(DirModelPluginPlugin)

View File

@@ -0,0 +1,18 @@
#ifndef DIRMODELPLUGIN_PLUGIN_H
#define DIRMODELPLUGIN_PLUGIN_H
#include <extensionsystem/iplugin.h>
class DirModelPluginPlugin : public ExtensionSystem::IPlugin
{
public:
DirModelPluginPlugin();
~DirModelPluginPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
};
#endif // DIRMODELPLUGIN_PLUGIN_H

View File

@@ -0,0 +1,25 @@
# Uncomment the lines below and set the path
QTC_SOURCE = C:/Work/QtCreator
QTC_BUILD = C:/Work/QtCreator/build
TEMPLATE = lib
TARGET = DirModelPlugin
IDE_SOURCE_TREE = $$QTC_SOURCE
IDE_BUILD_TREE = $$QTC_BUILD
PROVIDER = FooCompanyInc
include($$QTC_SOURCE/src/qtcreatorplugin.pri)
include($$QTC_SOURCE/src/plugins/coreplugin/coreplugin.pri)
LIBS += -L$$IDE_PLUGIN_PATH/Nokia
HEADERS = dirmodelpluginplugin.h \
dirnavigationfactory.h \
filesystemmodel.h
SOURCES = dirmodelpluginplugin.cpp \
dirnavigationfactory.cpp \
filesystemmodel.cpp
OTHER_FILES = DirModelPlugin.pluginspec

View File

@@ -0,0 +1,35 @@
#include "dirnavigationfactory.h"
#include "filesystemmodel.h"
#include <QTreeView>
#include <QDir>
#include <coreplugin/navigationwidget.h>
/**
\todo
*/
Core::NavigationView DirNavigationFactory::createWidget()
{
Core::NavigationView view;
// Create FileSystemModel and set the defauls path as home path
FileSystemModel* model = new FileSystemModel;
model->setRootPath(QDir::homePath());
// Create TreeView and set model
QTreeView* tree = new QTreeView;
tree->setModel(model);
view.widget = tree;
return view;
}
/**
\todo
*/
QString DirNavigationFactory::displayName()
{
return "Dir View";
}

View File

@@ -0,0 +1,15 @@
#ifndef DIRNAVIGATIONFACTORY_H
#define DIRNAVIGATIONFACTORY_H
#include <coreplugin/inavigationwidgetfactory.h>
class DirNavigationFactory : public Core::INavigationWidgetFactory
{
public:
DirNavigationFactory(){ }
~DirNavigationFactory() { }
Core::NavigationView createWidget();
QString displayName();
};
#endif // DIRNAVIGATIONFACTORY_H

View File

@@ -0,0 +1,20 @@
#include "filesystemmodel.h"
FileSystemModel::FileSystemModel(QObject* parent)
:QFileSystemModel(parent)
{
}
FileSystemModel::~FileSystemModel()
{
}
int FileSystemModel::columnCount(const QModelIndex &parent ) const
{
Q_UNUSED(parent)
return 1;
}

View File

@@ -0,0 +1,17 @@
#ifndef FILESYSTEMMODEL_H
#define FILESYSTEMMODEL_H
#include <QFileSystemModel>
/**
This FileSystemModel is subcalss of QFileSystemModel which just returns only 1 column.
*/
class FileSystemModel : public QFileSystemModel
{
public:
FileSystemModel(QObject* parent=0);
~FileSystemModel();
int columnCount(const QModelIndex &parent = QModelIndex()) const;
};
#endif // FILESYSTEMMODEL_H

View File

@@ -0,0 +1,10 @@
<plugin name="DoNothing" version="0.0.1">
<vendor>FooCompanyInc</vendor>
<copyright>FooCompanyInc</copyright>
<license></license>
<description>DO NOTHING</description>
<url>http://www.FooCompanyInc.com</url>
<dependencyList>
<dependency name="Core"/>
</dependencyList>
</plugin>

View File

@@ -0,0 +1,35 @@
#include "donothingplugin.h"
#include <QtPlugin>
#include <QStringList>
DoNothingPlugin::DoNothingPlugin()
{
// Do nothing
}
DoNothingPlugin::~DoNothingPlugin()
{
// Do notning
}
void DoNothingPlugin::extensionsInitialized()
{
// Do nothing
}
bool DoNothingPlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
return true;
}
void DoNothingPlugin::shutdown()
{
// Do nothing
}
Q_EXPORT_PLUGIN(DoNothingPlugin)

View File

@@ -0,0 +1,19 @@
#ifndef DONOTHING_PLUGIN_H
#define DONOTHING_PLUGIN_H
#include <extensionsystem/iplugin.h>
class DoNothingPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
public:
DoNothingPlugin();
~DoNothingPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
};
#endif // DONOTHING_PLUGIN_H

View File

@@ -0,0 +1,21 @@
QTC_SOURCE = C:/Work/QtCreator
QTC_BUILD = C:/Work/QtCreator/build
TEMPLATE = lib
TARGET = DoNothing
IDE_SOURCE_TREE = $$QTC_SOURCE
IDE_BUILD_TREE = $$QTC_BUILD
PROVIDER = FooCompanyInc
include($$QTC_SOURCE/src/qtcreatorplugin.pri)
include($$QTC_SOURCE/src/plugins/coreplugin/coreplugin.pri)
LIBS += -L$$IDE_PLUGIN_PATH/Nokia
HEADERS = donothingplugin.h
SOURCES = donothingplugin.cpp
OTHER_FILES = DoNothing.pluginspec

View File

@@ -0,0 +1,11 @@
<plugin name="HeaderFilter" version="0.0.1">
<vendor>FooCompanyInc</vendor>
<copyright></copyright>
<license></license>
<description>{{PLUGIN_DESCRIPTION}}</description>
<url>http://www.foocompany.com</url>
<dependencyList>
<dependency name="Core"/>
<dependency name="Find"/>
</dependencyList>
</plugin>

View File

@@ -0,0 +1,142 @@
#include "headerfilter.h"
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/iprojectmanager.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/filesearch.h>
#include<QFutureWatcher>
#include<QLabel>
#include <find/searchresultwindow.h>
#include <texteditor/basetexteditor.h>
using namespace Core;
using namespace Utils;
struct HeaderFilterData
{
HeaderFilterData() : m_projectPlugin(0), m_searchResultWindow(0){}
QFutureWatcher<FileSearchResult> watcher;
ProjectExplorer::ProjectExplorerPlugin* projectExplorer()
{
if(m_projectPlugin)
return m_projectPlugin;
ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance();
m_projectPlugin = pm->getObject<ProjectExplorer::ProjectExplorerPlugin>();
return m_projectPlugin;
}
// Method to search and return the search window
Find::SearchResultWindow* searchResultWindow()
{
if(m_searchResultWindow)
return m_searchResultWindow;
ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance();
m_searchResultWindow = pm->getObject<Find::SearchResultWindow>();
return m_searchResultWindow;
}
private:
ProjectExplorer::ProjectExplorerPlugin* m_projectPlugin;
Find::SearchResultWindow *m_searchResultWindow;
};
HeaderFilter::HeaderFilter()
{
d = new HeaderFilterData;
d->watcher.setPendingResultsLimit(1);
// displayResult(int) is called when every a new
// search result is generated
connect(&d->watcher, SIGNAL(resultReadyAt(int)),this, SLOT(displayResult(int)));
}
HeaderFilter::~HeaderFilter()
{
delete d;
}
QString HeaderFilter::id() const
{
return "HeaderFilter";
}
QString HeaderFilter::name() const
{
return tr("Header Filter");
}
bool HeaderFilter::isEnabled() const
{
QList<ProjectExplorer::Project*> projects = d->projectExplorer()->session()->projects();
if(projects.count())
return true;
return false;
}
QKeySequence HeaderFilter::defaultShortcut() const
{
return QKeySequence();
}
QWidget *HeaderFilter::createConfigWidget()
{
return (new QLabel("This is a header filter"));
}
void HeaderFilter::findAll(const QString &text,QTextDocument::FindFlags findFlags)
{
// Fetch a list of all open projects
QList<ProjectExplorer::Project*> projects = d->projectExplorer()->session()->projects();
// Make a list of files in each project
QStringList files;
Q_FOREACH(ProjectExplorer::Project* project, projects)
files += project->files(ProjectExplorer::Project::AllFiles);
// Remove duplicates
files.removeDuplicates();
//------------------------------------------------------------
// Begin searching
QString includeline = "#include <" + text + ">";
Find::SearchResult *result = d->searchResultWindow()->startNewSearch();
d->watcher.setFuture(QFuture<FileSearchResult>());
//When result gets activated it invokes the openEditor function
connect(result, SIGNAL(activated(Find::SearchResultItem)),
this, SLOT(openEditor(Find::SearchResultItem)));
d->searchResultWindow()->popup(true);
// Let the watcher monitor the search results
d->watcher.setFuture(Utils::findInFiles(includeline, files, findFlags));
}
void HeaderFilter::displayResult(int index)
{
FileSearchResult result = d->watcher.future().resultAt(index);
d->searchResultWindow()->addResult(result.fileName,
result.lineNumber,
result.matchingLine,
result.matchStart,
result.matchLength);
}
void HeaderFilter::openEditor(const Find::SearchResultItem &item)
{
TextEditor::BaseTextEditor::openEditorAt(item.fileName, item.lineNumber, item.index);
}

View File

@@ -0,0 +1,42 @@
#ifndef HEADERFILTER_H
#define HEADERFILTER_H
#include <find/ifindfilter.h>
#include <utils/filesearch.h>
namespace Find {
class SearchResultWindow;
struct SearchResultItem;
}
class QKeySequence;
class QWidget;
struct HeaderFilterData;
class HeaderFilter : public Find::IFindFilter
{
Q_OBJECT
public:
HeaderFilter();
~HeaderFilter();
QString id() const;
QString name() const;
bool isEnabled() const;
QKeySequence defaultShortcut() const;
void findAll(const QString &txt,QTextDocument::FindFlags findFlags);
QWidget *createConfigWidget();
protected slots:
void displayResult(int index);
void openEditor(const Find::SearchResultItem &item);
private:
HeaderFilterData *d;
};
#endif // HEADERFILTER_H

View File

@@ -0,0 +1,36 @@
#include "headerfilterplugin.h"
#include "headerfilter.h"
#include <QtPlugin>
#include <QStringList>
HeaderFilterPlugin::HeaderFilterPlugin()
{
// Do nothing
}
HeaderFilterPlugin::~HeaderFilterPlugin()
{
// Do notning
}
void HeaderFilterPlugin::extensionsInitialized()
{
// Do nothing
}
bool HeaderFilterPlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
addAutoReleasedObject( new HeaderFilter);
return true;
}
void HeaderFilterPlugin::shutdown()
{
// Do nothing
}
Q_EXPORT_PLUGIN(HeaderFilterPlugin)

View File

@@ -0,0 +1,20 @@
#ifndef HEADERFILTER_PLUGIN_H
#define HEADERFILTER_PLUGIN_H
#include <extensionsystem/iplugin.h>
class HeaderFilterPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
public:
HeaderFilterPlugin();
~HeaderFilterPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
};
#endif // HEADERFILTER_PLUGIN_H

View File

@@ -0,0 +1,26 @@
QTC_SOURCE = C:/Work/QtCreator
QTC_BUILD = C:/Work/QtCreator/build
DEFINES += FIND_LIBRARY
TEMPLATE = lib
TARGET = HeaderFilter
IDE_SOURCE_TREE = $$QTC_SOURCE
IDE_BUILD_TREE = $$QTC_BUILD
PROVIDER = FooCompanyInc
include($$QTC_SOURCE/src/libs/extensionsystem/extensionsystem.pri)
include($$QTC_SOURCE/src/qtcreatorplugin.pri)
include($$QTC_SOURCE/src/plugins/coreplugin/coreplugin.pri)
include($$QTC_SOURCE/src/libs/utils/utils.pri)
include($$QTC_SOURCE/src/plugins/projectexplorer/projectexplorer.pri)
include($$QTC_SOURCE/src/plugins/find/find.pri)
LIBS += -L$$IDE_PLUGIN_PATH/Nokia
HEADERS = headerfilterplugin.h \
headerfilter.h
SOURCES = headerfilterplugin.cpp \
headerfilter.cpp
OTHER_FILES = HeaderFilter.pluginspec

View File

@@ -0,0 +1,11 @@
<plugin name="HTMLEditor" version="0.0.1">
<vendor>FooCompanyInc Pvt. Ltd</vendor>
<copyright>(C) 2009-2010 FooCompanyInc Pvt. Ltd.</copyright>
<license></license>
<description>{{PLUGIN_DESCRIPTION}}</description>
<url>http://www.FooCompanyInc.com</url>
<dependencyList>
<dependency name="Core"/>
</dependencyList>
</plugin>

View File

@@ -0,0 +1,129 @@
#include "htmlfile.h"
#include "htmleditor.h"
#include "htmleditorwidget.h"
#include "coreplugin/uniqueidmanager.h"
struct HTMLEditorData
{
HTMLEditorData() : editorWidget(0), file(0) { }
HTMLEditorWidget* editorWidget;
QString displayName;
HTMLFile* file;
QList<int> context;
};
namespace HTMLEditorConstants
{
const char* const C_HTMLEDITOR_MIMETYPE = "text/html";
const char* const C_HTMLEDITOR = "HTML Editor";
}
HTMLEditor::HTMLEditor(HTMLEditorWidget* editorWidget)
:Core::IEditor(editorWidget)
{
d = new HTMLEditorData;
d->editorWidget = editorWidget;
d->file = new HTMLFile(this, editorWidget);
Core::UniqueIDManager* uidm = Core::UniqueIDManager::instance();
d->context << uidm->uniqueIdentifier(HTMLEditorConstants::C_HTMLEDITOR);
connect(d->editorWidget, SIGNAL(contentModified()),
d->file, SLOT(modified()));
connect(d->editorWidget, SIGNAL(titleChanged(QString)),
this, SLOT(slotTitleChanged(QString)));
connect(d->editorWidget, SIGNAL(contentModified()),
this, SIGNAL(changed()));
}
HTMLEditor::~HTMLEditor()
{
delete d;
}
QWidget* HTMLEditor::widget()
{
return d->editorWidget;
}
QList<int> HTMLEditor::context() const
{
return d->context;
}
Core::IFile* HTMLEditor::file()
{
return d->file;
}
bool HTMLEditor::createNew(const QString& contents)
{
Q_UNUSED(contents);
d->editorWidget->setContent(QByteArray());
d->file->setFilename(QString());
return true;
}
bool HTMLEditor::open(const QString &fileName)
{
return d->file->open(fileName);
}
const char* HTMLEditor::kind() const
{
return HTMLEditorConstants::C_HTMLEDITOR;
}
QString HTMLEditor::displayName() const
{
return d->displayName;
}
void HTMLEditor::setDisplayName(const QString& title)
{
if(d->displayName == title)
return;
d->displayName = title;
emit changed();
}
bool HTMLEditor::duplicateSupported() const
{
return false;
}
Core::IEditor* HTMLEditor::duplicate(QWidget* parent)
{
Q_UNUSED(parent);
return 0;
}
QByteArray HTMLEditor::saveState() const
{
return QByteArray();
}
bool HTMLEditor::restoreState(const QByteArray& state)
{
Q_UNUSED(state);
return false;
}
QToolBar* HTMLEditor::toolBar()
{
return 0;
}
bool HTMLEditor::isTemporary() const
{
return false;
}

View File

@@ -0,0 +1,44 @@
#ifndef HTMLEDITOR_H
#define HTMLEDITOR_H
#include "coreplugin/editormanager/ieditor.h"
#include <QToolBar>
class HTMLEditorWidget;
struct HTMLEditorData;
class HTMLEditor : public Core::IEditor
{
Q_OBJECT
public:
HTMLEditor(HTMLEditorWidget* editorWidget);
~HTMLEditor();
bool createNew(const QString& contents = QString());
QString displayName() const;
IEditor* duplicate(QWidget* parent);
bool duplicateSupported() const;
Core::IFile* file();
bool isTemporary() const;
const char* kind() const;
bool open(const QString& fileName = QString()) ;
bool restoreState(const QByteArray& state);
QByteArray saveState() const;
void setDisplayName(const QString &title);
QToolBar* toolBar();
// From Core::IContext
QWidget* widget();
QList<int> context() const;
protected slots:
void slotTitleChanged(const QString& title)
{ setDisplayName(title); }
private:
HTMLEditorData* d;
};
#endif // HTMLEDITOR_H

View File

@@ -0,0 +1,61 @@
#include "coreplugin/editormanager/editormanager.h"
#include "htmleditorfactory.h"
#include "htmleditorwidget.h"
#include "htmleditorplugin.h"
#include "htmleditor.h"
namespace HTMLEditorConstants
{
const char* const C_HTMLEDITOR_MIMETYPE = "text/html";
const char* const C_HTMLEDITOR = "HTML Editor";
}
struct HTMLEditorFactoryData
{
HTMLEditorFactoryData() : kind(HTMLEditorConstants::C_HTMLEDITOR)
{
mimeTypes << QString(HTMLEditorConstants::C_HTMLEDITOR_MIMETYPE);
}
QString kind;
QStringList mimeTypes;
};
HTMLEditorFactory::HTMLEditorFactory(HTMLEditorPlugin* owner)
:Core::IEditorFactory(owner)
{
d = new HTMLEditorFactoryData;
}
HTMLEditorFactory::~HTMLEditorFactory()
{
delete d;
}
QStringList HTMLEditorFactory::mimeTypes() const
{
return d->mimeTypes;
}
QString HTMLEditorFactory::kind() const
{
return d->kind;
}
Core::IFile* HTMLEditorFactory::open(const QString& fileName)
{
Core::EditorManager* em = Core::EditorManager::instance();
Core::IEditor* iface = em->openEditor(fileName, d->kind);
return iface ? iface->file() : 0;
}
Core::IEditor* HTMLEditorFactory::createEditor(QWidget* parent)
{
HTMLEditorWidget* editorWidget = new HTMLEditorWidget(parent);
return new HTMLEditor(editorWidget);
}

View File

@@ -0,0 +1,27 @@
#ifndef HTMLEDITORFACTORY_H
#define HTMLEDITORFACTORY_H
#include "coreplugin/editormanager/ieditorfactory.h"
class HTMLEditorPlugin;
struct HTMLEditorFactoryData;
class HTMLEditorFactory : public Core::IEditorFactory
{
Q_OBJECT
public:
HTMLEditorFactory(HTMLEditorPlugin* owner);
~HTMLEditorFactory();
QStringList mimeTypes() const;
QString kind() const;
Core::IEditor* createEditor(QWidget* parent);
Core::IFile* open(const QString &fileName);
private:
HTMLEditorFactoryData* d;
};
#endif // HTMLEDITORFACTORY_H

View File

@@ -0,0 +1,57 @@
#include "htmleditorplugin.h"
#include "htmleditorfactory.h"
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/mimedatabase.h>
#include <coreplugin/icore.h>
#include <QtPlugin>
#include <QString>
#include <QMessageBox>
#include <QFontDialog>
HTMLEditorPlugin::HTMLEditorPlugin()
{
// Do nothing
}
HTMLEditorPlugin::~HTMLEditorPlugin()
{
// Do notning
}
void HTMLEditorPlugin::extensionsInitialized()
{
// Do nothing
}
bool HTMLEditorPlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Core::ActionManager* am = Core::ICore::instance()->actionManager();
Core::ActionContainer* ac = am->actionContainer(Core::Constants::M_EDIT);
QAction* Font = ac->menu()->addAction("Font");
// Create a command for "Font".
Core::Command* cmd = am->registerAction(new QAction(this),"HTMLEditorPlugin.Font",QList<int>() << 0);
cmd->action()->setText("Font");
Core::ICore* core = Core::ICore::instance();
Core::MimeDatabase* mdb = core->mimeDatabase();
if(!mdb->addMimeTypes("text-html-mimetype.xml", errMsg))
return false;
QMessageBox::information(0, "Msg", *errMsg);
addAutoReleasedObject(new HTMLEditorFactory(this));
return true;
}
void HTMLEditorPlugin::shutdown()
{
// Do nothing
}
Q_EXPORT_PLUGIN(HTMLEditorPlugin)

View File

@@ -0,0 +1,21 @@
#ifndef HTMLEDITOR_PLUGIN_H
#define HTMLEDITOR_PLUGIN_H
#include "extensionsystem/iplugin.h"
#include "coreplugin/uniqueidmanager.h"
class HTMLEditorPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
public:
HTMLEditorPlugin();
~HTMLEditorPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
};
#endif // HTMLEDITOR_PLUGIN_H

View File

@@ -0,0 +1,31 @@
QTC_SOURCE = C:/Work/QtCreator
QTC_BUILD = C:/Work/QtCreator/build
TEMPLATE = lib
TARGET = HTMLEditor
IDE_SOURCE_TREE = $$QTC_SOURCE
IDE_BUILD_TREE = $$QTC_BUILD
PROVIDER = FooCompanyInc
QT += webkit
PROVIDER = FooCompanyInc
include($$QTC_SOURCE/src/qtcreatorplugin.pri)
include($$QTC_SOURCE/src/plugins/coreplugin/coreplugin.pri)
LIBS += -L$$IDE_PLUGIN_PATH/Nokia
HEADERS = htmleditorplugin.h \
htmleditorwidget.h \
htmlfile.h \
htmleditor.h \
htmleditorfactory.h
SOURCES = htmleditorplugin.cpp \
htmleditorwidget.cpp \
htmlfile.cpp \
htmleditor.cpp \
htmleditorfactory.cpp
OTHER_FILES = HTMLEditor.pluginspec \
text-html-mimetype.xml

View File

@@ -0,0 +1,82 @@
#include "htmleditorwidget.h"
#include <QTextEdit>
#include <QPlainTextEdit>
#include <QtWebKit>
#include <QDebug>
struct HTMLEditorWidgetData
{
QWebView* webView;
QPlainTextEdit* textEdit;
bool modified;
QString path;
};
HTMLEditorWidget::HTMLEditorWidget(QWidget* parent):QTabWidget(parent)
{
d = new HTMLEditorWidgetData;
d->webView = new QWebView;
d->textEdit = new QPlainTextEdit;
addTab(d->webView, "Preview");
addTab(d->textEdit, "Source");
setTabPosition(QTabWidget::South);
setTabShape(QTabWidget::Triangular);
d->textEdit->setFont( QFont("Courier", 12) );
connect(this, SIGNAL(currentChanged(int)),
this, SLOT(slotCurrentTabChanged(int)));
connect(d->textEdit, SIGNAL(textChanged()),
this, SLOT(slotContentModified()));
connect(d->webView, SIGNAL(titleChanged(QString)),
this, SIGNAL(titleChanged(QString)));
d->modified = false;
}
HTMLEditorWidget::~HTMLEditorWidget()
{
delete d;
}
void HTMLEditorWidget::setContent(const QByteArray& ba, const QString& path)
{
if(path.isEmpty())
d->webView->setHtml(ba);
else
d->webView->setHtml(ba, "file:///" + path);
d->textEdit->setPlainText(ba);
d->modified = false;
d->path = path;
}
QByteArray HTMLEditorWidget::content() const
{
QString HTMLText = d->textEdit->toPlainText();
return HTMLText.toAscii();
}
QString HTMLEditorWidget::title() const
{
return d->webView->title();
}
void HTMLEditorWidget::slotCurrentTabChanged(int tab)
{
if(tab == 0 && d->modified)
setContent( content(), d->path );
}
void HTMLEditorWidget::slotContentModified()
{
d->modified = true;
emit contentModified();
}

View File

@@ -0,0 +1,32 @@
#ifndef RTEDITORWIDGET_H
#define RTEDITORWIDGET_H
#include<QTabWidget>
struct HTMLEditorWidgetData;
class HTMLEditorWidget:public QTabWidget
{
Q_OBJECT
public:
HTMLEditorWidget(QWidget* parent = 0);
~HTMLEditorWidget();
void setContent(const QByteArray& ba, const QString& path=QString());
QByteArray content() const;
QString title() const;
protected slots:
void slotCurrentTabChanged(int tab);
void slotContentModified();
signals:
void contentModified();
void titleChanged(const QString&);
private:
HTMLEditorWidgetData* d;
};
#endif // RTEDITORWIDGET_H

View File

@@ -0,0 +1,130 @@
#include "htmlfile.h"
#include<QFile>
#include<QFileInfo>
namespace HTMLEditorConstants
{
const char* const C_HTMLEDITOR_MIMETYPE = "text/html";
const char* const C_HTMLEDITOR = "HTML Editor";
}
struct HTMLFileData
{
HTMLFileData(): mimeType(HTMLEditorConstants::C_HTMLEDITOR),
editorWidget(0), editor(0), modified(false) { }
const QString mimeType;
HTMLEditorWidget* editorWidget;
HTMLEditor* editor;
QString fileName;
bool modified;
};
HTMLFile::HTMLFile(HTMLEditor* editor, HTMLEditorWidget* editorWidget)
: Core::IFile(editor)
{
d = new HTMLFileData;
d->editor = editor;
d->editorWidget = editorWidget;
}
HTMLFile::~HTMLFile()
{
delete d;
}
void HTMLFile::setModified(bool val)
{
if(d->modified == val)
return;
d->modified = val;
emit changed();
}
bool HTMLFile::isModified() const
{
return d->modified;
}
QString HTMLFile::mimeType() const
{
return d->mimeType;
}
bool HTMLFile::save(const QString &fileName)
{
QFile file(fileName);
if(file.open(QFile::WriteOnly))
{
d->fileName = fileName;
QByteArray content = d->editorWidget->content();
file.write(content);
setModified(false);
return true;
}
return false;
}
bool HTMLFile::open(const QString &fileName)
{
QFile file(fileName);
if(file.open(QFile::ReadOnly))
{
d->fileName = fileName;
QString path = QFileInfo(fileName).absolutePath();
d->editorWidget->setContent(file.readAll(), path);
d->editor->setDisplayName(d->editorWidget->title());
return true;
}
return false;
}
void HTMLFile::setFilename(const QString& filename)
{
d->fileName = filename;
}
QString HTMLFile::fileName() const
{
return d->fileName;
}
QString HTMLFile::defaultPath() const
{
return QString();
}
QString HTMLFile::suggestedFileName() const
{
return QString();
}
QString HTMLFile::fileFilter() const
{
return QString();
}
QString HTMLFile::fileExtension() const
{
return QString();
}
bool HTMLFile::isReadOnly() const
{
return false;
}
bool HTMLFile::isSaveAsAllowed() const
{
return true;
}
void HTMLFile::modified(ReloadBehavior* behavior)
{
Q_UNUSED(behavior);
}

View File

@@ -0,0 +1,38 @@
#ifndef HTMLFILE_H
#define HTMLFILE_H
#include "coreplugin/ifile.h"
#include "htmleditorwidget.h"
#include "htmleditor.h"
struct HTMLFileData;
class HTMLFile : public Core::IFile
{
Q_OBJECT
public:
HTMLFile(HTMLEditor* editor, HTMLEditorWidget* editorWidget);
~HTMLFile();
void setModified(bool val=true);
bool isModified() const ;
bool save(const QString &filename);
bool open(const QString &filename);
void setFilename(const QString &filename);
QString mimiType(void) const ;
QString fileName() const;
QString defaultPath() const ;
QString mimeType() const;
QString suggestedFileName() const;
QString fileFilter() const;
QString fileExtension() const;
bool isReadOnly() const;
bool isSaveAsAllowed() const;
void modified(ReloadBehavior* behavior);
protected slots:
void modified() { setModified(true); }
private:
HTMLFileData* d;
};
#endif // HTMLFILE_H

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
<mime-type type="text/html">
<sub-class-of type="text/plain"/>
<comment>HTML File</comment>
<glob pattern="*.html"/>
</mime-type>
</mime-info>

View File

@@ -0,0 +1,10 @@
<plugin name="loggermode" version="0.0.1">
<vendor>FoocompanyInc</vendor>
<copyright></copyright>
<license></license>
<description>{{PLUGIN_DESCRIPTION}}</description>
<url>http://www.FooCompanyInc.com</url>
<dependencyList>
<dependency name="Core"/>
</dependencyList>
</plugin>

View File

@@ -0,0 +1,139 @@
#include "loggermode.h"
#include "loggermodewidget.h"
#include <extensionsystem/pluginmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
#include <utils/styledbar.h>
#include <utils/iwelcomepage.h>
#include <coreplugin/uniqueidmanager.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/session.h>
#include <projectexplorer/project.h>
#include <QtCore/QSettings>
#include <QStackedWidget>
#include <QLabel>
#include <QComboBox>
#include <QVBoxLayout>
#include <QPushbutton>
#include <QMessageBox>
struct LoggerModeData
{
QWidget *m_widget;
QLabel *currentProjectsLabel;
QLabel *addProjectLabel;
QComboBox *currentProjectsCombobox;
QComboBox *addProjectComboBox;
QPushButton *addToProjectButton;
QStackedWidget *stackedWidget;
};
LoggerMode::LoggerMode()
{
d = new LoggerModeData;
d->m_widget = new QWidget;
d->currentProjectsLabel = new QLabel("Current projects :");
d->currentProjectsLabel->setFixedWidth(90);
d->currentProjectsCombobox = new QComboBox;
d->currentProjectsCombobox->setSizePolicy(QSizePolicy::Preferred,
QSizePolicy::Preferred);
d->addProjectLabel = new QLabel("Add Project :");
d->addProjectLabel->setAlignment(Qt::AlignRight);
d->addProjectComboBox = new QComboBox;
d->addProjectComboBox->setSizePolicy(QSizePolicy::Preferred,
QSizePolicy::Preferred);
d->addProjectComboBox->setEditable(true);
d->addToProjectButton = new QPushButton(tr("Add Project"));
d->addToProjectButton->setFixedWidth(80);
QHBoxLayout *hLayout = new QHBoxLayout;
hLayout->addWidget(d->currentProjectsLabel);
hLayout->addWidget(d->currentProjectsCombobox);
hLayout->addWidget(d->addProjectLabel);
hLayout->addWidget(d->addProjectComboBox);
hLayout->addWidget(d->addToProjectButton);
d->stackedWidget = new QStackedWidget;
QVBoxLayout* layout = new QVBoxLayout;
layout->addLayout(hLayout);
layout->addWidget(d->stackedWidget);
d->m_widget->setLayout(layout);
d->addProjectComboBox->addItem("Project 1");
d->addProjectComboBox->addItem("Project 2");
d->addProjectComboBox->addItem("Project 3");
connect(d->addToProjectButton,SIGNAL(clicked()),
this,SLOT(addItem()));
connect(d->currentProjectsCombobox, SIGNAL(currentIndexChanged(int)),
d->stackedWidget, SLOT(setCurrentIndex(int)));
}
LoggerMode::~LoggerMode()
{
delete d->m_widget;
delete d;
}
void LoggerMode::addItem()
{
d->currentProjectsCombobox->addItem(d->addProjectComboBox->currentText());
addNewStackWidgetPage(d->currentProjectsCombobox->itemText(0));
d->addProjectComboBox->removeItem(d->addProjectComboBox->currentIndex());
}
QString LoggerMode::name() const
{
return tr("LoggerMode");
}
QIcon LoggerMode::icon() const
{
return QIcon(QLatin1String(":/core/images/qtcreator_logo_32.png"));
}
int LoggerMode::priority() const
{
return 0;
}
QWidget* LoggerMode::widget()
{
return d->m_widget;
}
const char* LoggerMode::uniqueModeName() const
{
return "LoggerMode" ;
}
QList<int> LoggerMode::context() const
{
return QList<int>();
}
void LoggerMode::addNewStackWidgetPage(const QString projectName)
{
d->stackedWidget->addWidget(new LoggerModeWidget(projectName));
}

View File

@@ -0,0 +1,35 @@
#ifndef LOGGERMODE_H
#define LOGGERMODE_H
#include <coreplugin/imode.h>
#include <projectexplorer/project.h>
class QWidget;
struct LoggerModeData;
class LoggerMode :public Core::IMode
{
Q_OBJECT
public:
LoggerMode();
~LoggerMode();
// IMode
QString name() const;
QIcon icon() const;
int priority() const;
QWidget *widget();
const char *uniqueModeName() const;
QList<int> context() const;
void activated();
QString contextHelpId() const { return QLatin1String("Qt Creator"); }
protected slots:
void addNewStackWidgetPage(const QString projectName);
void addItem();
private:
LoggerModeData *d;
};
#endif // NEWMODE_H

View File

@@ -0,0 +1,36 @@
#include "loggermodePlugin.h"
#include "loggermode.h"
#include <QtPlugin>
#include <QStringList>
LoggerModePlugin::LoggerModePlugin()
{
}
LoggerModePlugin::~LoggerModePlugin()
{
}
void LoggerModePlugin::extensionsInitialized()
{
}
bool LoggerModePlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
loggerMode = new LoggerMode;
addAutoReleasedObject(loggerMode);
return true;
}
void LoggerModePlugin::shutdown()
{
// Do nothing
}
Q_EXPORT_PLUGIN(LoggerModePlugin)

View File

@@ -0,0 +1,21 @@
#ifndef LOGGERMODE_PLUGIN_H
#define LOGGERMODE_PLUGIN_H
#include <extensionsystem/iplugin.h>
class LoggerMode;
class LoggerModePlugin : public ExtensionSystem::IPlugin
{
public:
LoggerModePlugin();
~LoggerModePlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
private:
LoggerMode *loggerMode;
};
#endif // NEWMODE_PLUGIN_H

View File

@@ -0,0 +1,20 @@
QTC_SOURCE = C:/Work/QtCreator
QTC_BUILD = C:/Work/QtCreator/build
TEMPLATE = lib
TARGET = loggermode
IDE_SOURCE_TREE = $$QTC_SOURCE
IDE_BUILD_TREE = $$QTC_BUILD
PROVIDER = FooCompanyInc
include($$QTC_SOURCE/src/qtcreatorplugin.pri)
include($$QTC_SOURCE/src/plugins/coreplugin/coreplugin.pri)
LIBS += -L$$IDE_PLUGIN_PATH/Nokia
HEADERS = loggermodePlugin.h \
loggermode.h \
loggermodewidget.h
SOURCES = loggermodePlugin.cpp \
loggermode.cpp \
loggermodewidget.cpp
OTHER_FILES = LoggerMode.pluginspec

View File

@@ -0,0 +1,192 @@
#include "loggermodewidget.h"
#include<QTableWidget>
#include <QFileDialog>
#include<QLabel>
#include<QGroupBox>
#include<QComboBox>
#include<QPushButton>
#include<QLineEdit>
#include<QTime>
#include<QTimer>
#include<QTextEdit>
#include<QCalendarWidget>
#include<QComboBox>
#include<QGridLayout>
#include<QMessageBox>
#include<QApplication>
#include<QTextStream>
#include<QCloseEvent>
struct LoggerModeWidgetData
{
QLabel *progressLabel;
QLabel *hoursWorkedLabel;
QLabel *dateLabel;
QLabel *descriptionLabel;
QCalendarWidget *calendar;
QComboBox *progressComboBox;
QLineEdit *hoursWorkedLineEdit;
QPushButton *startTimerButton;
QPushButton *stopTimerButton;
QPushButton *saveButton;
QTimer *timer;
QTextEdit *textEdit;
QString projectName;
int totalTime;
};
LoggerModeWidget::LoggerModeWidget(const QString projectName, QWidget* parent)
:QWidget(parent)
{
d = new LoggerModeWidgetData;
d->projectName = projectName;
d->totalTime = 0;
/*
// Catch hold of the plugin-manager
ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance();
// Look for the ProjectExplorerPlugin object
ProjectExplorer::ProjectExplorerPlugin* projectExplorerPlugin
= pm->getObject<ProjectExplorer::ProjectExplorerPlugin>();
// Fetch a list of all open projects
QList<ProjectExplorer::Project*> projects =projectExplorerPlugin->session()->projects();
Q_FOREACH(ProjectExplorer::Project* project, projects)
d->projectExplorerCombo->addItem( project->name());
*/
QStringList percentList;
percentList <<"10%" <<"20%" <<"30%" <<"40%" <<"50%"
<<"60%" <<"70%" <<"80%" <<"90%" <<"100%" ;
d->progressLabel = new QLabel("Progress:");
d->hoursWorkedLabel = new QLabel("Hours Worked:");
d->dateLabel = new QLabel("Date:");
d->descriptionLabel = new QLabel("Description :");
d->hoursWorkedLineEdit = new QLineEdit;
d->hoursWorkedLineEdit->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
d->progressComboBox = new QComboBox;
d->progressComboBox->addItems(percentList);
d->progressComboBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
d->startTimerButton = new QPushButton(tr("Start Timer"));
d->startTimerButton->setFixedWidth(80);
d->stopTimerButton = new QPushButton(tr("Pause Timer"));
d->stopTimerButton->setFixedWidth(80);
d->stopTimerButton->setCheckable(true);
d->textEdit = new QTextEdit(this);
d->textEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
d->calendar = new QCalendarWidget;
d->saveButton = new QPushButton(tr("Save To File"));
d->saveButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
QGroupBox *timeLoggerBox = new QGroupBox(tr("Time Logger"));
QGridLayout *gLayout = new QGridLayout;
gLayout->addWidget(d->dateLabel, 0, 0, 1, 1);
gLayout->addWidget(d->calendar, 1, 0, 1, 3);
gLayout->addWidget(d->progressLabel, 2, 0, 1, 1);
gLayout->addWidget(d->progressComboBox, 2, 1, 1, 1);
gLayout->addWidget(d->hoursWorkedLabel, 3, 0, 1, 1);
gLayout->addWidget(d->hoursWorkedLineEdit, 3, 1, 1, 1);
gLayout->addWidget(d->startTimerButton, 4, 1, 1, 1);
gLayout->addWidget(d->stopTimerButton, 4, 2, 1, 1);
timeLoggerBox->setLayout(gLayout);
d->timer = new QTimer(this);
//d->time.setHMS(0,0,0);
// connection of SIGNALS and SLOTS
connect(d->timer, SIGNAL(timeout()), this, SLOT(updateTime()));
connect(d->startTimerButton,SIGNAL(clicked()),this,SLOT(startTimeLog()));
connect(d->stopTimerButton,SIGNAL(clicked()),this,SLOT(endTimeLog()));
connect(d->saveButton, SIGNAL(clicked()), this, SLOT(saveToFile()));
QVBoxLayout *vLayout = new QVBoxLayout;
vLayout->addWidget(d->descriptionLabel);
vLayout->addWidget(d->textEdit);
QHBoxLayout * hLayout = new QHBoxLayout;
hLayout->addWidget(timeLoggerBox);
hLayout->addLayout(vLayout);
QHBoxLayout *bLayout = new QHBoxLayout;
bLayout->addStretch(1);
bLayout->addWidget(d->saveButton);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addLayout(hLayout);
mainLayout->addLayout(bLayout);
mainLayout->addStretch(1);
}
LoggerModeWidget::~LoggerModeWidget()
{
delete d;
}
bool LoggerModeWidget::saveToFile()
{
QString fileName = QFileDialog::getSaveFileName(this);
if (fileName.isEmpty())
return false;
QFile file(fileName);
if (!file.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::critical(this, tr("Application"),
tr("Unable to open file %1 for writing :\n%2.")
.arg(fileName)
.arg(file.errorString()));
return false;
}
QTextStream out(&file);
#ifndef QT_NO_CURSOR
QApplication::setOverrideCursor(Qt::WaitCursor);
#endif
out << "Project name : " << d->projectName << "\n";
out << "Date : " << d->calendar->selectedDate().toString() << "\n";
out << "Progress : " << d->progressComboBox->currentText() << "\n";
out << "Duration : " << d->hoursWorkedLineEdit->text() << "\n\n";
out << "Description : " << d->textEdit->toPlainText();
#ifndef QT_NO_CURSOR
QApplication::restoreOverrideCursor();
#endif
return true;
}
void LoggerModeWidget::startTimeLog()
{
d->totalTime = 0;
d->timer->start(1000);
}
void LoggerModeWidget::endTimeLog()
{
if(d->stopTimerButton->isChecked())
{
d->stopTimerButton->setText("Continue Timer");
d->timer->stop();
}
else
{
d->stopTimerButton->setText("Pause Timer");
d->timer->start(1000);
}
}
void LoggerModeWidget::updateTime()
{
d->totalTime++;
QTime time(0,0,0);
time = time.addSecs(d->totalTime);
d->hoursWorkedLineEdit->setText(time.toString());
}
/*
void LoggerModeWidget::setProjectName(QString name)
{
d->projectName = name;
}
*/

View File

@@ -0,0 +1,28 @@
#ifndef LOGGERMODEWIDGET_H
#define LOGGERMODEWIDGET_H
#include <QWidget>
struct LoggerModeWidgetData;
class LoggerModeWidget : public QWidget
{
Q_OBJECT
public:
LoggerModeWidget(const QString projectName, QWidget* parent = 0);
~LoggerModeWidget();
public slots:
//void setProjectName(QString name);
protected slots:
bool saveToFile();
void startTimeLog();
void endTimeLog();
void updateTime();
private:
LoggerModeWidgetData* d;
};
#endif // NEWMODEWIDGET_H

View File

@@ -0,0 +1,10 @@
<plugin name="DoNothing" version="0.0.1">
<vendor>FooCompanyInc</vendor>
<copyright>FooCompanyInc</copyright>
<license></license>
<description>DO NOTHING</description>
<url>http://www.FooCompanyInc.com</url>
<dependencyList>
<dependency name="Core"/>
</dependencyList>
</plugin>

View File

@@ -0,0 +1,64 @@
#include "donothingplugin.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/icore.h>
#include <QKeySequence>
#include <QtPlugin>
#include <QStringList>
#include <QMessageBox>
DoNothingPlugin::DoNothingPlugin()
{
// Do nothing
}
DoNothingPlugin::~DoNothingPlugin()
{
// Do notning
}
void DoNothingPlugin::extensionsInitialized()
{
// Do nothing
}
bool DoNothingPlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
// Fetch the action manager
Core::ActionManager* am = Core::ICore::instance()->actionManager();
// Create a DoNothing menu
Core::ActionContainer* ac = am->createMenu("DoNothingPlugin.DoNothingMenu");
ac->menu()->setTitle("DoNothing");
// Create a command for "About DoNothing".
QAction *action = new QAction(tr("About DoNothing"),this);
Core::Command* cmd = am->registerAction(action,"DoNothingPlugin.AboutDoNothing",QList<int>() << 0);
// Add DoNothing menu to the menubar
am->actionContainer(Core::Constants::MENU_BAR)->addMenu(ac);
// Add the "About DoNothing" action to the DoNothing menu
ac->addAction(cmd);
// Connect the action
connect(action, SIGNAL(triggered(bool)), this, SLOT(about()));
return true;
}
void DoNothingPlugin::shutdown()
{
// Do nothing
}
void DoNothingPlugin::about()
{
QMessageBox::information(0, "About DoNothing Plugin",
"Seriously dude, this plugin does nothing");
}
Q_EXPORT_PLUGIN(DoNothingPlugin)

View File

@@ -0,0 +1,22 @@
#ifndef DONOTHING_PLUGIN_H
#define DONOTHING_PLUGIN_H
#include <extensionsystem/iplugin.h>
class DoNothingPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
public:
DoNothingPlugin();
~DoNothingPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
private slots:
void about();
};
#endif // DONOTHING_PLUGIN_H

View File

@@ -0,0 +1,20 @@
QTC_SOURCE = C:/Work/QtCreator
QTC_BUILD = C:/Work/QtCreator/build
TEMPLATE = lib
TARGET = DoNothing
IDE_SOURCE_TREE = $$QTC_SOURCE
IDE_BUILD_TREE = $$QTC_BUILD
PROVIDER = FooCompanyInc
include($$QTC_SOURCE/src/qtcreatorplugin.pri)
include($$QTC_SOURCE/src/plugins/coreplugin/coreplugin.pri)
LIBS += -L$$IDE_PLUGIN_PATH/Nokia
HEADERS = donothingplugin.h
SOURCES = donothingplugin.cpp
OTHER_FILES = DoNothing.pluginspec

View File

@@ -0,0 +1,10 @@
<plugin name="DoNothing" version="0.0.1">
<vendor>FooCompanyInc</vendor>
<copyright>FooCompanyInc</copyright>
<license></license>
<description>DO NOTHING</description>
<url>http://www.FooCompanyInc.com</url>
<dependencyList>
<dependency name="Core"/>
</dependencyList>
</plugin>

View File

@@ -0,0 +1,66 @@
#include "donothingplugin.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/icore.h>
#include <QKeySequence>
#include <QtPlugin>
#include <QStringList>
#include <QMessageBox>
DoNothingPlugin::DoNothingPlugin()
{
// Do nothing
}
DoNothingPlugin::~DoNothingPlugin()
{
// Do notning
}
void DoNothingPlugin::extensionsInitialized()
{
// Do nothing
}
bool DoNothingPlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
// Fetch the action manager
Core::ActionManager* am = Core::ICore::instance()->actionManager();
// Create a DoNothing menu
Core::ActionContainer* ac = am->createMenu("DoNothingPlugin.DoNothingMenu");
ac->menu()->setTitle("DoNothing");
// Create a command for "About DoNothing".
QAction *action = new QAction(tr("About DoNothing"),this);
Core::Command* cmd = am->registerAction(action,"DoNothingPlugin.AboutDoNothing",QList<int>() << 0);
// Insert the "DoNothing" menu between "Window" and "Help".
QMenu* windowMenu = am->actionContainer(Core::Constants::M_HELP)->menu();
QMenuBar* menuBar = am->actionContainer(Core::Constants::MENU_BAR)->menuBar();
menuBar->insertMenu(windowMenu->menuAction(), ac->menu());
// Add the "About DoNothing" action to the DoNothing menu
ac->addAction(cmd);
// Connect the action
connect(action, SIGNAL(triggered(bool)), this, SLOT(about()));
return true;
}
void DoNothingPlugin::shutdown()
{
// Do nothing
}
void DoNothingPlugin::about()
{
QMessageBox::information(0, "About DoNothing Plugin",
"Seriously dude, this plugin does nothing");
}
Q_EXPORT_PLUGIN(DoNothingPlugin)

View File

@@ -0,0 +1,22 @@
#ifndef DONOTHING_PLUGIN_H
#define DONOTHING_PLUGIN_H
#include <extensionsystem/iplugin.h>
class DoNothingPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
public:
DoNothingPlugin();
~DoNothingPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
private slots:
void about();
};
#endif // DONOTHING_PLUGIN_H

View File

@@ -0,0 +1,20 @@
QTC_SOURCE = C:/Work/QtCreator
QTC_BUILD = C:/Work/QtCreator/build
TEMPLATE = lib
TARGET = DoNothing
IDE_SOURCE_TREE = $$QTC_SOURCE
IDE_BUILD_TREE = $$QTC_BUILD
PROVIDER = FooCompanyInc
include($$QTC_SOURCE/src/qtcreatorplugin.pri)
include($$QTC_SOURCE/src/plugins/coreplugin/coreplugin.pri)
LIBS += -L$$IDE_PLUGIN_PATH/Nokia
HEADERS = donothingplugin.h
SOURCES = donothingplugin.cpp
OTHER_FILES = DoNothing.pluginspec

View File

@@ -0,0 +1,10 @@
<plugin name="DoNothing" version="0.0.1">
<vendor>FooCompanyInc</vendor>
<copyright>FooCompanyInc</copyright>
<license></license>
<description>DO NOTHING</description>
<url>http://www.FooCompanyInc.com</url>
<dependencyList>
<dependency name="Core"/>
</dependencyList>
</plugin>

View File

@@ -0,0 +1,48 @@
#include "donothingplugin.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/icore.h>
#include <QKeySequence>
#include <QtPlugin>
#include <QStringList>
DoNothingPlugin::DoNothingPlugin()
{
// Do nothing
}
DoNothingPlugin::~DoNothingPlugin()
{
// Do notning
}
void DoNothingPlugin::extensionsInitialized()
{
// Do nothing
}
bool DoNothingPlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
// Fetch the action manager
Core::ActionManager* am = Core::ICore::instance()->actionManager();
// Create a command for "About DoNothing".
Core::Command* cmd = am->registerAction(new QAction(tr("About DoNothing"),this),"DoNothingPlugin.AboutDoNothing",
QList<int>() <<Core::Constants::C_GLOBAL_ID);
// Add the command to Help menu
am->actionContainer(Core::Constants::M_HELP)->addAction(cmd);
return true;
}
void DoNothingPlugin::shutdown()
{
// Do nothing
}
Q_EXPORT_PLUGIN(DoNothingPlugin)

View File

@@ -0,0 +1,19 @@
#ifndef DONOTHING_PLUGIN_H
#define DONOTHING_PLUGIN_H
#include <extensionsystem/iplugin.h>
class DoNothingPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
public:
DoNothingPlugin();
~DoNothingPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
};
#endif // DONOTHING_PLUGIN_H

View File

@@ -0,0 +1,20 @@
QTC_SOURCE = C:/Work/QtCreator
QTC_BUILD = C:/Work/QtCreator/build
TEMPLATE = lib
TARGET = DoNothing
IDE_SOURCE_TREE = $$QTC_SOURCE
IDE_BUILD_TREE = $$QTC_BUILD
PROVIDER = FooCompanyInc
include($$QTC_SOURCE/src/qtcreatorplugin.pri)
include($$QTC_SOURCE/src/plugins/coreplugin/coreplugin.pri)
LIBS += -L$$IDE_PLUGIN_PATH/Nokia
HEADERS = donothingplugin.h
SOURCES = donothingplugin.cpp
OTHER_FILES = DoNothing.pluginspec

View File

@@ -0,0 +1,11 @@
<plugin name="DoNothing" version="0.0.1">
<vendor>FooCompanyInc</vendor>
<copyright>FooCompanyInc</copyright>
<license>
GPL</license>
<description>DO NOTHING</description>
<url>http://www.FooCompanyInc.com</url>
<dependencyList>
<dependency name="Core"/>
</dependencyList>
</plugin>

View File

@@ -0,0 +1,57 @@
#include "donothingplugin.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/icore.h>
#include <QKeySequence>
#include <QtPlugin>
#include <QStringList>
#include <QMessageBox>
DoNothingPlugin::DoNothingPlugin()
{
// Do nothing
}
DoNothingPlugin::~DoNothingPlugin()
{
// Do notning
}
void DoNothingPlugin::extensionsInitialized()
{
// Do nothing
}
bool DoNothingPlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
// Fetch the action manager
Core::ActionManager* am = Core::ICore::instance()->actionManager();
// Create a command for "About DoNothing".
QAction *action = new QAction(tr("About DoNothing"),this);
Core::Command* cmd = am->registerAction(action,"DoNothingPlugin.AboutDoNothing",QList<int>() << 0);
Core::ActionContainer* ac = am->createMenu("DoNothingPlugin.DoNothingMenu");
// Add the command to Help menu
am->actionContainer(Core::Constants::M_HELP)->addAction(cmd);
connect(action, SIGNAL(triggered(bool)), this, SLOT(about()));
return true;
}
void DoNothingPlugin::shutdown()
{
// Do nothing
}
void DoNothingPlugin::about()
{
QMessageBox::information(0, "About DoNothing Plugin",
"Seriously dude, this plugin does nothing");
}
Q_EXPORT_PLUGIN(DoNothingPlugin)

View File

@@ -0,0 +1,22 @@
#ifndef DONOTHING_PLUGIN_H
#define DONOTHING_PLUGIN_H
#include <extensionsystem/iplugin.h>
class DoNothingPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
public:
DoNothingPlugin();
~DoNothingPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
private slots:
void about();
};
#endif // DONOTHING_PLUGIN_H

View File

@@ -0,0 +1,20 @@
QTC_SOURCE = C:/Work/QtCreator
QTC_BUILD = C:/Work/QtCreator/build
TEMPLATE = lib
TARGET = DoNothing
IDE_SOURCE_TREE = $$QTC_SOURCE
IDE_BUILD_TREE = $$QTC_BUILD
PROVIDER = FooCompanyInc
include($$QTC_SOURCE/src/qtcreatorplugin.pri)
include($$QTC_SOURCE/src/plugins/coreplugin/coreplugin.pri)
LIBS += -L$$IDE_PLUGIN_PATH/Nokia
HEADERS = donothingplugin.h
SOURCES = donothingplugin.cpp
OTHER_FILES = DoNothing.pluginspec

View File

@@ -0,0 +1,10 @@
<plugin name="PreferencePane" version="0.0.1">
<vendor>FooCompanyInc Pvt. Ltd</vendor>
<copyright>(C) 2009-2010 FooCompanyInc Pvt. Ltd.</copyright>
<license></license>
<description>{{PLUGIN_DESCRIPTION}}</description>
<url>http://www.FooCompany.com</url>
<dependencyList>
<dependency name="Core"/>
</dependencyList>
</plugin>

View File

@@ -0,0 +1,47 @@
#include "modifiedfilelister.h"
#include "modifiedfilelistwidget.h"
ModifiedFileLister::ModifiedFileLister(QObject *parent): IOptionsPage(parent)
{
}
ModifiedFileLister::~ModifiedFileLister()
{
}
QString ModifiedFileLister::id() const
{
return "ModifiedFiles";
}
QString ModifiedFileLister::trName() const
{
return tr("Modified Files");
}
QString ModifiedFileLister::category() const
{
return "Help";
}
QString ModifiedFileLister::trCategory() const
{
return tr("Help");
}
QWidget *ModifiedFileLister::createPage(QWidget *parent)
{
return new ModifiedFileListWidget(parent);
}
void ModifiedFileLister::apply()
{
// Do nothing
}
void ModifiedFileLister::finish()
{
// Do nothing
}

View File

@@ -0,0 +1,21 @@
#ifndef MODIFIEDFILELISTER_H
#define MODIFIEDFILELISTER_H
#include <coreplugin/dialogs/ioptionspage.h>
class ModifiedFileLister : public Core::IOptionsPage
{
Q_OBJECT
public:
ModifiedFileLister(QObject *parent = 0);
~ModifiedFileLister();
// IOptionsPage implementation
QString id() const;
QString trName() const;
QString category() const;
QString trCategory() const;
QWidget *createPage(QWidget *parent);
void apply();
void finish();
};
#endif // MODIFIEDFILELISTER_H

View File

@@ -0,0 +1,20 @@
#include "modifiedfilelistwidget.h"
#include <coreplugin/filemanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/ifile.h>
ModifiedFileListWidget::ModifiedFileListWidget(QWidget* parent):QListWidget(parent)
{
// Show the list of modified pages
Core::FileManager* fm = Core::ICore::instance()->fileManager();
QList<Core::IFile*> files = fm->modifiedFiles();
for(int i=0; i<files.count();i++)
this->addItem(files.at(i)->fileName());
}
ModifiedFileListWidget::~ModifiedFileListWidget()
{
//Do Nothing
}

View File

@@ -0,0 +1,14 @@
#ifndef MODIFIEDFILELISTWIDGET_H
#define MODIFIEDFILELISTWIDGET_H
#include <QListWidget>
class ModifiedFileListWidget: public QListWidget
{
Q_OBJECT
public:
ModifiedFileListWidget(QWidget* parent=0);
~ModifiedFileListWidget();
};
#endif // MODIFIEDFILELISTWIDGET_H

View File

@@ -0,0 +1,36 @@
#include "preferencepaneplugin.h"
#include "modifiedfilelister.h"
#include <QtPlugin>
#include <QStringList>
PreferencePanePlugin::PreferencePanePlugin()
{
// Do nothing
}
PreferencePanePlugin::~PreferencePanePlugin()
{
// Do notning
}
void PreferencePanePlugin::extensionsInitialized()
{
// Do nothing
}
bool PreferencePanePlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
addAutoReleasedObject(new ModifiedFileLister);
return true;
}
void PreferencePanePlugin::shutdown()
{
// Do nothing
}
Q_EXPORT_PLUGIN(PreferencePanePlugin)

View File

@@ -0,0 +1,18 @@
#ifndef PREFERENCEPANE_PLUGIN_H
#define PREFERENCEPANE_PLUGIN_H
#include <extensionsystem/iplugin.h>
class PreferencePanePlugin : public ExtensionSystem::IPlugin
{
public:
PreferencePanePlugin();
~PreferencePanePlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
};
#endif // PREFERENCEPANE_PLUGIN_H

View File

@@ -0,0 +1,21 @@
QTC_SOURCE = C:/Work/QtCreator
QTC_BUILD = C:/Work/QtCreator/build
TEMPLATE = lib
TARGET = PreferencePane
IDE_SOURCE_TREE = $$QTC_SOURCE
IDE_BUILD_TREE = $$QTC_BUILD
PROVIDER = FooCompanyInc
include($$QTC_SOURCE/src/qtcreatorplugin.pri)
include($$QTC_SOURCE/src/plugins/coreplugin/coreplugin.pri)
LIBS += -L$$IDE_PLUGIN_PATH/Nokia
HEADERS = preferencepaneplugin.h \
modifiedfilelistwidget.h \
modifiedfilelister.h
SOURCES = preferencepaneplugin.cpp \
modifiedfilelistwidget.cpp \
modifiedfilelister.cpp
OTHER_FILES = PreferencePane.pluginspec

View File

@@ -0,0 +1,11 @@
<plugin name="ProgressBar" version="0.0.1">
<vendor>FooCompanyInc</vendor>
<copyright></copyright>
<license></license>
<description>{{PLUGIN_DESCRIPTION}}</description>
<url>http://www.foocompany.com</url>
<dependencyList>
<dependency name="Core"/>
<dependency name="Find"/>
</dependencyList>
</plugin>

View File

@@ -0,0 +1,188 @@
#include "headerfilterprogress.h"
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/iprojectmanager.h>
#include <extensionsystem/pluginmanager.h>
#include <texteditor/basetexteditor.h>
#include <find/searchresultwindow.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include <find/textfindconstants.h>
#include <utils/stylehelper.h>
#include <utils/filesearch.h>
#include <coreplugin/icore.h>
#include <QtGui/QComboBox>
#include <QtGui/QCheckBox>
#include<QFutureWatcher>
#include<QStringListModel>
#include<QLabel>
#include<QFont>
#include<QMessageBox>
#include<QGridLayout>
using namespace Core;
using namespace Utils;
using namespace TextEditor;
struct HeaderFilterProgressData
{
HeaderFilterProgressData() : projectPlugin(0), m_searchResultWindow(0){}
QFutureWatcher<FileSearchResult> watcher;
QLabel* resultLabel;
ProjectExplorer::ProjectExplorerPlugin* projectExplorer()
{
if(projectPlugin)
return projectPlugin;
ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance();
projectPlugin = pm->getObject<ProjectExplorer::ProjectExplorerPlugin>();
return projectPlugin;
}
// Method to search and return the search window
Find::SearchResultWindow* searchResultWindow()
{
if(m_searchResultWindow)
return m_searchResultWindow;
ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance();
m_searchResultWindow = pm->getObject<Find::SearchResultWindow>();
return m_searchResultWindow;
}
private:
ProjectExplorer::ProjectExplorerPlugin* projectPlugin;
Find::SearchResultWindow* m_searchResultWindow;
};
HeaderFilterProgress::HeaderFilterProgress()
{
d = new HeaderFilterProgressData;
d->watcher.setPendingResultsLimit(1);
d->resultLabel = 0 ;
// displayResult(int) is called when every a new
// search result is generated
connect(&d->watcher, SIGNAL(resultReadyAt(int)),this, SLOT(displayResult(int)));
}
HeaderFilterProgress::~HeaderFilterProgress()
{
delete d;
}
QString HeaderFilterProgress::id() const
{
return "HeaderFilter";
}
QString HeaderFilterProgress::name() const
{
return tr("Header Filter");
}
bool HeaderFilterProgress::isEnabled() const
{
QList<ProjectExplorer::Project*> projects = d->projectExplorer()->session()->projects();
if(projects.count())
return true;
return false;
}
QKeySequence HeaderFilterProgress::defaultShortcut() const
{
return QKeySequence();
}
void HeaderFilterProgress::findAll(const QString &text,QTextDocument::FindFlags findFlags)
{
// Fetch a list of all open projects
QList<ProjectExplorer::Project*> projects = d->projectExplorer()->session()->projects();
// Make a list of files in each project
QStringList files;
Q_FOREACH(ProjectExplorer::Project* project, projects)
files += project->files(ProjectExplorer::Project::AllFiles);
// Remove duplicates
files.removeDuplicates();
//------------------------------------------------------------
// Begin searching
QString includeline = "#include <" + text + ">";
Find::SearchResult* result = d->searchResultWindow()->startNewSearch();
d->watcher.setFuture(QFuture<FileSearchResult>());
//When result gets activated it invokes the openEditor function
connect(result, SIGNAL(activated(Find::SearchResultItem)),
this, SLOT(openEditor(Find::SearchResultItem)));
d->searchResultWindow()->popup(true);
// Let the watcher monitor the search results
d->watcher.setFuture(Utils::findInFiles(includeline, files, findFlags));
//Creates the Progres bar
Core::FutureProgress* progress =
Core::ICore::instance()->progressManager()->addTask(d->watcher.future(),
"MySearch",
Find::Constants::TASK_SEARCH,
Core::ProgressManager::KeepOnFinish
);
progress->setWidget(createProgressWidget());
connect(progress, SIGNAL(clicked()), d->searchResultWindow(), SLOT(popup()));
}
QWidget* HeaderFilterProgress::createProgressWidget()
{
d->resultLabel = new QLabel;
d->resultLabel->setAlignment(Qt::AlignCenter);
QFont f = d->resultLabel->font();
f.setBold(true);
f.setPointSizeF(StyleHelper::sidebarFontSize());
d->resultLabel->setFont(f);
d->resultLabel->setPalette(StyleHelper::sidebarFontPalette(d->resultLabel->palette()));
d->resultLabel->setText(tr("%1 found").arg(d->searchResultWindow()->numberOfResults()));
return d->resultLabel;
}
QWidget* HeaderFilterProgress::createConfigWidget()
{
return (new QLabel("This is a header filter"));
}
void HeaderFilterProgress::displayResult(int index)
{
FileSearchResult result = d->watcher.future().resultAt(index);
d->searchResultWindow()->addResult(result.fileName,
result.lineNumber,
result.matchingLine,
result.matchStart,
result.matchLength);
if (d->resultLabel)
d->resultLabel->setText(tr("%1 found").arg(d->searchResultWindow()->numberOfResults()));
}
void HeaderFilterProgress::openEditor(const Find::SearchResultItem &item)
{
TextEditor::BaseTextEditor::openEditorAt(item.fileName, item.lineNumber, item.index);
}

View File

@@ -0,0 +1,45 @@
#ifndef HEADERFILTERPROGRESS_H
#define HEADERFILTERPROGRESS_H
#include <find/ifindfilter.h>
#include <utils/filesearch.h>
#include <QtGui/QComboBox>
namespace Find {
class SearchResultWindow;
struct SearchResultItem;
}
class QKeySequence;
class QWidget;
struct HeaderFilterProgressData;
class HeaderFilterProgress : public Find::IFindFilter
{
Q_OBJECT
public:
HeaderFilterProgress();
~HeaderFilterProgress();
QString id() const;
QString name() const;
bool isEnabled() const;
QKeySequence defaultShortcut() const;
void findAll(const QString &txt,QTextDocument::FindFlags findFlags);
QWidget* createConfigWidget();
QWidget* createProgressWidget();
protected slots:
void displayResult(int index);
void openEditor(const Find::SearchResultItem &item);
private:
HeaderFilterProgressData* d;
};
#endif // HEADERFILTERPROGRESS_H

View File

@@ -0,0 +1,28 @@
QTC_SOURCE = C:/Work/QtCreator
QTC_BUILD = C:/Work/QtCreator/build
DEFINES += FIND_LIBRARY
TEMPLATE = lib
TARGET = ProgressBar
IDE_SOURCE_TREE = $$QTC_SOURCE
IDE_BUILD_TREE = $$QTC_BUILD
PROVIDER = FooCompanyInc
include($$QTC_SOURCE/src/libs/extensionsystem/extensionsystem.pri)
include($$QTC_SOURCE/src/qtcreatorplugin.pri)
include($$QTC_SOURCE/src/plugins/coreplugin/coreplugin.pri)
include($$QTC_SOURCE/src/libs/utils/utils.pri)
include($$QTC_SOURCE/src/plugins/projectexplorer/projectexplorer.pri)
include($$QTC_SOURCE/src/plugins/find/find.pri)
LIBS += -L$$IDE_PLUGIN_PATH/Nokia
HEADERS = progressbarplugin.h \
headerfilterprogress.h
SOURCES = progressbarplugin.cpp \
headerfilteprogress.cpp
OTHER_FILES = ProgressBar.pluginspec

View File

@@ -0,0 +1,36 @@
#include "progressbarplugin.h"
#include "headerfilterprogress.h"
#include <QtPlugin>
#include <QStringList>
ProgressBarPlugin::ProgressBarPlugin()
{
// Do nothing
}
ProgressBarPlugin::~ProgressBarPlugin()
{
// Do notning
}
void ProgressBarPlugin::extensionsInitialized()
{
// Do nothing
}
bool ProgressBarPlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
addAutoReleasedObject( new HeaderFilterProgress);
return true;
}
void ProgressBarPlugin::shutdown()
{
// Do nothing
}
Q_EXPORT_PLUGIN(ProgressBarPlugin)

View File

@@ -0,0 +1,20 @@
#ifndef PROGRESSBAR_PLUGIN_H
#define PROGRESSBAR_PLUGIN_H
#include <extensionsystem/iplugin.h>
class ProgressBarPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
public:
ProgressBarPlugin();
~ProgressBarPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString* errorString);
void shutdown();
};
#endif // PROGRESSBAR_PLUGIN_H

View File

@@ -0,0 +1,10 @@
<plugin name="CustomProject" version="0.0.1">
<vendor>FooCompanyInc</vendor>
<copyright></copyright>
<license></license>
<description>{{PLUGIN_DESCRIPTION}}</description>
<url>http://www.FooCompanyInc.com</url>
<dependencyList>
<dependency name="Core"/>
</dependencyList>
</plugin>

View File

@@ -0,0 +1,37 @@
#include "customprojectplugin.h"
#include "customprojectwizard.h"
#include <QtPlugin>
#include <QStringList>
CustomProjectPlugin::CustomProjectPlugin()
{
// Do nothing
}
CustomProjectPlugin::~CustomProjectPlugin()
{
// Do notning
}
void CustomProjectPlugin::extensionsInitialized()
{
// Do nothing
}
bool CustomProjectPlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
addAutoReleasedObject(new CustomProjectWizard);
return true;
}
void CustomProjectPlugin::shutdown()
{
// Do nothing
}
Q_EXPORT_PLUGIN(CustomProjectPlugin)

View File

@@ -0,0 +1,18 @@
#ifndef CUSTOMPROJECT_PLUGIN_H
#define CUSTOMPROJECT_PLUGIN_H
#include <extensionsystem/iplugin.h>
class CustomProjectPlugin : public ExtensionSystem::IPlugin
{
public:
CustomProjectPlugin();
~CustomProjectPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
};
#endif // CUSTOMPROJECT_PLUGIN_H

View File

@@ -0,0 +1,18 @@
QTC_SOURCE = C:/Work/QtCreator
QTC_BUILD = C:/Work/QtCreator/build
TEMPLATE = lib
TARGET = CustomProject
IDE_SOURCE_TREE = $$QTC_SOURCE
IDE_BUILD_TREE = $$QTC_BUILD
PROVIDER = FooCompanyInc
include($$QTC_SOURCE/src/qtcreatorplugin.pri)
include($$QTC_SOURCE/src/plugins/coreplugin/coreplugin.pri)
LIBS += -L$$IDE_PLUGIN_PATH/Nokia
HEADERS = customprojectplugin.h \
customprojectwizard.h
SOURCES = customprojectplugin.cpp \
customprojectwizard.cpp
OTHER_FILES = CustomProject.pluginspec

View File

@@ -0,0 +1,51 @@
#include "customprojectwizard.h"
#include <QMessageBox>
#include <QApplication>
#include <QIcon>
CustomProjectWizard::CustomProjectWizard()
{
}
CustomProjectWizard::~CustomProjectWizard()
{
}
Core::IWizard::Kind CustomProjectWizard::kind() const
{
return IWizard::ProjectWizard;
}
QIcon CustomProjectWizard::icon() const
{
return qApp->windowIcon();
}
QString CustomProjectWizard::description() const
{
return "A custom project";
}
QString CustomProjectWizard::name() const
{
return "CustomProject";
}
QString CustomProjectWizard::category() const
{
return "FooCompanyInc";
}
QString CustomProjectWizard::trCategory() const
{
return tr("FooCompanyInc");
}
QStringList CustomProjectWizard::runWizard(const QString &path, QWidget *parent)
{
Q_UNUSED(path);
Q_UNUSED(parent);
QMessageBox::information(parent, "Custom Wizard Dialog", "Hi there!");
return QStringList();
}

View File

@@ -0,0 +1,21 @@
#ifndef CUSTOMPROJECTWIZARD_H
#define CUSTOMPROJECTWIZARD_H
#include <coreplugin/dialogs/iwizard.h>
class CustomProjectWizard : public Core::IWizard
{
public:
CustomProjectWizard();
~CustomProjectWizard();
Core::IWizard::Kind kind() const;
QIcon icon() const;
QString description() const;
QString name() const;
QString category() const;
QString trCategory() const;
QStringList runWizard(const QString &path, QWidget *parent);
};
#endif // CUSTOMPROJECTWIZARD_H

View File

@@ -0,0 +1,22 @@
#ifndef {{UPPER_CLASS_NAME}}_H
#define {{UPPER_CLASS_NAME}}_H
#include <{{BASE_CLASS_NAME}}>
struct {{CLASS_NAME}}Data;
class {{CLASS_NAME}} : public {{BASE_CLASS_NAME}}
{
Q_OBJECT
public:
{{CLASS_NAME}}(QObject* parent=0);
~{{CLASS_NAME}}();
int rowCount(const QModelIndex& parent) const;
QVariant data(const QModelIndex& index, int role) const;
private:
{{CLASS_NAME}}Data* d;
};
#endif // {{UPPER_CLASS_NAME}}_H

View File

@@ -0,0 +1,23 @@
#include <{{CLASS_HEADER}}>
struct {{CLASS_NAME}}Data
{
};
{{CLASS_NAME}}::{{CLASS_NAME}}(QObject* parent)
:{{BASE_CLASS_NAME}}(parent)
{
d = {{CLASS_NAME}}Data;
}
{{CLASS_NAME}}::~{{CLASS_NAME}}()
{
}
int {{CLASS_NAME}}::rowCount(const QModelIndex& parent) const
{
}
QVariant {{CLASS_NAME}}::data(const QModelIndex& index, int role) const
{
}

View File

@@ -0,0 +1,10 @@
<plugin name="ItemModelWizard" version="0.0.1">
<vendor>FooCompanyInc</vendor>
<copyright></copyright>
<license></license>
<description>{{PLUGIN_DESCRIPTION}}</description>
<url>http://www.FooCompanyInc.com</url>
<dependencyList>
<dependency name="Core"/>
</dependencyList>
</plugin>

View File

@@ -0,0 +1,43 @@
#include "itemmodelwizardplugin.h"
#include "modelclasswizard.h"
#include <QApplication>
#include <QtPlugin>
#include <QStringList>
ItemModelWizardPlugin::ItemModelWizardPlugin()
{
// Do nothing
}
ItemModelWizardPlugin::~ItemModelWizardPlugin()
{
// Do notning
}
void ItemModelWizardPlugin::extensionsInitialized()
{
// Do nothing
}
bool ItemModelWizardPlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
Core::BaseFileWizardParameters params;
params.setKind(Core::IWizard::ClassWizard);
params.setIcon(qApp->windowIcon());
params.setDescription("Generates an item-model class");
params.setName("Item Model");
params.setCategory("FooCompany");
params.setTrCategory(tr("FooCompany"));
addAutoReleasedObject(new ModelClassWizard(params, this));
return true;
}
void ItemModelWizardPlugin::shutdown()
{
// Do nothing
}
Q_EXPORT_PLUGIN(ItemModelWizardPlugin)

View File

@@ -0,0 +1,18 @@
#ifndef ITEMMODELWIZARD_PLUGIN_H
#define ITEMMODELWIZARD_PLUGIN_H
#include <extensionsystem/iplugin.h>
class ItemModelWizardPlugin : public ExtensionSystem::IPlugin
{
public:
ItemModelWizardPlugin();
~ItemModelWizardPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
};
#endif // ITEMMODELWIZARD_PLUGIN_H

View File

@@ -0,0 +1,25 @@
QTC_SOURCE = C:/Work/QtCreator
QTC_BUILD = C:/Work/QtCreator/build
TEMPLATE = lib
TARGET = ItemModelWizard
IDE_SOURCE_TREE = $$QTC_SOURCE
IDE_BUILD_TREE = $$QTC_BUILD
PROVIDER = FooCompanyInc
include($$QTC_SOURCE/src/qtcreatorplugin.pri)
include($$QTC_SOURCE/src/plugins/coreplugin/coreplugin.pri)
include($$QTC_SOURCE/src/plugins/texteditor/texteditor.pri)
include($$QTC_SOURCE/src/plugins/cppeditor/cppeditor.pri)
LIBS += -L$$IDE_PLUGIN_PATH/Nokia
HEADERS = itemmodelwizardplugin.h \
modelnamepage.h \
modelclasswizard.h
SOURCES = itemmodelwizardplugin.cpp \
modelnamepage.cpp \
modelclasswizard.cpp
OTHER_FILES = ItemModelWizard.pluginspec
FORMS += modelnamepage.ui
RESOURCES += template.qrc

View File

@@ -0,0 +1,101 @@
#include "modelclasswizard.h"
#include "modelnamepage.h"
#include <QFile>
#include <QFileInfo>
#include <cppeditor/cppeditor.h>
#include <cppeditor/cppeditorconstants.h>
#include <coreplugin/basefilewizard.h>
ModelClassWizard::ModelClassWizard(const Core::BaseFileWizardParameters &parameters,QObject *parent)
: Core::BaseFileWizard(parameters, parent)
{
}
ModelClassWizard::~ModelClassWizard()
{
}
QWizard * ModelClassWizard::createWizardDialog(
QWidget *parent,
const QString &defaultPath,
const WizardPageList &extensionPages) const
{
// Create a wizard
QWizard* wizard = new QWizard(parent);
wizard->setWindowTitle("Model Class Wizard");
// Make our page as first page
ModelNamePage* page = new ModelNamePage(wizard);
int pageId = wizard->addPage(page);
wizard->setProperty("_PageId_", pageId);
page->setPath(defaultPath);
// Now add the remaining pages
foreach (QWizardPage *p, extensionPages)
wizard->addPage(p);
return wizard;
}
QString ModelClassWizard::readFile(const QString& fileName, const QMap<QString,QString>&
replacementMap) const
{
QFile file(fileName);
file.open(QFile::ReadOnly);
QString retStr = file.readAll();
QMap<QString,QString>::const_iterator it = replacementMap.begin();
QMap<QString,QString>::const_iterator end = replacementMap.end();
while(it != end)
{
retStr.replace(it.key(), it.value());
++it;
}
return retStr;
}
Core::GeneratedFiles ModelClassWizard::generateFiles(
const QWizard *w,QString *errorMessage) const
{
Q_UNUSED(errorMessage);
Core::GeneratedFiles ret;
int pageId = w->property("_PageId_").toInt();
ModelNamePage* page = qobject_cast<ModelNamePage*>(w->page(pageId));
if(!page)
return ret;
ModelClassParameters params = page->parameters();
QMap<QString,QString> replacementMap;
replacementMap["{{UPPER_CLASS_NAME}}"] = params.className.toUpper();
replacementMap["{{BASE_CLASS_NAME}}"] = params.baseClass;
replacementMap["{{CLASS_NAME}}"] = params.className;
replacementMap["{{CLASS_HEADER}}"] = QFileInfo(params.headerFile).fileName();
Core::GeneratedFile headerFile(params.path + "/" + params.headerFile);
headerFile.setEditorKind(CppEditor::Constants::CPPEDITOR_KIND);
Core::GeneratedFile sourceFile(params.path + "/" + params.sourceFile);
sourceFile.setEditorKind(CppEditor::Constants::CPPEDITOR_KIND);
if(params.baseClass == "QAbstractItemModel")
{
headerFile.setContents(readFile(":/CustomProject/ItemModelHeader", replacementMap) );
sourceFile.setContents(readFile(":/CustomProject/ItemModelSource", replacementMap) );
}
else if(params.baseClass == "QAbstractTableModel")
{
headerFile.setContents(readFile(":/CustomProject/TableModelHeader", replacementMap) );
sourceFile.setContents(readFile(":/CustomProject/TableModelSource", replacementMap) );
}
else if(params.baseClass == "QAbstractListModel")
{
headerFile.setContents(readFile(":/CustomProject/ListModelHeader", replacementMap) );
sourceFile.setContents(readFile(":/CustomProject/ListModelSource", replacementMap) );
}
ret << headerFile << sourceFile;
return ret;
}

View File

@@ -0,0 +1,26 @@
#ifndef MODELCLASSWIZARD_H
#define MODELCLASSWIZARD_H
#include <coreplugin/basefilewizard.h>
class ModelClassWizard : public Core::BaseFileWizard
{
Q_OBJECT
public:
ModelClassWizard(const Core::BaseFileWizardParameters &parameters, QObject *parent = 0);
~ModelClassWizard();
QWizard *createWizardDialog(QWidget *parent,
const QString &defaultPath,
const WizardPageList &extensionPages) const;
Core::GeneratedFiles generateFiles(const QWizard *w, QString *errorMessage) const;
private:
QString readFile(const QString& fileName,
const QMap<QString,QString>& replacementMap) const;
};
#endif // MODELCLASSWIZARD_H

View File

@@ -0,0 +1,38 @@
#include "modelnamepage.h"
#include "ui_modelnamepage.h"
ModelNamePage::ModelNamePage(QWidget *parent) :
QWizardPage(parent)
{
setTitle("Enter model class information");
setSubTitle("The header and source file names will be derived from the class name");
ui.setupUi(this);
}
ModelNamePage::~ModelNamePage()
{
}
void ModelNamePage::setPath(const QString& path)
{
this->path = path;
}
void ModelNamePage::on_txtModelClass_textEdited(const QString& txt)
{
ui.txtHeaderFile->setText(txt + ".h");
ui.txtImplFile->setText(txt + ".cpp");
}
ModelClassParameters ModelNamePage::parameters() const
{
ModelClassParameters params;
params.className = ui.txtModelClass->text();
params.headerFile = ui.txtHeaderFile->text();
params.sourceFile = ui.txtImplFile->text();
params.baseClass = ui.cmbBaseClass->currentText();
params.path = path;
return params;
}

View File

@@ -0,0 +1,34 @@
#ifndef MODELNAMEPAGE_H
#define MODELNAMEPAGE_H
#include <QWizardPage>
#include "ui_ModelNamePage.h"
struct ModelClassParameters
{
QString className;
QString headerFile;
QString sourceFile;
QString baseClass;
QString path;
};
class ModelNamePage : public QWizardPage
{
Q_OBJECT
public:
ModelNamePage(QWidget *parent = 0);
~ModelNamePage();
void setPath(const QString& path);
ModelClassParameters parameters() const;
private slots:
void on_txtModelClass_textEdited(const QString& txt);
private:
Ui::ModelNamePage ui;
QString path;
};
#endif // MODELNAMEPAGE_H

View File

@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ModelNamePage</class>
<widget class="QWidget" name="ModelNamePage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>346</width>
<height>257</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Model Class Name:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="txtModelClass"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Base Class Name:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="cmbBaseClass">
<item>
<property name="text">
<string>QAbstractItemModel</string>
</property>
</item>
<item>
<property name="text">
<string>QAbstractListModel</string>
</property>
</item>
<item>
<property name="text">
<string>QAbstractTableModel</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Header:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="txtHeaderFile"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Implementation:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="txtImplFile"/>
</item>
<item row="4" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>61</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/CustomProject">
<file alias="ItemModelSource">ItemModelSource.txt</file>
<file alias="ItemModelHeader">ItemModelHeader.txt</file>
</qresource>
</RCC>

View File

@@ -0,0 +1,7 @@
/*!
\page adv-find-filter.html
\title 15.Adding "advanced" find filter
This page needs to be written still!
*/

102
doc/pluginhowto/classic.css Normal file
View File

@@ -0,0 +1,102 @@
h3.fn,span.fn
{
margin-left: 1cm;
text-indent: -1cm;
}
a:link
{
color: #004faf;
text-decoration: none
}
a:visited
{
color: #672967;
text-decoration: none
}
td.postheader
{
font-family: sans-serif
}
tr.address
{
font-family: sans-serif
}
body
{
background: #ffffff;
color: black
}
table tr.odd {
background: #f0f0f0;
color: black;
}
table tr.even {
background: #e4e4e4;
color: black;
}
table.annotated th {
padding: 3px;
text-align: left
}
table.annotated td {
padding: 3px;
}
table tr pre
{
padding-top: none;
padding-bottom: none;
padding-left: none;
padding-right: none;
border: none;
background: none
}
tr.qt-style
{
background: #a2c511;
color: black
}
body pre
{
padding: 0.2em;
border: #e7e7e7 1px solid;
background: #f1f1f1;
color: black
}
span.preprocessor, span.preprocessor a
{
color: darkblue;
}
span.comment
{
color: darkred;
font-style: italic
}
span.string,span.char
{
color: darkgreen;
}
.subtitle
{
font-size: 0.8em
}
.small-subtitle
{
font-size: 0.65em
}

View File

@@ -0,0 +1,998 @@
/*!
\page editor-type.html
\title 10. Adding editor type
At the very basic level Qt Creator is a text editor. On top of supporting editing of text files, Qt Creator also allows users
to edit UI (Qt Designer) files, QRC (Resource) files, PRO/PRI (Project) files and EXE/DLL/SO (Binary) files.
\inlineimage qtc-editor-10.png
In this chapter we will understand how to provide editors for custom file formats, specifically the HTML file format.
When we are done, we will be able to load HTML files from the local file system and view/edit them.
\inlineimage qtc-fileformat-10.png
\section1 10.1 Core Classes and Interfaces
To support a new editor type, we need to
\list
\o Implement a plugin \bold {(Core::IPlugin} implementation) class that exposes an "editor factory". Chapter 2 in this
document provides a detailed description on creating plugins by implementing the \bold {Core::IPlugin interface}.
\o Implement the editor factory, \bold {Core::IEditorFactory}, interface. This interface implementation provides
methods to help create instances of "editor" object for a specified mime-type.
\o Implement the editor, \bold {Core::IEditor}, interface. This interface implementation provides a widget that helps
edit a file type (for example: HTML, ODF etc). Editors must provide access to the "file" that it is currently being
shown or edited.
\o Implement the file, \bold{Core::IFile}, interface to help customize the loading and saving of data into disk files.
\endlist
In the following subsections, we will take a look at each of the above mentioned core interfaces.
\section2 10.1.1 The Core::IFile interface
This interface abstracts file operations from the user-interface point of view. It provides virtual methods to load and
save files, given a file name. It also helps in understanding the mime-type of file and value of certain flags like <20>modified<65>
and "read-only". The \bold{Core::IFile} interface is declared as follows in src/plugins/coreplugin/ifile.h
\code
namespace Core
{
class IFile : public QObject
{
Q_OBJECT
public:
enum ReloadBehavior { AskForReload, ReloadAll, ReloadPermissions, ReloadNone };
IFile(QObject *parent = 0) : QObject(parent) {}
virtual ~IFile() {}
virtual bool save(const QString &fileName = QString()) = 0;
virtual QString fileName() const = 0;
virtual QString defaultPath() const = 0;
virtual QString suggestedFileName() const = 0;
virtual QString mimeType() const = 0;
virtual bool isModified() const = 0;
virtual bool isReadOnly() const = 0;
virtual bool isSaveAsAllowed() const = 0;
virtual void modified(ReloadBehavior *behavior) = 0;
virtual void checkPermissions() {}
signals:
void changed();
};
} // namespace Core
\endcode
You may be wondering: "Why go for another interface called \bold {IFile} when we already have a class called \bold {QFile} that
provides the exact same functionality?" Good point. The responses to this question are listed below
\list
\o \bold {IFile} has to take care of loading contents of a filename into an editor \bold {(Core::IEditor} interface discussed
next). \bold {QFile} on the other hand simply loads contents into a \bold {QByteArray}.
\o \bold {IFile} has to emit the \bold {modified()} signal when the user edits the contents of the file in the editor, but the
actual disk-file contents have not been modified. \bold {QFile} emits the \bold {bytesWritten()} signal only when the
disk-file contents have been modified.
\o \bold {IFile} has to handle how a modified file, on the disk, is reloaded. \bold {QFile} on the other-hand doesn<73>t need to
handle this.
\endlist
We will learn more about implementing the \bold {Core::IFile} interface in a future section.
\section2 10.1.2 The Core::IEditor interface
Implementations of the \bold {Core::IEditor} interface provide editors for different types of files. It is declared as follows
in src/plugins/coreplugin/editormanager/ieditor.h.
\code
namespace Core
{
class IContext : public QObject
{
Q_OBJECT
public:
IContext(QObject *parent = 0) : QObject(parent) {}
virtual ~IContext() {}
virtual QList<int> context() const = 0;
virtual QWidget *widget() = 0;
virtual QString contextHelpId() const { return QString(); }
};
class IEditor : public IContext
{
Q_OBJECT
public:
IEditor(QObject *parent = 0) : IContext(parent) {}
virtual ~IEditor() {}
virtual bool createNew(const QString &contents = QString()) = 0;
virtual bool open(const QString &fileName = QString()) = 0;
virtual IFile *file() = 0;
virtual const char *kind() const = 0;
virtual QString displayName() const = 0;
virtual void setDisplayName(const QString &title) = 0;
virtual bool duplicateSupported() const = 0;
virtual IEditor *duplicate(QWidget *parent) = 0;
virtual QByteArray saveState() const = 0;
virtual bool restoreState(const QByteArray &state) = 0;
virtual int currentLine() const { return 0; }
virtual int currentColumn() const { return 0; }
virtual bool isTemporary() const = 0;
virtual QToolBar *toolBar() = 0;
signals:
void changed();
};
} // namespace Core
\endcode
The \bold {Core::IEditor} interface primary provides access to
\list
\o An \underline{editor widget}\bold{ (Core::IEditor::widget()} method) that Qt Creator can use to display contents of the
file being edited.
\o The file \bold {(Core::IEditor::file() } method), which is a \bold {Core::IFile} implementation, that Qt Creator
can use to trigger the loading and saving of data from disk-files.
\o An optional custom toolbar that Qt Creator can show whenever the editor becomes active.
\o The current position of the edit-cursor within the file \bold {(Core::IEditor::currentLine()} and
\bold {Core::IEditor::currentColumn())}
\o The name that needs to be displayed in the \underline{open-files combo box}.
\endlist
Take a look at the following screenshot to get a better understanding.
\inlineimage qtc-ieditor-10.png
We will understand more about implementing the \bold {Core::IEditor} interface in a future section.
\section2 10.1.3 The Core::IEditorFactory interface
Implementations of \bold {Core::IEditorFactory} interface provide methods to create instances of Core::IEditor
for a supported mime-type. It is declared as follows in src/plugins/coreplugin/editormanager/ieditorfactory.h.
\code
namespace Core
{
class IFileFactory : public QObject
{
Q_OBJECT
public:
IFileFactory(QObject *parent = 0) : QObject(parent) {}
virtual ~IFileFactory() {}
virtual QStringList mimeTypes() const = 0;
virtual QString kind() const = 0;
virtual Core::IFile *open(const QString &fileName) = 0;
};
class IEditorFactory : public Core::IFileFactory
{
Q_OBJECT
public:
IEditorFactory(QObject *parent = 0) : IFileFactory(parent) {}
virtual ~IEditorFactory() {}
virtual IEditor *createEditor(QWidget *parent) = 0;
};
} // namespace Core
\endcode
The \bold {IEditorFactory::mimeType()} method should be implemented to return the mime-type supported by the
editor for which the factory is implemented. The \bold {IEditorFactory::createEditor()} method should be
implemented to actually create a concrete editor and return the same.
\section2 10.1.4 The Core::MimeDatabase class
The \bold {Core::MimeDatabase} class keeps track of all the mime-types supported by Qt Creator. It also helps figure out
the mime-type of a given file. Take the following code for example:
\code
#include <coreplugin/mimedatabase.h>
Core::ICore* core = Core::ICore::instance();
Core::MimeDatabase* mdb = core->mimeDatabase();
Core::MimeType type1 = mdb->findByFile( QFileInfo("C:/Temp/sample.html") );
qDebug("File Type for sample.html = %s", qPrintable(type1.type()));
Core::MimeType type2 = mdb->findByFile( QFileInfo("C:/Temp/TextEdit/Main.cpp") );
qDebug("File Type for Main.cpp = %s", qPrintable(type2.type()));
Core::MimeType type3 = mdb->findByFile( QFileInfo("C:/Temp/TextEdit/TextEdit.pro") );
qDebug("File Type for TextEdit.pro = %s", qPrintable(type3.type()));
\endcode
When the above code is compiled and executed, we get the following as output.
\code
File Type for sample.html = text/plain
File Type for Main.cpp = text/x-c++src
File Type for TextEdit.pro = text/plain
\endcode
The \bold { Core::MimeDatabase } uses filename suffix, glob patterns and "magic" matchers to figure out the mime-type of
a given filename. At this point however, lets not dig into how the mime-database manages to figure out the mime-type
from a filename; it is enough if we know that mime-type discovery is possible.
The \bold Core::IEditorFactory interface, as described in the previous section, provides an editor \bold{(Core::IEditor}
implementation) for a specific mime-type. The following points help us understand how Qt Creator manages to pick the
appropriate \bold {Core::IEditorFactory} for a given filename.
\list 1
\o User selects File -> Open and chooses a file to open
\o Qt Creator uses \bold {Core::MimeDatabase} to figure out the mime-type of the selected file
\o Qt Creator runs through all \bold {Core::IEditorFactory} implementations and picks the editor-factory that
supports the mime-type evaluated in step 2
\o Qt Creator asks the selected editor factory to create an editor (Core::IEditor implementation)
\o The widget returned by \bold {Core::IEditor::widget()} is then shown in the workspace area of the mainwindow
\o The \bold {Core::IEditor::open()} method is then called to open the file selected in step 1.
\endlist
\section2 10.1.5 Adding a new mime-type
If we wanted to support a new editor type, then we need to register the mime-type supported by the new editor with
the \bold {Core::MimeDatabase}. Several mechanisms can be used to register a new mime-type. In this chapter we will
learn the simplest way to register a new mime-type from an XML file.
Suppose that we wanted to register the \bold {text/html} mime-type and associate it with \bold {*.html} filenames. We create an XML
file as and save it as \bold {text-html-mimetype.xml}.
\code
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
<mime-type type="text/html">
<sub-class-of type="text/plain"/>
<comment>HTML File</comment>
<glob pattern="*.html"/>
</mime-type>
</mime-info>
\endcode
We then register the mime-type described in the XML file (above) using the
\bold {Core::MimeDatabase::addMimeTypes()} method. Take a look at the code snippet below
\code
Core::ICore* core = Core::ICore::instance();
Core::MimeDatabase* mdb = core->mimeDatabase();
QString errMsg;
bool success = mdb->addMimeTypes("text-html-mimetype.xml", errMsg);
\endcode
Once registered, Qt Creator will begin to map all *.html filenames to text/plain mime-type.
\section1 10.2 Providing a HTML Editor in Qt Creator
Let's implement a plugin for Qt Creator that provides support for viewing and editing HTML files. The following
screenshots show the expected results.
The user select a HTML file to open using the standard File -> Open menuitem.
\inlineimage qtc-menuitem-10.png
Upon selecting a HTML file, Qt Creator will show a custom editor as shown below.
\inlineimage qtc-customeditor-10.png
Notice that the editor has two tabs called "Preview" and "Source" at the bottom edge.
\inlineimage qtc-editortabs-10.png
Clicking on the "Source" tab shows the HTML code in a \bold { QPlainTextEdit} widget.
\inlineimage qtc-plaintextedit-10.png
Users can edit the HTML in this tab, and when he moves back to the "preview" tab the changes are reflected. Users can
continue to make use of File -> Save menu item to save changes to the HTML file.
For achieving the above we implement the following classes
\table
\header
\o Class
\o Interface\\Baseclass
\o Description
\row
\o \c{HtmlEditorWidget}
\o \bold {QTabWidget}
\o Provides a tab widget with two tabs, one for showing the
HTML preview and other for showing the HTML code.
\row
\o \c{HtmlFile}
\o \bold {Core::IFile}
\o Implements the \bold {IFile} interface for the file shown in
\bold {HtmlEditorWidget}.
\row
\o \c {HtmlEditor}
\o \bold {Core::IEditor}
\o Implements the \bold{IEditor} interface for managing the
\bold{HtmlEditorWidget} and hooking up an \bold{IFile} with it.
\row
\o \c {HtmlEditorFactory}
\o \bold {Core::IEditorFactory}
\o Implements the \bold{IEditorFactory} interface for creating
instances of \bold{IEditor} for the "text/html" mime-type.
\row
\o \c {HtmlEditorPlugin}
\o \bold {Core::IPlugin }
\o Implements the \bold{IPlugin} interface for hooking all of the
above into Qt Creator.
\endtable
For every html file there is an instance each of \bold{HtmlEditorWidget},\bold{HtmlFile} and \bold{HtmlEditor} handling the
loading, editing and saving functionality. In our implementation we provide mechanisms to help establish association
between instances of the above classes that handle the same file.
\section2 10.2.1 Implementing the HTML Editor Widget
By default, Qt Creator uses a plain-text editor widget to display the contents of the HTML file being edited. We would
like to offer a tabbed widget as editor. One of the tabs shows the HTML preview, the other shows the HTML code. The
class \bold {HtmlEditorWidget} is our editor; and it is declared as follows.
\code
struct HtmlEditorWidgetData;
class HtmlEditorWidget : public QTabWidget
{
Q_OBJECT
public:
HtmlEditorWidget(QWidget* parent = 0);
~HtmlEditorWidget();
void setContent(const QByteArray& ba, const QString& path=QString());
QByteArray content() const;
QString title() const;
protected slots:
void slotCurrentTabChanged(int tab);
void slotContentModified();
signals:
void contentModified();
void titleChanged(const QString&);
private:
HtmlEditorWidgetData* d;
};
\endcode
The constructor basically creates two different views from \bold{QWebView} and \bold {QPlainTextEdit} and adds them as tabs
at the bottom position of the tab widget. We will learn about the signal-slot connections later.
\code
HtmlEditorWidget::HtmlEditorWidget(QWidget* parent):QTabWidget(parent)
{
d = new HtmlEditorWidgetData;
d->webView = new QWebView;
d->textEdit = new QPlainTextEdit;
addTab(d->webView, "Preview");
addTab(d->textEdit, "Source");
setTabPosition(QTabWidget::South);
setTabShape(QTabWidget::Triangular);
d->textEdit->setFont( QFont("Courier", 12) );
connect(this, SIGNAL(currentChanged(int)),this, SLOT(slotCurrentTabChanged(int)));
connect(d->textEdit, SIGNAL(textChanged()),this, SLOT(slotContentModified()));
connect(d->webView, SIGNAL(titleChanged(QString)),this, SIGNAL(titleChanged(QString)));
d->modified = false;
}
\endcode
The destructor does nothing other than deleting the private \bold{"d"} object.
\code
HtmlEditorWidget::~HtmlEditorWidget()
{
delete d;
}
\endcode
The setContent method simply sets the contents of html file to \bold{webView} and \bold {textEdit}.
\code
void HtmlEditorWidget::setContent(const QByteArray& ba, const QString& path)
{
if(path.isEmpty())
d->webView->setHtml(ba);
else
d->webView->setHtml(ba, "file:///" + path);
d->textEdit->setPlainText(ba);
d->modified = false;
d->path = path;
}
\endcode
The \bold {content} method returns the contents of the \bold {textEdit}.
\code
QByteArray HtmlEditorWidget::content() const
{
QString htmlText = d->textEdit->toPlainText();
return htmlText.toAscii();
}
\endcode
The \bold {title()} method returns the title from the webView. The string returned from this method will be used in the
open-file combo box.
\inlineimage qtc-title-10.png
\code
QString HtmlEditorWidget::title() const
{
return d->webView->title();
}
\endcode
The following connection made in the constructor of \bold {HtmlEditorWidget} makes sure that when the user moves from
"source" to "preview" tab, the HTML content viewed in the preview tab is updated.
\code
connect(this, SIGNAL(currentChanged(int)),this, SLOT(slotCurrentTabChanged(int)));
void HtmlEditorWidget::slotCurrentTabChanged(int tab)
{
if(tab == 0 && d->modified)
setContent( content(), d->path );
}
\endcode
Following connection makes sure that \bold {setContentModified()} slot is called whenever user edits the html source.
The slot \bold {setContentModified()} simply sets modified to true and emits the signal "contentModified" We will
know the usability of this signal later in the section while understanding \bold {HtmlFile} class.
\code
connect(d->textEdit, SIGNAL(textChanged()), this, SLOT(slotContentModified()));
void HtmlEditorWidget::slotContentModified()
{
d->modified = true;
emit contentModified();
}
\endcode
Following connection simply emits \bold {titleChanged()} signal on title change of \bold {webView}. We will know more about
this signal later.
\code
connect(d->webView, SIGNAL(titleChanged(QString)),this, SIGNAL(titleChanged(QString)));
\endcode
\section2 10.2.2 Implementing the Core::IFile interface
We implement the \bold {Core::IFile} interface in the \bold {HtmlFile} class. Apart from implementing the pure virtual
functions from \bold {IFile} (introduced in section 5.1.1); the \bold {HtmlFile} class has methods to get/set the modified flag
which indicates the modification status of the file contents.
\code
struct HtmlFileData;
class HtmlFile : public Core::IFile
{
Q_OBJECT
public:
HtmlFile(HtmlEditor* editor, HtmlEditorWidget* editorWidget);
~HtmlFile();
void setModified(bool val=true);
// Declare all the virtual functions from IFile here..
protected slots:
void modified() { setModified(true); }
private:
HtmlFileData* d;
};
struct HtmlFileData
{
HtmlFileData(): mimeType(HtmlEditorConstants::C_HTMLEDITOR_MIMETYPE),editorWidget(0), editor(0), modified(false) { }
const QString mimeType;
HtmlEditorWidget* editorWidget;
HtmlEditor* editor;
QString fileName;
bool modified;
};
\endcode
In the constructor implementation is simple. It establishes the association between an instance of \bold {HtmlFile} with the
corresponding \bold {HtmlEditor} and the \bold {HtmlEditorWidget} instances.
\code
HtmlFile::HtmlFile(HtmlEditor* editor, HtmlEditorWidget* editorWidget): Core::IFile(editor)
{
d = new HtmlFileData;
d->editor = editor;
d->editorWidget = editorWidget;
}
\endcode
The destructor does nothing other than deleting the private \bold {"d"} object.
\code
HtmlFile::~HtmlFile()
{
delete d;
}
\endcode
The \bold {setModified()} function stores the modification flag and emits the \bold {changed()} signal.
\code
void HtmlFile::setModified(bool val)
{
if(d->modified == val)
return;
d->modified = val;
emit changed();
}
bool HtmlFile::isModified() const
{
return d->modified;
}
\endcode
Returns the mime-type handled by this class.
\code
QString HtmlFile::mimeType() const
{
return d->mimeType;
}
\endcode
The save method is called when file->save action (Ctrl+s) is triggered. This saves the contents of \bold {HtmlEditorWidget}
(the contents shown by plain text editor) in the file as shown below. The modified flag is set to false after the contents
are saved into the file.
\code
bool HtmlFile::save(const QString &fileName)
{
QFile file(fileName);
if(file.open(QFile::WriteOnly))
{
d->fileName = fileName;
QByteArray content = d->editorWidget->content();
file.write(content);
setModified(false);
return true;
}
return false;
}
\endcode
The \bold {open} method is called when file->open action is triggered. This opens the file and calls the setContent()
method of \bold {HtmlEditorWidget}. The display name is set to the title of the html file.
\code
bool HtmlFile::open(const QString &fileName)
{
QFile file(fileName);
if(file.open(QFile::ReadOnly))
{
d->fileName = fileName;
QString path = QFileInfo(fileName).absolutePath();
d->editorWidget->setContent(file.readAll(), path);
d->editor->setDisplayName(d->editorWidget->title());
return true;
}
return false;
}
\endcode
The following methods implement the "filename" property.
\code
void HtmlFile::setFilename(const QString& filename)
{
d->fileName = filename;
}
QString HtmlFile::fileName() const
{
return d->fileName;
}
\endcode
We implement the \bold {defaultPath()},\bold { suggestedFileName()},\bold {fileFilter()} and fileExtension()
methods to do nothing at the moment.
\code
QString HtmlFile::defaultPath() const
{
return QString();
}
QString HtmlFile::suggestedFileName() const
{
return QString();
}
QString HtmlFile::fileFilter() const
{
return QString();
}
QString HtmlFile::fileExtension() const
{
return QString();
}
\endcode
Since we want to edit the file, we return false in \bold {isReadOnly()} method and true from \bold {isSaveAsAllowed()}
method.
\code
bool HtmlFile::isReadOnly() const
{
return false;
}
bool HtmlFile::isSaveAsAllowed() const
{
return true;
}
\endcode
The \bold {modified()} function has to be implemented to customize the way in which the Html editor should handle
reloading of a modified file. This function is called if a html-file was modified outside of Qt Creator, while it is being
edited. For now we do nothing.
\code
void HtmlFile::modified(ReloadBehavior* behavior)
{
Q_UNUSED(behavior);
}
\endcode
\section2 10.2.3 Implementing the Core::IEditor interface
The \bold {HtmlEditor} class implements \bold {IEditor} interface to provide an editor widget for html (*.html) files and
associate a \bold {HtmlFile} instance with it.
\code
#include <coreplugin/editormanager/ieditor.h>
struct HtmlEditorData;
class HtmlEditor : public Core::IEditor
{
Q_OBJECT
public:
HtmlEditor(HtmlEditorWidget* editorWidget);
~HtmlEditor();
bool createNew(const QString& contents = QString());
QString displayName() const;
IEditor* duplicate(QWidget* parent);
bool duplicateSupported() const;
Core::IFile* file();
bool isTemporary() const;
const char* kind() const;
bool open(const QString& fileName = QString()) ;
bool restoreState(const QByteArray& state);
QByteArray saveState() const;
void setDisplayName(const QString &title);
QToolBar* toolBar();
// From Core::IContext
QWidget* widget();
QList<int> context() const;
protected slots:
void slotTitleChanged(const QString& title)
{ setDisplayName(title); }
private:
HtmlEditorData* d;
};
\endcode
\bold {HtmlEditorData} holds object of \bold {HtmlEditorWidget} and \bold {HtmlFile}. displayName is used as visual
description of the document.
\code
struct HtmlEditorData
{
HtmlEditorData() : editorWidget(0), file(0) { }
HtmlEditorWidget* editorWidget;
QString displayName;
HtmlFile* file;
QList<int> context;
};
\endcode
The constructor creates initializes itself on an \bold {HtmlEditorWidget}. It creates an \bold {HtmlFile} instance so that its
association with \bold {HtmlEditor} and widget is set.
\code
HtmlEditor::HtmlEditor(HtmlEditorWidget* editorWidget): Core::IEditor(editorWidget)
{
d = new HtmlEditorData;
d->editorWidget = editorWidget;
d->file = new HtmlFile(this, editorWidget);
Core::UniqueIDManager* uidm = Core::UniqueIDManager::instance();
d->context << uidm->uniqueIdentifier(HtmlEditorConstants::C_HTMLEDITOR);
connect(d->editorWidget, SIGNAL(contentModified()),d->file,SLOT(modified()));
connect(d->editorWidget, SIGNAL(titleChanged(QString)),this,SLOT(slotTitleChanged(QString)));
connect(d->editorWidget, SIGNAL(contentModified()),this,SIGNAL(changed()));
}
\endcode
The destructor does nothing other than deleting the private \bold {'d'} object.
\code
HtmlEditor::~HtmlEditor()
{
delete d;
}
\endcode
The following functions are self explanatory.
\code
QWidget* HtmlEditor::widget()
{
return d->editorWidget;
}
QList<int> HtmlEditor::context() const
{
return d->context;
}
Core::IFile* HtmlEditor::file()
{
return d->file;
}
\endcode
The \bold {createNew()} method is implemented to reset the contents of the \bold {HtmlEditorWidget} and \bold {HtmlFile}
objects. For now we ignore the contents parameter.
\code
bool HtmlEditor::createNew(const QString& contents)
{
Q_UNUSED(contents);
d->editorWidget->setContent(QByteArray());
d->file->setFilename(QString());
return true;
}
\endcode
The \bold {open()} method causes the \bold {HtmlFile} to open a given filename. It is assumed that the filename is a HTML
filename.
\code
bool HtmlEditor::open(const QString &fileName)
{
return d->file->open(fileName);
}
\endcode
The following method returns the \bold {'kind'} of the editor.
\code
namespace HtmlEditorConstants
{
const char* const C_HTMLEDITOR_MIMETYPE = "text/html";
const char* const C_HTMLEDITOR = "HTML Editor";
}
const char* HtmlEditor::kind() const
{
return HtmlEditorConstants::C_HTMLEDITOR;
}
\endcode
The string returned by \bold {displayName} is used in the open-file combobox. The following methods help set and fetch the
display name.
\code
QString HtmlEditor::displayName() const
{
return d->displayName;
}
void HtmlEditor::setDisplayName(const QString& title)
{
if(d->displayName == title)
return;
d->displayName = title;
emit changed();
}
\endcode
We implement the following methods to do nothing in this example.
\code
bool HtmlEditor::duplicateSupported() const
{
return false;
}
Core::IEditor* HtmlEditor::duplicate(QWidget* parent)
{
Q_UNUSED(parent);
return 0;
}
QByteArray HtmlEditor::saveState() const
{
return QByteArray();
}
bool HtmlEditor::restoreState(const QByteArray& state)
{
Q_UNUSED(state);
return false;
}
QToolBar* HtmlEditor::toolBar()
{
return 0;
}
bool HtmlEditor::isTemporary() const
{
return false;
}
\endcode
\section2 10.2.4 Implementing the Core::IEditorFactory interface
The \bold HtmlEditorFactory class implements the \bold Core::IEditorFactory interface; and is declared as follows.
\code
#include <coreplugin/editormanager/ieditorfactory.h>
struct HtmlEditorFactoryData;
class HtmlEditorFactory : public Core::IEditorFactory
{
Q_OBJECT
public:
HtmlEditorFactory(HtmlEditorPlugin* owner);
~HtmlEditorFactory();
QStringList mimeTypes() const;
QString kind() const;
Core::IEditor* createEditor(QWidget* parent);
Core::IFile* open(const QString &fileName);
private:
HtmlEditorFactoryData* d;
};
\endcode
\bold {HtmlEditorFactoryData} structure holds the private data of the \bold {HtmlEditorFactory} class. Notice that the
constructor initializes the mime-types to \bold {HtmlEditorConstants::C_HTMLEDITOR_MYMETYPE}. It also
initializes the \bold {kind} of the editor. This kind should be same as \bold{kind} of \bold {HtmlEditor}.
\code
namespace HtmlEditorConstants
{
const char* const C_HTMLEDITOR_MIMETYPE = "text/html";
const char* const C_HTMLEDITOR = "HTML Editor";
}
struct HtmlEditorFactoryData
{
HtmlEditorFactoryData(): kind(HtmlEditorConstants::C_HTMLEDITOR)
{
mimeTypes << QString(HtmlEditorConstants::C_HTMLEDITOR_MIMETYPE);
}
QString kind;
QStringList mimeTypes;
};
\endcode
The following methods are self-explanatory.
\code
HtmlEditorFactory::HtmlEditorFactory(HtmlEditorPlugin* owner):Core::IEditorFactory(owner)
{
d = new HtmlEditorFactoryData;
}
HtmlEditorFactory::~HtmlEditorFactory()
{
delete d;
}
QStringList HtmlEditorFactory::mimeTypes() const
{
return d->mimeTypes;
}
QString HtmlEditorFactory::kind() const
{
return d->kind;
}
\endcode
The \bold {open()} method should be implemented to return the IFile that is currently handling the given filename. If there
are none, then a new editor for the file is created and it's IFile is returned. To fully understand this process take a
look at the implementation of \bold {Core::EditorManager::openEditor()} method.
\code
Core::IFile* HtmlEditorFactory::open(const QString& fileName)
{
Core::EditorManager* em = Core::EditorManager::instance();
Core::IEditor* iface = em->openEditor(fileName, d->kind);
return iface ? iface->file() : 0;
}
\endcode
This method creates and returns an instance of the \bold {HtmlEditor} class.
\code
Core::IEditor* HtmlEditorFactory::createEditor(QWidget* parent)
{
HtmlEditorWidget* editorWidget = new HtmlEditorWidget(parent);
return new HtmlEditor(editorWidget);
}
\endcode
\section2 10.2.5 Implementing the plugin
We implement the \bold {HtmlEditorPlugin} plugin class using the same means described in Chapter 2. The only change is
the \bold {initialize()} method implementation.
\code
bool HtmlEditorPlugin::initialize(const QStringList &arguments, QString* errMsg)
{
Q_UNUSED(arguments);
Core::ICore* core = Core::ICore::instance();
Core::MimeDatabase* mdb = core->mimeDatabase();
if(!mdb->addMimeTypes("text-html-mimetype.xml", errMsg))
return false;
addAutoReleasedObject(new HtmlEditorFactory(this));
return true;
}
\endcode
When the plugin is compiled and Qt Creator is (re)started; we will be able to load HTML files using the newly
implemented editor plugin.
\inlineimage qtc-htmleditor-10.png
*/

View File

@@ -0,0 +1,549 @@
/*!
\page find-filter.html
\title 9. Find Filter
Qt Creator's find dialog box allows users to search for a text or regular expression in opened projects and unloaded disk
files. Clicking on "Edit -> Find/Replace -> Find Dialog" shows the find dialog box.
\inlineimage qtc-finddialog-9.png
In the find dialog box the "scope" and "configuration widget" are extensible. It is possible to add more items to the
scope combo box and against every item it is possible to provide a configuration widget that needs to be shown below.
Each item in the "scope" combo box is called "find filter" in Qt Creator lingo.
\section1 9.1 Find::IFindFilter interface
The \underline {find} plugin in Qt Creator exposes an interface called Find::IFindFilter. The interface is declared as follows in
the src/plugins/find/ifindfilter.h header.
\code
class FIND_EXPORT IFindFilter : public QObject
{
Q_OBJECT
public:
virtual ~IFindFilter() {}
virtual QString id() const = 0;
virtual QString name() const = 0;
virtual bool isEnabled() const = 0;
virtual QKeySequence defaultShortcut() const = 0;
virtual void findAll(const QString &txt, QTextDocument::FindFlags findFlags) = 0;
virtual QWidget *createConfigWidget() { return 0; }
virtual void writeSettings(QSettings *settings) { Q_UNUSED(settings); }
virtual void readSettings(QSettings *settings) { Q_UNUSED(settings); }
signals:
void changed();
};
\endcode
By implementing the \bold {IFindFilter} interface and adding an instance of it to the object pool, we will be able to add a
new find-filter; which means another entry in the "scope" combo box of the find dialog box.
\section1 9.2 Providing a custom filter
Suppose that we wanted to provide a custom filter that will allow us to look for files in the loaded projects that include a
given header. In the following steps we will understand how to write a find filter for this.
\section2 Step 1: Declaring the HeaderFilter class
We first begin by declaring a class called HeaderFilter that implements the Find::IFindFilter interface. The class
definition is as follows.
\code
#include <find/ifindfilter.h>
class HeaderFilter : public Find::IFindFilter
{
Q_OBJECT
public:
HeaderFilter();
~HeaderFilter();
QString id() const;
QString name() const;
bool isEnabled() const;
QKeySequence defaultShortcut() const;
void findAll(const QString &txt,
QTextDocument::FindFlags findFlags);
QWidget *createConfigWidget();
private:
HeaderFilterData *d;
};
\endcode
\section2 Step 2: Implementing the HeaderFilter class
The constructor and destructors are currently empty. We will fill in more code as we progress with our understanding of
the \bold {IFindFilter} interface.
\code
struct HeaderFilterData
{
};
HeaderFilter:: HeaderFilter()
{
d = new HeaderFilterData;
}
HeaderFilter::~ HeaderFilter()
{
delete d;
}
\endcode
The \bold{id()} method should be implemented to return a unique identifier for the find filter.
\code
QString HeaderFilter::id() const
{
return "HeaderFilter";
}
\endcode
The \bold {name()} method should be implemented to return the string that gets shown in the "scope" combo box of the find
dialog box.
\code
QString HeaderFilter::name() const
{
return tr("Header Filter");
}
\endcode
The \bold {isEnabled()} method should be implemented to return whether the find filter is enabled or not. In our case we
would like to show the filter enabled if projects are loaded in Qt Creator, false otherwise. To fully understand the
implementation of the function, we must first study the \bold {ProjectExplorer} namespace. For now let's just return true
and revisit the function after learning about the \bold {ProjectExplorer} namespace.
\code
bool HeaderFilter::isEnabled() const
{
return true;
}
\endcode
The \bold{defaultShortcut()} method should be implemented to return a key-sequence that the user can use to launch
the find dialog box with the "header filter" selected in "cope". In our implementation we return an invalid keysequence.
\code
QKeySequence HeaderFilter::defaultShortcut() const
{
return QKeySequence();
}
\endcode
The \bold {createConfigWidget()} method should be implemented to return a configuration widget that gets shown at
the bottom edge of the find dialog box.
\inlineimage qtc-configwidget-9.png
For our header-filter; let's return a simple QLabel because we don't want to provide any configuration options.
\code
QWidget *HeaderFilter::createConfigWidget()
{
return (new QLabel("This is a header filter"));
}
\endcode
The \bold{findAll()} method should be implemented to perform the actual "find" or "search" operation. We need to
understand few key classes in the \bold {ProjectExplorer},\bold {TextEditor},\bold {Find }and \bold {Core::Utils} namespace before
attempting to implement the filter. For now implement the method to do nothing.
\code
void HeaderFilter::findAll(const QString &text,QTextDocument::FindFlags findFlags)
{
// Do nothing
}
\endcode
\section2 Step 3: Implementing the "header-filter" plugin.
We implement the header-filter plugin very similar to the \bold {DoNothingPlugin} class described in Chapter 2. Here we
only look at the implementation if the \bold {initialize()} method.
\code
bool HeaderFilterPlugin::initialize(const QStringList& args,QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
addAutoReleasedObject(new HeaderFilter);
return true;
}
\endcode
\section2 Step 4: Testing the plugin
Upon compiling the plugin and restarting Qt Creator, we can notice the "Header Filter" item in the scope combo box of
the find dialog box.
\inlineimage qtc-testplugin-9.png
Currently no "finding" or "searching" is done by our plugin because we have not yet implemented the
\bold {HeaderFilter::findAll()} method.
\section1 9.3 The ProjectExplorer namespace
The \bold {ProjectExplorer} namespace comprises of classes and interfaces that make up the project management
system in Qt Creator. This namespace is provided by the \bold {projectexplorer} plugin. Support for project types are provided
by plugins. For example
\list
\o \bold {cmakeprojectmanager} plugin provides implementations of interfaces in \bold {ProjectExplorer} namespace for
supporting CMake projects
\o \bold {qt4projectmanager} plugin provides support for Qt 4 projects
\o \bold {qmlprojectmanager} plugin provides support for QML projects
\endlist
\table
\header
\o Class/Interface
\o Description
\row
\o \c {ProjectExplorer::IProjectManager}
\o This interface must be implemented to provide support for a kind of
project. Implementations of this interface help load projects into Qt
Creator.
\row
\o \c {ProjectExplorer::Project}
\o This interface describes a project in terms of
\list
\o A file (Core::IFile) that describes the project.
\o A Boolean flag describing whether the project builds an
application or library
\o Build steps (ProjectExplorer:: BuildStep) that
need to be performed in order to build and clean the project
\o Run configurations that need to be used for running the
project
\o The environment within which the project needs to be run
\o The root node in the project explorer panel
\o Include paths and macros to be used while building the project
\endlist
\row
\o \c {ProjectManager::}
\o This class is the implementation of the Core::IPlugin interface for the
\row
\o \c {ProjectExplorerPlugin}
\o project explorer plugin. Through this class we can
\list
\o gain access to all the open projects
\o gain access the current project
\o gain access to the currently selected node (file/folder) in the
project explorer panel
\o gain access to the build manager
\bold {(ProjectManager::BuildManager)}
\endlist
\endtable
\section2 9.3.1 Getting a list of open-projects
Using the \bold {ProjectManager::ProjectExplorerPlugin} class we can catch hold of all the open-projects in Qt
Creator. The following code snippet shows how to do that
\code
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/projectexplorer.h>
// Catch hold of the plugin-manager
ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance();
// Look for the ProjectExplorerPlugin object
ProjectExplorer::ProjectExplorerPlugin* projectExplorerPlugin
= pm->getObject<ProjectExplorer::ProjectExplorerPlugin>();
// Fetch a list of all open projects
QList<ProjectExplorer::Project*> projects = d->projectPlugin->session()->projects();
\endcode
From the projects list we can gain access to the project file and all the other (source, header, resource etc) files in the
project. To gain access to the project file(s) we can
\code
Q_FOREACH(ProjectExplorer::Project* project, projects)
{
QString name = project->name();
Core::IFile* projectFile = project->file();
// Do something with the above. For example:
qDebug("Project %s has project file as %s",
qPrintable(name),
qPrintable(projectFile->fileName()));
}
\endcode
While the above code snippet helps with fetching the project file (CMakeLists.txt, .pro etc..), it doesn't help us fetch all
the files associated with the project.
\section2 9.3.2 Getting a list of files
From the projects list we can get a string-list of all file names associated with the project using the following code
snippet.
\code
// Make a list of files in each project
QStringList files;
Q_FOREACH(ProjectManager::Project* project, projects)
files += project->files(Project::AllFiles);
\endcode
\section2 9.3.3 Enabling the HeaderFilter conditionally
Ideally the header-filter should be enabled only if there is atleast one open project. To make this happen, we upgrade
the HeaderFilter implementation as follows
\code
struct HeaderFilterData
{
ProjectExplorer::ProjectExplorerPlugin* projectExplorer()
{
if(m_projectPlugin)
return m_projectPlugin;
ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance();
m_projectPlugin = pm->getObject<ProjectExplorer::ProjectExplorerPlugin>();
return m_projectPlugin;
}
private:
ProjectExplorer::ProjectExplorerPlugin* m_projectPlugin;
};
bool HeaderFilter::isEnabled() const
{
QList<ProjectExplorer::Project*> projects = d->projectExplorer()->session()->projects();
if(projects.count())
return true;
return false;
}
\endcode
\section1 9.4 Searching in files
In the previous section we understood how to gain access to the file names of all files associated with open projects. We
are now in a position to search within files. Let's begin the implementation of the \bold {HeaderFilter::findAll()}
method, and understand more concepts as we progress.
\code
void HeaderFilter::findAll(const QString &text,QTextDocument::FindFlags findFlags)
{
// Fetch a list of all open projects
QList<Project*> projects = d->projectPlugin->session()->projects();
// Make a list of files in each project
QStringList files;
Q_FOREACH(Project* project, projects)
files += project->files(Project::AllFiles);
// Remove duplicates
files.removeDuplicates();
// Search for text in "files"
// ...
}
\endcode
The number of files that need to be searched can be varying. It may be as little as 1 and as high as 1000 or more! Hence
searching for something in files within the \bold {findAll()} method is a bad idea. If the \bold {findAll()} method takes too long
then it may cause Qt Creator to appear frozen until searching is finished.
The solution to this is
\list
\o We make use of QtConcurrent and spawn multiple threads to perform the actual searching
\o We initialize a QFutureWatcher on the QFuture returned by QtConcurrent to emit signals as and when
search results are generated
\o We catch the signals generated by QFutureWatcher and list search results as they come
\endlist
Qt Creator's core utils library provides a readymade function called \bold {findInFiles()} that looks for a string within a list
of files and returns a \bold {QFuture} to monitor search results. The function is declared as follows in src/libs/utils/filesearch.h
\code
namespace Core {
namespace Utils {
class FileSearchResult
{
public:
QString fileName;
int lineNumber;
QString matchingLine;
int matchStart;
int matchLength;
};
QFuture<FileSearchResult> findInFiles(const QString &searchTerm,const QStringList &files,
QTextDocument::FindFlags flags
);
QFuture<FileSearchResult> findInFilesRegExp(const QString &searchTerm,const QStringList &files,
QTextDocument::FindFlags flags
);
} // namespace Utils
} // namespace Core
\endcode
Lets now continue with the implementation of \bold {HeaderFilter::findAll()} by making use of the
\bold {findInFiles()} method.
\code
struct HeaderFilterData
{
QFutureWatcher<FileSearchResult> watcher;
ProjectExplorer::ProjectExplorerPlugin* projectExplorer() {
...
}
};
HeaderFilter::HeaderFilter()
{
d->watcher.setPendingResultsLimit(1);
connect(&d->watcher, SIGNAL(resultReadyAt(int)),
this, SLOT(displayResult(int)));
}
void HeaderFilter::findAll(const QString &text,QTextDocument::FindFlags findFlags)
{
....
// Remove duplicates
files.removeDuplicates();
// Begin searching
QString includeline = "#include <" + text + ">";
Find::SearchResult *result = d->searchResultWindow()->startNewSearch();
// Let the watcher monitor the search results
d->watcher.setFuture(QFuture<FileSearchResult>());
}
void HeaderFilter::displayResult(int index)
{
// TODO
}
\endcode
In the revised \bold {findAll()} implementation we make use of the \bold {findInFiles()} method to spawn multiple
background threads to do all the finding. As search results are generated, the \bold {displayResult(int)} slot is called. In
this slot we can now show search results to the user.
\section1 9.5 Showing search results
The "find" plugin provides an object of class \bold {Find::SearchResultWindow}. This class provides access to the widget
that displays search results.
\inlineimage qtc-search-9.png
We would like to show our search results in the "search result window" as well. To do so, we modify the
\bold {HeaderFilter} code as follows
\code
#include <find/searchresultwindow.h>
struct HeaderFilterData
{
// Method to search and return the search window
Find::SearchResultWindow* searchResultWindow()
{
if(m_searchResultWindow)
return m_searchResultWindow;
ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance();
m_searchResultWindow = pm->getObject<Find::SearchResultWindow>();
return m_searchResultWindow;
}
private:
Find::SearchResultWindow *m_searchResultWindow;
};
HeaderFilter::HeaderFilter()
{
// displayResult(int) is called when every a new
// search result is generated
connect(&d->watcher, SIGNAL(resultReadyAt(int)),this, SLOT(displayResult(int)));
}
void HeaderFilter::findAll(const QString &text,QTextDocument::FindFlags findFlags)
{
...
//When result gets activated it invokes the openEditor function
connect(result, SIGNAL(activated(Find::SearchResultItem)),
this, SLOT(openEditor(Find::SearchResultItem)));
d->searchResultWindow()->popup(true);
d->watcher.setFuture(Utils::findInFiles(includeline, files, findFlags));
}
void HeaderFilter::displayResult(int index)
{
FileSearchResult result = d->watcher.future().resultAt(index);
d->searchResultWindow()->addResult(result.fileName,
result.lineNumber,
result.matchingLine,
result.matchStart,
result.matchLength);
}
void HeaderFilter::openEditor(const QString &fileName, int line, int column)
{
// TODO
}
\endcode
Whenever the user double clicks on the search results, the \bold {openEditor()} method is called. In that method we should
have Qt Creator open the corresponding file and mark the searched text.
\section1 9.6 Opening the searched files
Without going into too many details about the texteditor plugin, lets just take a look at the function that loads a named
file for us and moves the cursor to a specified location. The \bold {BaseTextEditor} class in the \bold {TextEditor} namespace
provides a static method called \bold {openEditorAt()} that serves our purpose.
\code
namespace TextEditor {
class BaseTextEditor : public QPlainTextEdit
{
public:
....
static ITextEditor *openEditorAt(const QString &fileName,int line, int column = 0,
const QString &editorKind);
....
};
} // TextEditor namespace
\endcode
We now update the \bold {HeaderFilter::openEditor()} slot as follows
\code
#include <texteditor/basetexteditor.h>
void HeaderFilter::openEditor(const Find::SearchResultItem &item)
{
TextEditor::BaseTextEditor::openEditorAt(item.fileName, item.lineNumber, item.index);
}
\endcode
With this the \bold {HeaderFilter} is now complete.
*/

View File

@@ -0,0 +1,6 @@
/*!
\page find-support.html
\title 9.Find support
This page needs to be written still!
*/

View File

@@ -0,0 +1,327 @@
/*!
\page first-plugin.html
itle 2. First Plugin
The best way to learn about writing Qt Creator plugins is to actually start by writing the very first plugin.
There are two ways for writing plugins for Qt Creator:
\list
\o \l {Writing plugin inside the source tree.}
\o \l {Writing plugin outside the source tree.}
\endlist
For Writing plugin in the any of the above mentioned way Qt Creator source scould have been compiled.
Lets keep our goals very simple for this one. We are going to provide a plugin for Qt Creator that does nothing. The purpose behind
this "Do nothing" plugin is to discover the basic classes in Qt Creator and to feel happy when our plugin shows up in the
"plugin list"
\inlineimage qtc-aboutplugin-2.png
arget {Writing plugin inside the source tree.}
\section1 2.1 Create a plugin project in Qt Creator
Create a folder called DoNothing in $$QT_CREATOR_ROOT/src/plugins directory. The entire source code of
the plugin will be put into this directory.
\bold {Note:}\underline {It may be possible to write and build Qt Creator plugins outside of its source tree, but it is
much easier to write plugins within the source tree}.
Lets first create the \c {DoNothing.pro} file with the following contents
\code
TEMPLATE = lib
TARGET = DoNothing
PROVIDER = FooCompanyInc
include(../../qtcreatorplugin.pri)
include(../../plugins/coreplugin/coreplugin.pri)
HEADERS += DoNothingPlugin.h
SOURCES += DoNothingPlugin.cpp
OTHER_FILES += DoNothing.pluginspec
\endcode
The project file configures the following aspects of the plugin:
\list 1
\o Declares that DoNothing is a library. The output will be DoNothing.dll
\o Configures DoNothing to make use of settings defined in qtcreatorplugin.pri
\o Overrides the default destination directory to $$IDE_PLUGIN_PATH/FooCompanyInc. By default the value
will be to $$IDE_PLUGIN_PATH/Nokia
\o Configures DoNothing to make use of settings defined in coreplugin.pri
\o Provides information about the .h and .cpp files that make up the plugin
\endlist
\section1 2.2 Marking the plugin for build
Edit the \c {$$QT_CREATOR_ROOT/src/plugins/plugins.pro } file and include the following lines at the end of
the file and save the changes.
\code
SUBDIRS += plugin_DoNothing
plugin_DoNothing.subdir = DoNothing
\endcode
The above lines make sure that the next time we build Qt Creator, the DoNothing plugin is compiled along with the rest
of Qt Creator plugins.
\section1 2.3 Implementing the plugin
So far we have only written the project file and marked our plugin for compilation. We now do the actual
implementation of the plugin. All plugins implement the IPlugin interface. Lets take a look at how the DoNothing plugin
implements the interface and understand it in stages.
In \c {$$QT_CREATOR_ROOT/src/plugins/DoNothing/DoNothingPluigin.h} enter the following code.
\code
#ifndef DONOTHINGPLUGIN_H
#define DONOTHINGPLUGIN_H
#include <extensionsystem/iplugin.h>
class DoNothingPlugin : public ExtensionSystem::IPlugin
{
public:
DoNothingPlugin();
~DoNothingPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
};
#endif // DONOTHINGPLUGIN_H
\endcode
As you can see the DoNothingPlugin class implements the IPlugin interface and nothing else. Lets look at how the
functions are implemented.
\code
#include "DoNothingPlugin.h"
#include <QtPlugin>
#include <QStringList>
DoNothingPlugin::DoNothingPlugin()
{
// Do nothing
}
DoNothingPlugin::~DoNothingPlugin()
{
// Do notning
}
\endcode
Apart from initializing local (non widget and non action) variables; the constructor and destructor don't do much else.
\code
bool DoNothingPlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
return true;
}
\endcode
The \bold initialize() method is called when Qt Creator wants the plugin to initialize itself. This function is ideally used to
initialize the internal state of the plugin and register actions/objects with Qt Creator. The function is called after all the
dependencies of this plugin have been loaded.
Since our plugin really does nothing, we return \bold {true} signifying that the initialization was successful. If the initialization
was unsuccessful (for some wired reason); the \bold {errMsg} string should be set to a human readable error message.
\code
void DoNothingPlugin::extensionsInitialized()
{
// Do nothing
}
\endcode
The \bold extensionsInitialized() method is called after this plugin has been initialized (ie. after initialize() method has been
called). This method is called on plugins that depend on this plugin first.
\code
void DoNothingPlugin::shutdown()
{
// Do nothing
}
\endcode
The \bold shutdown() method is called when the plugin is about to be unloaded.
\code
Q_EXPORT_PLUGIN(DoNothingPlugin)
\endcode
Finally we export the plugin class by making use of the \bold {Q_EXPORT_PLUGIN()} macro.
\section1 2.4 Writing the pluginspec file
Each plugin should accompany a pluginspec file that provides some meta data about the plugin. For our plugin the
pluginspec file is as follows
\code
<plugin name="DoNothing" version="0.0.1">
<vendor>FooCompanyInc</vendor>
<copyright>(C) 2009-2010 FooCompanyInc Pvt. Ltd.</copyright>
<license>Do anything you want</license>
<description>A plugin that does nothing</description>
<url>http://www.FooCompanyInc.com</url>
<dependencyList>
<dependency name="Core"/>
</dependencyList>
</plugin>
\endcode
The pluginspec file provides the following fields of information:
\list 1
\o Name of the plugin, which is also used as the name of the library file that provides the plugin implementation.
(In our case DoNothing.dll on Windows, libDoNothing.so on Unix)
\o Version of the plugin
\o Vendor name
\o Copyright
\o License text
\o Description
\o URL of the plugin vendor
\o Dependency List provides all the plugins that this plugin depends on. Qt Creator ensures that dependencies
are loaded and initialized before this plugin.
\endlist
\bold {Note:}\underline {The pluginspec file should be in the same directory as the plugin's project file. Just to make things clear, the
contents of the DoNothing plugin directory is as shown below}
\inlineimage qtc-plugindirectory-2.png
\section1 2.5 Compiling the plugin
Open a command prompt and move to the Qt Creator build directory (the same build directory you created in the
previous chapter). Execute the following commands
\code
qmake ..\qtcreator.pro -recursive
nmake
\endcode
After nmake returns, you will notice a FooCompanyInc folder within plugins folder whose contents are shown in the image
below.
\inlineimage qtc-compiledplugin-2.png
\section1 2.6 Check out the new plugin
Launch (or relaunch) Qt Creator and notice that the "Installed Plugins" dialog box now reports that DoNothing plugin
was infact loaded and initialized.
\inlineimage qtc-installedplugin-2.png
In the coming chapters we will learn to write more complicated plugins for Qt Creator.
arget {Writing plugin outside the source tree.}
\section1 2.7 Building out-of-source plugins
Thus far we have understood how to build plugins within the source tree of Qt Creator. It may not be practical for us to
use the Qt Creator source tree for plugin development all the time. Suppose that you are the author of a specialized
library (or application) and you want integrate your product into Qt Creator. Since you are a 3rd party developer you
cannot expect to have your code in Qt Creator source tree all the time. In this section we will look at how to build
plugins that are outside the Qt Creator source tree.
\section2 2.7.1 The plugin project file
The whole magic of out-of-source plugin builds lies in the project (.pro) file of your plugin. Lets the DoNothing plugin
discussed in the previous section and modify (its ".pro" file) so that plugins can be built from a directory outside Qt
Creator source.
The following table lists out the directory structure
able
\header
\o Description
\o Directory
\row
\o Qt Creator Source Code
\o C:\\Work\\QtCreator
\row
\o Qt Creator Build Directory
\o C:\\Work\\QtCreator\\build
\row
\o DoNothing Plugin Source
\o C:\\Work\\Research\\QtCreator\\Plugins\\DoNothing
This directory currently contains
\list
\o DoNothing.pluginspec
\o DoNothing.pro
\o DoNothingPlugin.cpp
\o DoNothingPlugin.h
\endlist
\row
\o Target plugin directory
\o C:\\Work\\QtCreator\\build\\lib\\qtcreator\\plugins\\FooCompanyInc
\endtable
Let's now modify the DoNothing.pro file in C:\\Work\\Research\\QtCreator\\Plugins\\DoNothing as follows.
\code
QTC_SOURCE = C:/Work/QtCreator/
QTC_BUILD = C:/Work/QtCreator/build/
TEMPLATE = lib
TARGET = DoNothing
IDE_SOURCE_TREE = $$QTC_SOURCE
IDE_BUILD_TREE = $$QTC_BUILD
PROVIDER = FooCompanyInc
LIBS += -L$$IDE_PLUGIN_PATH/Nokia
include($$QTC_SOURCE/src/qtcreatorplugin.pri)
include($$QTC_SOURCE/src/plugins/coreplugin/coreplugin.pri)
HEADERS = DoNothingPlugin.h
SOURCES = DoNothingPlugin.cpp
OTHER_FILES = DoNothingPlugin.pluginspec
\endcode
The \bold{QTC_SOURCE} and \bold {QTC_BUILD} variables in the project file point to the source and build directories of Qt Creator.
If you prefer setting these as environment variables, then use \bold{$$(QTC_BUILD)} instead of \bold{$$QTC_BUILD} in the
project file.
The \bold {IDE_SOURCE_TREE} and \bold {IDE_BUILD_TREE} variables are used by qtcreatorplugin.pri to establish the include
and library paths.
The \bold {PROVIDER} and \bold {DESTDIR} directories must be set before including qtcreatorplugin.pri. This is because the variables
will be provided default values are \bold {Nokia} and \bold {$$IDE_BUILD_TREE/lib/qtcreator/plugins/Nokia} otherwise.
By default qtcreatorplugin.pri assumes that all the libs that a plugin may depend on are present inside the \bold {DESTDIR}. If
our \bold {DESTDIR} is different from the default (Nokia) one, then we will need to explicitly set that. The remaining things are
just the same.
\section2 2.7.2 Compiling the plugin
Once the project file has been created, we make use of the standard qmake and make commands to compile the plugin.
\code
C:\Work\Research\QtCreator\Plugins\DoNothing>qmake
C:\Work\Research\QtCreator\Plugins\DoNothing>nmake
Microsoft (R) Program Maintenance Utility Version 8.00.50727.762
Copyright (C) Microsoft Corporation. All rights reserved.
"C:\Program Files\Microsoft Visual Studio 8\VC\BIN\nmake.exe" -f Makefile.Debug
Microsoft (R) Program Maintenance Utility Version 8.00.50727.762
Copyright (C) Microsoft Corporation. All rights reserved.
copy /y "DoNothing.pluginspec"
"..\..\..\..\QtCreator\build\lib\qtcreator\plugins\FooCompanyInc\DoNothing.pluginspec"
1 file(s) copied.
........................................
mt.exe -nologo -manifest "debug\DoNothingd.intermediate.manifest" -
outputresource:..\..\..\..\QtCreator\build\lib\qtcreator\plugins\FooCompanyInc\DoNothingd.dll;2
C:\Work\Research\QtCreator\Plugins\DoNothing>
\endcode
*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Some files were not shown because too many files have changed in this diff Show More