forked from qt-creator/qt-creator
This allows desktop environments to pick the right icon size when displaying the Qt Creator menu entry. Change-Id: I10f6b46fb99202571d081a5e6e4d680be7ca069f Merge-request: 328 Reviewed-by: Daniel Molkentin <daniel.molkentin@nokia.com> Reviewed-on: http://codereview.qt.nokia.com/64
538 lines
16 KiB
Plaintext
538 lines
16 KiB
Plaintext
/*!
|
|
\page mode.html
|
|
\title 13. Adding a mode
|
|
|
|
When we are working in Qt Creator then we in one of the six modes below.
|
|
|
|
\list
|
|
\o Welcome
|
|
\o Edit
|
|
\o Debug
|
|
\o Project
|
|
\o Help
|
|
\o Output
|
|
\endlist
|
|
|
|
By selecting different modes in Qt creator we can quickly switch between different task spaces, such
|
|
as editing, browsing the Qt Creator manual, setting up the build environment, etc.
|
|
Different modes can be selected either by clicking on the mode selectors or through keyboard shortcuts.
|
|
|
|
The following figure shows the mode selectors in the Qt Creator.
|
|
|
|
\inlineimage qtc-modes-13.png
|
|
|
|
|
|
Now in this chapter we are concerned about learning to add a new mode and a "LoggerMode" mode selector will be availble in Qt Creator.
|
|
|
|
\section1 13.1 Core Classes and Interfaces
|
|
|
|
To support a new mode we need to
|
|
\list
|
|
\o Implement a plugin \bold {(ExtensionSystem::IPlugin } implementation) class that exposes the new mode.Chapter 2 in this
|
|
document provides a detailed description on creating plugins by implementing the ExtensionSystem::IPlugin interface.
|
|
\o Implement the \bold{(Core::IMode)} interface. This interface allows us to add a new mode in Qt creator
|
|
\endlist
|
|
|
|
|
|
\section2 Step 1. Core::IMode interface
|
|
This interface abstracts the creation of a mode, adding an icon to the mode selector, setting the mode priority,
|
|
setting a unique made name. The \bold {Core::IMode} interface is declared as follows in scr/plugins/coreplugin/imode.h
|
|
\code
|
|
namespace Core {
|
|
|
|
class CORE_EXPORT IMode : public IContext
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
IMode(QObject *parent = 0) : IContext(parent) {}
|
|
virtual ~IMode() {}
|
|
|
|
virtual QString name() const = 0;
|
|
virtual QIcon icon() const = 0;
|
|
virtual int priority() const = 0;
|
|
virtual const char *uniqueModeName() const = 0;
|
|
};
|
|
} // namespace Core
|
|
\endcode
|
|
|
|
Notice that Core::IMode inherits Core::IContext. Core::IContext is an interface through which
|
|
Qt Creator picks up the widget corresponding to the mode. The Core::IContext interface is declared
|
|
as follows.
|
|
|
|
\code
|
|
namespace Core
|
|
{
|
|
|
|
class CORE_EXPORT 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(); }
|
|
};
|
|
}
|
|
\endcode
|
|
|
|
\section1 13.2 Adding a new mode
|
|
Lets add a mode to Qt Creator called "LoggerMode". LoggerMode allows the user (developer) to log the number of hours he/she
|
|
has worked on a project. The following steps explain how the new mode "LoggerMode" is added.
|
|
|
|
\section2 Step 1. Declaring the LoggerMode class
|
|
We first begin by declaring a class called LoggerMode that implements the Core::IMode interface.
|
|
The class definition is as follows.
|
|
\code
|
|
#include <coreplugin/imode.h>
|
|
|
|
struct LoggerModeData;
|
|
class LoggerMode : public Core::IMode
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
LoggerMode();
|
|
~LoggerMode();
|
|
|
|
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"); }
|
|
|
|
private:
|
|
LoggerModeData *d;
|
|
};
|
|
\endcode
|
|
|
|
\section2 Step 2. Implementing the LoggerMode class
|
|
Declaring the private variables of the LoggerMode class.
|
|
\code
|
|
struct LoggerModeData
|
|
{
|
|
QWidget *m_widget;
|
|
};
|
|
\endcode
|
|
The constructor creates a new blank widget just for now to get started with the mode.
|
|
The constructor and the destructor are implemented as follows
|
|
\code
|
|
LoggerMode::LoggerMode()
|
|
{
|
|
d = new LoggerModeData;
|
|
d->m_widget = new QWidget;
|
|
}
|
|
|
|
LoggerMode::~LoggerMode()
|
|
{
|
|
delete d->m_widget;
|
|
delete d;
|
|
}
|
|
\endcode
|
|
The \bold {name()} method returns a name for the new mode selector.
|
|
\code
|
|
QString LoggerMode::name() const
|
|
{
|
|
return tr("LoggerMode");
|
|
}
|
|
\endcode
|
|
|
|
The \bold {icon()} method returns a logo for the new mode selector.
|
|
\code
|
|
QIcon LoggerMode::icon() const
|
|
{
|
|
return QIcon(QLatin1String(":/core/images/logo/32/qtcreator.png"));
|
|
}
|
|
\endcode
|
|
|
|
The \bold {priority()} method is implemented to return a priority for the mode. Modes of higher
|
|
priority are shown above modes of lower priority. The highest priority in Qt Creator is currently
|
|
100 and is associated with the Welcome mode. We return 0 from LoggerMode, becasue we want this
|
|
mode to appear at the end.
|
|
\code
|
|
int LoggerMode::priority() const
|
|
{
|
|
return 0;
|
|
}
|
|
\endcode
|
|
Thw \bold {widget()} method returns a widget to the new mode.
|
|
\code
|
|
QWidget* LoggerMode::widget()
|
|
{
|
|
return d->m_widget;
|
|
}
|
|
\endcode
|
|
|
|
The \bold {uniqueModeName()} returns the name of the mode to the "LoggerMode" Class.
|
|
\code
|
|
const char* LoggerMode::uniqueModeName() const
|
|
{
|
|
return "LoggerMode" ;
|
|
}
|
|
\endcode
|
|
The \bold {context()} method returns an empty list of integers to tne "LoggerMode" class.
|
|
\code
|
|
QList<int> LoggerMode::context() const
|
|
{
|
|
return QList<int>();
|
|
}
|
|
\endcode
|
|
|
|
\section2 Step 3. Implementing the "LoggerMode" plugin
|
|
We implement the "LoggerMode" plugin very similar to the DoNothingPlugin class described in Chapter 2.
|
|
Here we only look at the implementation of the initialize() method.
|
|
\code
|
|
bool LoggerModePlugin::initialize(const QStringList& args, QString *errMsg)
|
|
{
|
|
Q_UNUSED(args);
|
|
Q_UNUSED(errMsg);
|
|
|
|
loggerMode = new LoggerMode;
|
|
addAutoReleasedObject(loggerMode);
|
|
|
|
return true;
|
|
}
|
|
\endcode
|
|
\section2 Step 4. Testing the plugin.
|
|
Upon compiling the plugin and restarting Qt Creator, we can notice the "LoggerMode" mode selector in the Qt creator.
|
|
|
|
\inlineimage qtc-loggermode-13.png
|
|
|
|
\section1 13.3 Adding Functionality to the "LoggerMode"
|
|
The actual function of the "LoggerMode" is to log data in a text file about a project, such as progress , hours worked,
|
|
description etc.
|
|
|
|
\section2 Step 1. Modifying the "LoggerMode" Class
|
|
|
|
To add the functionalities, the LoggerMode class is further modified.
|
|
The code block is given as follows.
|
|
|
|
\code
|
|
struct LoggerModeData;
|
|
class LoggerMode :public Core::IMode
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
LoggerMode();
|
|
~LoggerMode();
|
|
...
|
|
...
|
|
|
|
protected slots:
|
|
void addNewStackWidgetPage(const QString projectName);
|
|
void addItem();
|
|
|
|
private:
|
|
...
|
|
};
|
|
\endcode
|
|
|
|
The constructor of the \bold {LoggerMode} class is modified as follows.
|
|
\code
|
|
LoggerMode::LoggerMode()
|
|
{
|
|
d = new LoggerModeData;
|
|
d->m_widget = new QWidget;
|
|
|
|
//Current Projects Label and combobox widget are created.
|
|
|
|
d->currentProjectsLabel = new QLabel("Current projects :");
|
|
d->currentProjectsLabel->setFixedWidth(90);
|
|
d->currentProjectsCombobox = new QComboBox;
|
|
d->currentProjectsCombobox->setSizePolicy(QSizePolicy::Preferred,
|
|
QSizePolicy::Preferred);
|
|
|
|
//Add Projects Label and combobox widget are created.
|
|
|
|
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);
|
|
|
|
//Creating a horizontal Layout
|
|
|
|
QHBoxLayout *hLayout = new QHBoxLayout;
|
|
hLayout->addWidget(d->currentProjectsLabel);
|
|
hLayout->addWidget(d->currentProjectsCombobox);
|
|
hLayout->addWidget(d->addProjectLabel);
|
|
hLayout->addWidget(d->addProjectComboBox);
|
|
hLayout->addWidget(d->addToProjectButton);
|
|
|
|
//creating a stackedWidget
|
|
|
|
d->stackedWidget = new QStackedWidget;
|
|
|
|
//creating a vertical layout
|
|
|
|
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)));
|
|
}
|
|
|
|
\endcode
|
|
|
|
Implementation of the \bold{addNewStackWidgetPage()} slot of \bold {LoggerMode} class
|
|
\code
|
|
void LoggerMode::addNewStackWidgetPage(const QString projectName)
|
|
{
|
|
d->stackedWidget->addWidget(new LoggerModeWidget(projectName));
|
|
}
|
|
\endcode
|
|
|
|
Implementation of the \bold{addItem()} slot of \bold {LoggerMode} class
|
|
\code
|
|
void LoggerMode::addItem()
|
|
{
|
|
d->currentProjectsCombobox->addItem(d->addProjectComboBox->currentText());
|
|
addNewStackWidgetPage(d->currentProjectsCombobox->itemText(0));
|
|
}
|
|
\endcode
|
|
|
|
The effect of the above block of code can be seen in the following image.
|
|
|
|
\inlineimage qtc-loggerpage-13.png
|
|
|
|
|
|
\section2 Step 2. Declaration of the "LoggerModeWidget" class
|
|
Reffering to the above image, when ever we select a project from the \bold {Add Project} combobox and click
|
|
\bold {Add Project} button a new project is added to the \bold {Current projects} list and and a corresponding
|
|
\bold {LoggerModeWidget} is opened, for logging different informations about the project.
|
|
The declaration of the \bold {LoggerModeWidget} class is shown in the following code block.
|
|
|
|
\code
|
|
#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;
|
|
};
|
|
\endcode
|
|
|
|
\section2 Step 3. Implementing the "LoggerModeWidget" class
|
|
Declaring the private member variables in the structure called \bold {LoggerModeWidgetData}
|
|
\code
|
|
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;
|
|
};
|
|
\endcode
|
|
Implementation of the constructor and destructor of the \bold {LoggerModeWidget} class
|
|
\code
|
|
LoggerModeWidget::LoggerModeWidget(const QString projectName, QWidget* parent)
|
|
:QWidget(parent)
|
|
{
|
|
d = new LoggerModeWidgetData;
|
|
d->projectName = projectName;
|
|
d->totalTime = 0;
|
|
|
|
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);
|
|
|
|
// 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;
|
|
}
|
|
|
|
\endcode
|
|
|
|
The \bold {saveToFile()} slot is used by the "SaveTofile" button to save the contents of the "LoggerModeWidget" to a
|
|
text file.
|
|
\code
|
|
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;
|
|
}
|
|
\endcode
|
|
The \bold {startTimeLog()} slot is used by the \bold {Start Timer} button to start the timer.
|
|
\code
|
|
void LoggerModeWidget::startTimeLog()
|
|
{
|
|
d->totalTime = 0;
|
|
d->timer->start(1000);
|
|
}
|
|
\endcode
|
|
|
|
The \bold {endTimeLog()} slot is used by the \bold (Pause Timer } button to pause and resume the timer.
|
|
\code
|
|
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);
|
|
}
|
|
}
|
|
\endcode
|
|
|
|
The \bold {updateTime()} slot is used to update the time.
|
|
\code
|
|
void LoggerModeWidget::updateTime()
|
|
{
|
|
d->totalTime++;
|
|
QTime time(0,0,0);
|
|
time = time.addSecs(d->totalTime);
|
|
d->hoursWorkedLineEdit->setText(time.toString());
|
|
}
|
|
\endcode
|
|
|
|
\section1 13.4 Testing the final LoggerMode plugin.
|
|
|
|
\section2 Step 1. A "LoggerMode" mode selector can be seen int the Qt Creator.
|
|
\inlineimage qtc-loggermode-13.png
|
|
|
|
\section2 Step 2. A LoggerMode widget opens with options to "Add Projects"
|
|
\inlineimage qtc-loggerpage-13.png
|
|
|
|
\section2 Step 3. The "Add Project" button adds a project to the "Current Project list and opens the the "LoggerModeWidget"
|
|
\inlineimage qtc-loggermodewidget-13.png
|
|
|
|
*/
|