Commit f633d66c authored by dt's avatar dt
Browse files

Merge branch '0.9.1-beta' of git@scm.dev.nokia.troll.no:creator/mainline into 0.9.1-beta

parents d6e726ec ecfb77d4
......@@ -814,21 +814,26 @@
a pointer to some private data structure, you will see a list of children,
signals and slots.
Similarily, instead of showing a bunch of pointers and ints,
a QHash or QMap will display its contents in an orderly fashion,
a QFileInfo will expose e.g. access data, and the otherwise
"opaque" QVariant gives access to the "real" contents.
The \gui{Locals and Watchers View} can be used to change the
contents of variables of simple data types like int or float
while the program is stopped. To do so, click into the 'Value'
column, modify the value there, and hit \key{Return}.
Similarly, instead of displaying many pointers and integers, Qt Creator's
debugger will display the contents of a QHash or QMap in an orderly manner.
Also, the debugger will display access data for QFileInfo and provide
access to the "real" contents of QVariant.
The \gui{Locals and Watchers} view can be used to change the contents of
variables of simple data types such as \c int or \c float when the program
is stopped. To do so, click on the \gui Value column, modify the value
with the inplace editor, and hit \key Enter (or \key Return).
\section2 Modules
The \gui{Modules View} is hidden by default and only useful in
By default, the \gui Modules view is hidden as it is only useful with the
experimental delayed debug information loading feature. You can turn this
feature on by selecting \gui{Fast Debugger Start}
The \gui Modules view is hidden by default and only useful in
connection with the experimental feature of delayed debug
information loading. This feature is accessible by selecting
\gui{Debug} and \gui{Fast Debugger Start}. When using the
......@@ -849,29 +854,28 @@
commands
\section1 A Walkthrough for the Debugger Frontend
\section1 A short walk through the debugger frontend
In our \l{Writing a Simple Program with Qt Creator}{TextFinder}
example, we read a text file into a QString and then display it with a
QTextEdit. Suppose, you would like to look at this QString, \c{line},
and see what data it actually stores. Follow the steps described below
to place a break point and view the QString object's data.
In our \l{Writing a Simple Program with Qt Creator}{TextFinder} example, we
read a text file into a QString and then display it with a QTextEdit.
Suppose, you would like to look at this QString, \c{line}, and see what
data it actually stores. Follow the steps described below to place a
breakpoint and view the QString object's data.
\table
\row
\i \inlineimage qtcreator-setting-breakpoint1.png
\i \inlineimage qtcreator-setting-breakpoint1.png
\i \bold{Setting a Breakpoint}
First, we set a breakpoint on the line where we invoke
\l{QTextEdit::}{setPlainText()} by clicking between the line number and
the window border. Then, select \gui{Start Debugging} from the
\gui{Debug} menu or press \key{F5}.
\l{QTextEdit::}{setPlainText()} by clicking between the line number and the
window border. Then, select \gui{Start Debugging} from the \gui{Debug} menu
or press \key{F5}.
\endtable
Breakpoints are visible in the \gui{Breakpoints} view, shown below, in
\gui{Debug} mode. If you wish to remove a breakpoint, simply right
click on it and select \gui{Delete breakpoint} from the context menu.
\gui{Debug} mode. If you wish to remove a breakpoint, simply right-click on
it and select \gui{Delete breakpoint} from the context menu.
\image qtcreator-setting-breakpoint2.png
......@@ -880,10 +884,10 @@
\image qtcreator-watcher.png
Suppose we modify our \c{on_findButton_clicked()} function to move back
to the start of the document and continue searching once the cursor
hits the end of the document. Adding this functionality can be done
with the code snippet below:
Suppose we modify our \c{on_findButton_clicked()} function to move back to
the start of the document and continue searching once the cursor hits the
end of the document. Adding this functionality can be done with the code
snippet below:
\code
void TextFinder::on_findButton_clicked()
......@@ -915,9 +919,9 @@
}
\endcode
However, if you compile and run this code, the application will not
work correctly due to a logic error. To locate this logic error, you
can step through the code using the following buttons:
However, if you compile and run this code, the application will not work
correctly due to a logic error. To locate this logic error, you can step
through the code using the following buttons:
\image qtcreator-debugging-buttons.png
*/
......@@ -931,20 +935,20 @@
\title Tips and Tricks
\bold{Quick mode switch}
\bold{Quickly Switching between Modes}
You can quickly switch between modes by pressing \key{Ctrl+1},
\key{Ctrl+2}, etc.
\key{Ctrl+2}, and so on.
\bold{Other keyboard shortcuts}
\bold{Keyboard Shortcuts}
There are a lot of other \l{keyboard-shortcuts}{keyboard shortcuts}.
Qt Creator provides a lot of useful keyboard shortcuts. A complete list can
be found \l{Keyboard Shortcuts}{here}.
\bold{Command line}
\bold{Running Qt Creator from the Command Line}
You can start Qt Creator from a command prompt with an already
existing session or \c{.pro} file by giving the name as argument on the
command line.
You can start Qt Creator from a command prompt with an existing session or
\c{.pro} file by giving the name as argument on the command line.
\bold{Sidebar}
......
......@@ -292,6 +292,7 @@ Use *Scope::useAt(unsigned index) const
void Scope::addUse(unsigned sourceOffset, Name *name)
{
#ifdef CPLUSPLUS_WITH_USES
if (++_useCount == _allocatedUses) {
_allocatedUses += 4;
_uses = reinterpret_cast<Use *>(realloc(_uses, _allocatedUses * sizeof(Use)));
......@@ -303,6 +304,7 @@ void Scope::addUse(unsigned sourceOffset, Name *name)
else
lastVisibleSymbol = _symbols[_symbolCount];
_uses[_useCount].init(sourceOffset, name, lastVisibleSymbol);
#endif
}
CPLUSPLUS_END_NAMESPACE
......@@ -9,7 +9,8 @@ HEADERS += \
$$PWD/helpviewer.h \
$$PWD/contentwindow.h \
$$PWD/bookmarkmanager.h \
$$PWD/../namespace_global.h
$$PWD/../namespace_global.h \
$$PWD/indexwindow.h
SOURCES += \
$$PWD/filternamedialog.cpp \
......@@ -19,7 +20,7 @@ SOURCES += \
$$PWD/contentwindow.cpp \
$$PWD/bookmarkmanager.cpp
FORMS += \
FORMS += \
$$PWD/filternamedialog.ui \
$$PWD/topicchooser.ui \
$$PWD/bookmarkdialog.ui
......@@ -61,11 +61,11 @@ Icons::Icons()
{
}
QIcon Icons::iconForSymbol(Symbol *symbol) const
QIcon Icons::iconForSymbol(const Symbol *symbol) const
{
if (symbol->isFunction() || (symbol->isDeclaration() && symbol->type()->isFunction()))
{
Function *function = symbol->asFunction();
const Function *function = symbol->asFunction();
if (!function)
function = symbol->type()->asFunction();
......
......@@ -47,7 +47,7 @@ class CPLUSPLUS_EXPORT Icons
public:
Icons();
QIcon iconForSymbol(Symbol *symbol) const;
QIcon iconForSymbol(const Symbol *symbol) const;
QIcon keywordIcon() const;
QIcon macroIcon() const;
......
......@@ -235,9 +235,9 @@ bool ResolveExpression::visit(ExpressionListAST *)
return false;
}
bool ResolveExpression::visit(BinaryExpressionAST *)
bool ResolveExpression::visit(BinaryExpressionAST *ast)
{
// nothing to do.
accept(ast->left_expression);
return false;
}
......
......@@ -33,26 +33,65 @@
#include "filenamevalidatinglineedit.h"
#include <QtCore/QRegExp>
#include <QtCore/QDebug>
namespace Core {
namespace Utils {
// Naming a file like a device name will break on Windows, even if it is
// "com1.txt". Since we are cross-platform, we generally disallow such file
// names.
static const QRegExp &windowsDeviceNoSubDirPattern()
{
static const QRegExp rc(QLatin1String("CON|AUX|PRN|COM1|COM2|LPT1|LPT2|NUL"),
Qt::CaseInsensitive);
Q_ASSERT(rc.isValid());
return rc;
}
static const QRegExp &windowsDeviceSubDirPattern()
{
static const QRegExp rc(QLatin1String(".*[/\\\\]CON|.*[/\\\\]AUX|.*[/\\\\]PRN|.*[/\\\\]COM1|.*[/\\\\]COM2|.*[/\\\\]LPT1|.*[/\\\\]LPT2|.*[/\\\\]NUL"),
Qt::CaseInsensitive);
Q_ASSERT(rc.isValid());
return rc;
}
// ----------- FileNameValidatingLineEdit
FileNameValidatingLineEdit::FileNameValidatingLineEdit(QWidget *parent) :
BaseValidatingLineEdit(parent)
BaseValidatingLineEdit(parent),
m_allowDirectories(false),
m_unused(0)
{
}
bool FileNameValidatingLineEdit::allowDirectories() const
{
return m_allowDirectories;
}
void FileNameValidatingLineEdit::setAllowDirectories(bool v)
{
m_allowDirectories = v;
}
/* Validate a file base name, check for forbidden characters/strings. */
static const char *notAllowedChars = "/?:&\\*\"|#%<> ";
static const char *notAllowedSubStrings[] = {".."};
#ifdef Q_OS_WIN
# define SLASHES "/\\"
#else
# define SLASHES "/"
#endif
// Naming a file like a device name will break on Windows, even if it is
// "com1.txt". Since we are cross-platform, we generally disallow such file
// names.
static const char *notAllowedStrings[] = {"CON", "AUX", "PRN", "COM1", "COM2", "LPT1", "LPT2" };
static const char *notAllowedCharsSubDir = "?:&*\"|#%<> ";
static const char *notAllowedCharsNoSubDir = "?:&*\"|#%<> "SLASHES;
bool FileNameValidatingLineEdit::validateFileName(const QString &name, QString *errorMessage /* = 0*/)
static const char *notAllowedSubStrings[] = {".."};
bool FileNameValidatingLineEdit::validateFileName(const QString &name,
bool allowDirectories,
QString *errorMessage /* = 0*/)
{
if (name.isEmpty()) {
if (errorMessage)
......@@ -60,6 +99,7 @@ bool FileNameValidatingLineEdit::validateFileName(const QString &name, QString *
return false;
}
// Characters
const char *notAllowedChars = allowDirectories ? notAllowedCharsSubDir : notAllowedCharsNoSubDir;
for (const char *c = notAllowedChars; *c; c++)
if (name.contains(QLatin1Char(*c))) {
if (errorMessage)
......@@ -76,22 +116,22 @@ bool FileNameValidatingLineEdit::validateFileName(const QString &name, QString *
return false;
}
}
// Strings
const int notAllowedStringCount = sizeof(notAllowedStrings)/sizeof(const char *);
for (int s = 0; s < notAllowedStringCount; s++) {
const QLatin1String notAllowedString(notAllowedStrings[s]);
if (name == notAllowedString) {
if (errorMessage)
*errorMessage = tr("The name must not be '%1'.").arg(QString(notAllowedString));
return false;
}
// Windows devices
bool matchesWinDevice = windowsDeviceNoSubDirPattern().exactMatch(name);
if (!matchesWinDevice && allowDirectories)
matchesWinDevice = windowsDeviceSubDirPattern().exactMatch(name);
if (matchesWinDevice) {
if (errorMessage)
*errorMessage = tr("The name must not match that of a MS Windows device. (%1).").
arg(windowsDeviceNoSubDirPattern().pattern().replace(QLatin1Char('|'), QLatin1Char(',')));
return false;
}
return true;
}
bool FileNameValidatingLineEdit::validate(const QString &value, QString *errorMessage) const
{
return validateFileName(value, errorMessage);
return validateFileName(value, m_allowDirectories, errorMessage);
}
} // namespace Utils
......
......@@ -43,14 +43,23 @@ class QWORKBENCH_UTILS_EXPORT FileNameValidatingLineEdit : public BaseValidating
{
Q_OBJECT
Q_DISABLE_COPY(FileNameValidatingLineEdit)
Q_PROPERTY(bool allowDirectories READ allowDirectories WRITE setAllowDirectories)
public:
explicit FileNameValidatingLineEdit(QWidget *parent = 0);
static bool validateFileName(const QString &name, QString *errorMessage /* = 0*/);
static bool validateFileName(const QString &name,
bool allowDirectories = false,
QString *errorMessage = 0);
bool allowDirectories() const;
void setAllowDirectories(bool v);
protected:
virtual bool validate(const QString &value, QString *errorMessage) const;
private:
bool m_allowDirectories;
void *m_unused;
};
} // namespace Utils
......
......@@ -123,7 +123,7 @@ void FileWizardPage::slotActivated()
bool FileWizardPage::validateBaseName(const QString &name, QString *errorMessage /* = 0*/)
{
return FileNameValidatingLineEdit::validateFileName(name, errorMessage);
return FileNameValidatingLineEdit::validateFileName(name, false, errorMessage);
}
} // namespace Utils
......
......@@ -346,6 +346,21 @@ void NewClassWidget::setFormExtension(const QString &e)
m_d->m_formExtension = fixSuffix(e);
}
bool NewClassWidget::allowDirectories() const
{
return m_d->m_ui.headerFileLineEdit->allowDirectories();
}
void NewClassWidget::setAllowDirectories(bool v)
{
// We keep all in sync
if (allowDirectories() != v) {
m_d->m_ui.sourceFileLineEdit->setAllowDirectories(v);
m_d->m_ui.headerFileLineEdit->setAllowDirectories(v);
m_d->m_ui.formFileLineEdit->setAllowDirectories(v);
}
}
void NewClassWidget::slotValidChanged()
{
const bool newValid = isValid();
......
......@@ -73,6 +73,7 @@ class QWORKBENCH_UTILS_EXPORT NewClassWidget : public QWidget
Q_PROPERTY(QString formExtension READ formExtension WRITE setFormExtension DESIGNABLE true)
Q_PROPERTY(bool formInputCheckable READ formInputCheckable WRITE setFormInputCheckable DESIGNABLE true)
Q_PROPERTY(bool formInputChecked READ formInputChecked WRITE setFormInputChecked DESIGNABLE true)
Q_PROPERTY(bool allowDirectories READ allowDirectories WRITE setAllowDirectories)
// Utility "USER" property for wizards containing file names.
Q_PROPERTY(QStringList files READ files DESIGNABLE false USER true)
public:
......@@ -97,7 +98,7 @@ public:
QString sourceExtension() const;
QString headerExtension() const;
QString formExtension() const;
bool allowDirectories() const;
bool isValid(QString *error = 0) const;
......@@ -125,6 +126,7 @@ public slots:
void setSourceExtension(const QString &e);
void setHeaderExtension(const QString &e);
void setFormExtension(const QString &e);
void setAllowDirectories(bool v);
/* Suggest a class name from the base class by stripping the leading 'Q'
* character. This will happen automagically if the base class combo
......
......@@ -30,6 +30,7 @@
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#ifndef PATHCHOOSER_H
#define PATHCHOOSER_H
......
......@@ -45,7 +45,7 @@ ProjectNameValidatingLineEdit::ProjectNameValidatingLineEdit(QWidget *parent)
bool ProjectNameValidatingLineEdit::validateProjectName(const QString &name, QString *errorMessage /* = 0*/)
{
// Validation is file name + checking for dots
if (!FileNameValidatingLineEdit::validateFileName(name, errorMessage))
if (!FileNameValidatingLineEdit::validateFileName(name, false, errorMessage))
return false;
// We don't want dots in the directory name for some legacy Windows
......
......@@ -125,6 +125,7 @@ struct SynchronousProcessPrivate {
SynchronousProcessResponse m_result;
int m_hangTimerCount;
int m_maxHangTimerCount;
bool m_startFailure;
ChannelBuffer m_stdOut;
ChannelBuffer m_stdErr;
......@@ -133,7 +134,8 @@ struct SynchronousProcessPrivate {
SynchronousProcessPrivate::SynchronousProcessPrivate() :
m_stdOutCodec(0),
m_hangTimerCount(0),
m_maxHangTimerCount(defaultMaxHangTimerCount)
m_maxHangTimerCount(defaultMaxHangTimerCount),
m_startFailure(false)
{
}
......@@ -143,6 +145,7 @@ void SynchronousProcessPrivate::clearForRun()
m_stdOut.clearForRun();
m_stdErr.clearForRun();
m_result.clear();
m_startFailure = false;
}
// ----------- SynchronousProcess
......@@ -221,22 +224,26 @@ SynchronousProcessResponse SynchronousProcess::run(const QString &binary,
qDebug() << '>' << Q_FUNC_INFO << binary << args;
m_d->clearForRun();
m_d->m_timer.start();
QApplication::setOverrideCursor(Qt::WaitCursor);
// On Windows, start failure is triggered immediately if the
// executable cannot be found in the path. Do not start the
// event loop in that case.
m_d->m_process.start(binary, args, QIODevice::ReadOnly);
m_d->m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
if (m_d->m_result.result == SynchronousProcessResponse::Finished || m_d->m_result.result == SynchronousProcessResponse::FinishedError) {
processStdOut(false);
processStdErr(false);
}
if (!m_d->m_startFailure) {
m_d->m_timer.start();
QApplication::setOverrideCursor(Qt::WaitCursor);
m_d->m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
if (m_d->m_result.result == SynchronousProcessResponse::Finished || m_d->m_result.result == SynchronousProcessResponse::FinishedError) {
processStdOut(false);
processStdErr(false);
}
m_d->m_result.stdOut = convertStdOut(m_d->m_stdOut.data);
m_d->m_result.stdErr = convertStdErr(m_d->m_stdErr.data);
m_d->m_result.stdOut = convertStdOut(m_d->m_stdOut.data);
m_d->m_result.stdErr = convertStdErr(m_d->m_stdErr.data);
m_d->m_timer.stop();
QApplication::restoreOverrideCursor();
m_d->m_timer.stop();
QApplication::restoreOverrideCursor();
}
if (debug)
qDebug() << '<' << Q_FUNC_INFO << binary << m_d->m_result;
......@@ -246,12 +253,14 @@ SynchronousProcessResponse SynchronousProcess::run(const QString &binary,
void SynchronousProcess::slotTimeout()
{
if (++m_d->m_hangTimerCount > m_d->m_maxHangTimerCount) {
if (debug)
qDebug() << Q_FUNC_INFO << "HANG detected, killing";
m_d->m_process.kill();
m_d->m_result.result = SynchronousProcessResponse::Hang;
} else {
if (debug)
qDebug() << Q_FUNC_INFO << m_d->m_hangTimerCount;
}
if (debug)
qDebug() << Q_FUNC_INFO << m_d->m_hangTimerCount;
}
void SynchronousProcess::finished(int exitCode, QProcess::ExitStatus e)
......@@ -265,7 +274,9 @@ void SynchronousProcess::finished(int exitCode, QProcess::ExitStatus e)
m_d->m_result.exitCode = exitCode;
break;
case QProcess::CrashExit:
m_d->m_result.result = SynchronousProcessResponse::TerminatedAbnormally;
// Was hang detected before and killed?
if (m_d->m_result.result != SynchronousProcessResponse::Hang)
m_d->m_result.result = SynchronousProcessResponse::TerminatedAbnormally;
m_d->m_result.exitCode = -1;
break;
}
......@@ -277,7 +288,10 @@ void SynchronousProcess::error(QProcess::ProcessError e)
m_d->m_hangTimerCount = 0;
if (debug)
qDebug() << Q_FUNC_INFO << e;
m_d->m_result.result = SynchronousProcessResponse::StartFailed;
// Was hang detected before and killed?
if (m_d->m_result.result != SynchronousProcessResponse::Hang)
m_d->m_result.result = SynchronousProcessResponse::StartFailed;
m_d->m_startFailure = true;
m_d->m_eventLoop.quit();
}
......
......@@ -127,6 +127,7 @@ MainWindow::MainWindow() :
m_mimeDatabase(new MimeDatabase),
m_navigationWidget(0),
m_rightPaneWidget(0),
m_versionDialog(0),
m_activeContext(0),
m_pluginManager(0),
m_outputPane(new OutputPane(m_globalContext)),
......@@ -1085,8 +1086,20 @@ void MainWindow::openRecentFile()
void MainWindow::aboutQtCreator()
{
VersionDialog versionDialog(this);
versionDialog.exec();
if (!m_versionDialog) {
m_versionDialog = new VersionDialog(this);
connect(m_versionDialog, SIGNAL(finished(int)),
this, SLOT(destroyVersionDialog()));
}
m_versionDialog->show();
}
void MainWindow::destroyVersionDialog()
{
if (m_versionDialog) {
m_versionDialog->deleteLater();
m_versionDialog = 0;
}
}
void MainWindow::aboutPlugins()
......
......@@ -83,6 +83,7 @@ class OutputPane;
class ProgressManager;
class ShortcutSettings;
class ViewManager;
class VersionDialog;
class CORE_EXPORT MainWindow : public QMainWindow
{
......@@ -160,6 +161,7 @@ private slots:
void aboutPlugins();
void updateFocusWidget(QWidget *old, QWidget *now);
void toggleNavigation();
void destroyVersionDialog();
private:
void updateContextObject(IContext *context);
......@@ -190,6 +192,7 @@ private:
NavigationWidget *m_navigationWidget;
RightPaneWidget *m_rightPaneWidget;
Core::BaseView *m_outputView;
VersionDialog *m_versionDialog;
IContext * m_activeContext;
......
......@@ -73,6 +73,7 @@ ClassNamePage::ClassNamePage(const QString &sourceSuffix,
m_newClassWidget->setBaseClassEditable(true);
m_newClassWidget->setFormInputVisible(false);
m_newClassWidget->setNamespacesEnabled(true);
m_newClassWidget->setAllowDirectories(true);
connect(m_newClassWidget, SIGNAL(validChanged()),
this, SLOT(slotValidChanged()));
......
......@@ -206,6 +206,7 @@ void CPPEditor::createToolBar(CPPEditorEditable *editable)
connect(m_methodCombo, SIGNAL(activated(int)), this, SLOT(jumpToMethod(int)));
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateMethodBoxIndex()));
connect(m_methodCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMethodBoxToolTip()));
connect(file(), SIGNAL(changed()), this, SLOT(updateFileName()));
......@@ -355,10 +356,16 @@ void CPPEditor::updateMethodBoxIndex()
if (lastIndex.isValid()) {
bool blocked = m_methodCombo->blockSignals(true);
m_methodCombo->setCurrentIndex(lastIndex.row());
updateMethodBoxToolTip();
(void) m_methodCombo->blockSignals(blocked);
}