Commit 685a23b5 authored by Kai Koehne's avatar Kai Koehne
Browse files

Merge branch 'master' of git@scm.dev.nokia.troll.no:creator/mainline

parents 2839fdf6 5a8b61b2
......@@ -844,6 +844,26 @@ static void qDumpUnknown(QDumper &d, const char *why = 0)
d.disarm();
}
static inline void dumpStdStringValue(QDumper &d, const std::string &str)
{
d.beginItem("value");
d.putBase64Encoded(str.c_str(), str.size());
d.endItem();
d.putItem("valueencoded", "1");
d.putItem("type", "std::string");
d.putItem("numchild", "0");
}
static inline void dumpStdWStringValue(QDumper &d, const std::wstring &str)
{
d.beginItem("value");
d.putBase64Encoded((const char *)str.c_str(), str.size() * sizeof(wchar_t));
d.endItem();
d.putItem("valueencoded", (sizeof(wchar_t) == 2 ? "2" : "3"));
d.putItem("type", "std::wstring");
d.putItem("numchild", "0");
}
static void qDumpInnerValueHelper(QDumper &d, const char *type, const void *addr,
const char *field = "value")
{
......@@ -928,6 +948,16 @@ static void qDumpInnerValueHelper(QDumper &d, const char *type, const void *addr
d.putItem(field, *(QString*)addr);
}
return;
case 't':
if (isEqual(type, "std::string")
|| isEqual(type, "std::basic_string<char,std::char_traits<char>,std::allocator<char> >")) {
d.putCommaIfNeeded();
dumpStdStringValue(d, *reinterpret_cast<const std::string*>(addr));
} else if (isEqual(type, "std::wstring")
|| isEqual(type, "std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >")) {
dumpStdWStringValue(d, *reinterpret_cast<const std::wstring*>(addr));
}
return;
default:
return;
}
......@@ -944,7 +974,6 @@ static void qDumpInnerValue(QDumper &d, const char *type, const void *addr)
qDumpInnerValueHelper(d, type, addr);
}
static void qDumpInnerValueOrPointer(QDumper &d,
const char *type, const char *strippedtype, const void *addr)
{
......@@ -2753,37 +2782,28 @@ static void qDumpStdString(QDumper &d)
{
const std::string &str = *reinterpret_cast<const std::string *>(d.data);
if (!str.empty()) {
const std::string::size_type size = str.size();
if (int(size) < 0)
return;
if (size) {
qCheckAccess(str.c_str());
qCheckAccess(str.c_str() + str.size() - 1);
qCheckAccess(str.c_str() + size - 1);
}
d.beginItem("value");
d.putBase64Encoded(str.c_str(), str.size());
d.endItem();
d.putItem("valueencoded", "1");
d.putItem("type", "std::string");
d.putItem("numchild", "0");
dumpStdStringValue(d, str);
d.disarm();
}
static void qDumpStdWString(QDumper &d)
{
const std::wstring &str = *reinterpret_cast<const std::wstring *>(d.data);
if (!str.empty()) {
const std::wstring::size_type size = str.size();
if (int(size) < 0)
return;
if (size) {
qCheckAccess(str.c_str());
qCheckAccess(str.c_str() + str.size() - 1);
qCheckAccess(str.c_str() + size - 1);
}
d.beginItem("value");
d.putBase64Encoded((const char *)str.c_str(), str.size() * sizeof(wchar_t));
d.endItem();
d.putItem("valueencoded", (sizeof(wchar_t) == 2 ? "2" : "3"));
d.putItem("type", "std::wstring");
d.putItem("numchild", "0");
dumpStdWStringValue(d, str);
d.disarm();
}
......@@ -3164,6 +3184,8 @@ void *qDumpObjectData440(
.put("std::string=\"").put(sizeof(std::string)).put("\",")
.put("std::wstring=\"").put(sizeof(std::wstring)).put("\",")
.put("std::allocator=\"").put(sizeof(std::allocator<int>)).put("\",")
.put("std::char_traits<char>=\"").put(sizeof(std::char_traits<char>)).put("\",")
.put("std::char_traits<unsigned short>=\"").put(sizeof(std::char_traits<unsigned short>)).put("\",")
#if QT_VERSION >= 0x040500
.put(NS"QSharedPointer=\"").put(sizeof(QSharedPointer<int>)).put("\",")
.put(NS"QSharedDataPointer=\"").put(sizeof(QSharedDataPointer<QSharedData>)).put("\",")
......
......@@ -256,6 +256,18 @@ static int dumpStdStringVector()
return 0;
}
static int dumpStdWStringVector()
{
std::vector<std::wstring> test;
test.push_back(L"item1");
test.push_back(L"item2");
prepareInBuffer("std::vector", "local.wstringvector", "local.wstringvector", "std::wstring");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::wstring), sizeof(std::list<int>::allocator_type), 0, 0);
fputs(qDumpOutBuffer, stdout);
fputc('\n', stdout);
return 0;
}
static int dumpStdIntSet()
{
std::set<int> test;
......@@ -335,6 +347,8 @@ static bool dumpType(const char *arg)
{ dumpStdIntVector(); return true; }
if (!qstrcmp(arg, "vector<string>"))
{ dumpStdStringVector(); return true; }
if (!qstrcmp(arg, "vector<wstring>"))
{ dumpStdWStringVector(); return true; }
if (!qstrcmp(arg, "set<int>"))
{ dumpStdIntSet(); return true; }
if (!qstrcmp(arg, "set<string>"))
......
......@@ -1421,6 +1421,8 @@ bool Preprocessor::isQtReservedWord(const QByteArray &macroId) const
const int size = macroId.size();
if (size == 9 && macroId.at(0) == 'Q' && macroId == "Q_SIGNALS")
return true;
else if (size == 9 && macroId.at(0) == 'Q' && macroId == "Q_FOREACH")
return true;
else if (size == 7 && macroId.at(0) == 'Q' && macroId == "Q_SLOTS")
return true;
else if (size == 8 && macroId.at(0) == 'Q' && macroId == "Q_SIGNAL")
......@@ -1433,6 +1435,8 @@ bool Preprocessor::isQtReservedWord(const QByteArray &macroId) const
return true;
else if (size == 7 && macroId.at(0) == 's' && macroId == "signals")
return true;
else if (size == 7 && macroId.at(0) == 'f' && macroId == "foreach")
return true;
else if (size == 5 && macroId.at(0) == 's' && macroId == "slots")
return true;
return false;
......
......@@ -82,7 +82,6 @@ CMakeOpenProjectWizard::CMakeOpenProjectWizard(CMakeManager *cmakeManager, const
setPage(InSourcePageId, new InSourceBuildPage(this));
setPage(ShadowBuildPageId, new ShadowBuildPage(this));
setPage(XmlFileUpToDatePageId, new XmlFileUpToDatePage(this));
setPage(CMakeRunPageId, new CMakeRunPage(this));
setStartId(startid);
......@@ -137,15 +136,9 @@ int CMakeOpenProjectWizard::nextId() const
return QWizard::nextId();
int cid = currentId();
if (cid == InSourcePageId) {
if (existsUpToDateXmlFile())
return XmlFileUpToDatePageId;
else
return CMakeRunPageId;
return CMakeRunPageId;
} else if (cid == ShadowBuildPageId) {
if (existsUpToDateXmlFile())
return XmlFileUpToDatePageId;
else
return CMakeRunPageId;
return CMakeRunPageId;
}
return -1;
}
......@@ -227,18 +220,6 @@ InSourceBuildPage::InSourceBuildPage(CMakeOpenProjectWizard *cmakeWizard)
}
XmlFileUpToDatePage::XmlFileUpToDatePage(CMakeOpenProjectWizard *cmakeWizard)
: QWizardPage(cmakeWizard), m_cmakeWizard(cmakeWizard)
{
setLayout(new QVBoxLayout);
QLabel *label = new QLabel(this);
label->setWordWrap(true);
label->setText(tr("Qt Creator has found a recent cbp file, which Qt Creator will parse to gather information about the project. "
"You can change the command line arguments used to create this file in the project mode. "
"Click finish to load the project."));
layout()->addWidget(label);
}
ShadowBuildPage::ShadowBuildPage(CMakeOpenProjectWizard *cmakeWizard, bool change)
: QWizardPage(cmakeWizard), m_cmakeWizard(cmakeWizard)
{
......@@ -313,10 +294,19 @@ void CMakeRunPage::initWidgets()
void CMakeRunPage::initializePage()
{
if (m_mode == Initial) {
m_complete = m_cmakeWizard->existsUpToDateXmlFile();
m_buildDirectory = m_cmakeWizard->buildDirectory();
m_descriptionLabel->setText(
tr("The directory %1 does not contain a cbp file. Qt Creator needs to create this file by running cmake. "
"Some projects require command line arguments to the initial cmake call.").arg(m_buildDirectory));
if (m_cmakeWizard->existsUpToDateXmlFile()) {
m_descriptionLabel->setText(
tr("The directoyr %1 already contains a cbp file, which is recent enough. "
"You can pass special arguments or change the used toolchain here and rerun cmake. "
"Or simply finish the wizard directly").arg(m_buildDirectory));
} else {
m_descriptionLabel->setText(
tr("The directory %1 does not contain a cbp file. Qt Creator needs to create this file by running cmake. "
"Some projects require command line arguments to the initial cmake call.").arg(m_buildDirectory));
}
} else if (m_mode == CMakeRunPage::Update) {
m_descriptionLabel->setText(tr("The directory %1 contains an outdated .cbp file. Qt "
"Creator needs to update this file by running cmake. "
......
......@@ -58,7 +58,6 @@ public:
enum PageId {
InSourcePageId,
ShadowBuildPageId,
XmlFileUpToDatePageId,
CMakeRunPageId
};
......@@ -85,9 +84,9 @@ public:
ProjectExplorer::Environment environment() const;
QString msvcVersion() const;
void setMsvcVersion(const QString &version);
bool existsUpToDateXmlFile() const;
private:
void init();
bool existsUpToDateXmlFile() const;
bool hasInSourceBuild() const;
CMakeManager *m_cmakeManager;
QString m_buildDirectory;
......@@ -107,17 +106,6 @@ private:
CMakeOpenProjectWizard *m_cmakeWizard;
};
class XmlFileUpToDatePage : public QWizardPage
{
Q_OBJECT
public:
XmlFileUpToDatePage(CMakeOpenProjectWizard *cmakeWizard);
private:
CMakeOpenProjectWizard *m_cmakeWizard;
};
class ShadowBuildPage : public QWizardPage
{
Q_OBJECT
......
......@@ -544,12 +544,23 @@ static inline QString msgDumpFailed(const WatchData &wd, const QString *why)
return QString::fromLatin1("Unable to dump '%1' (%2): %3").arg(wd.name, wd.type, *why);
}
static inline QString msgNotHandled(const QString &type)
{
return QString::fromLatin1("The type '%1' is not handled.").arg(type);
}
CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool dumpChildren, int source,
QList<WatchData> *result, QString *errorMessage)
{
// Check failure cache and supported types
if (m_state == Disabled || m_failedTypes.contains(wd.type))
if (m_state == Disabled) {
*errorMessage = QLatin1String("Dumpers are disabled");
return DumpNotHandled;
}
if (m_failedTypes.contains(wd.type)) {
*errorMessage = msgNotHandled(wd.type);
return DumpNotHandled;
}
// Ensure types are parsed and known.
if (!ensureInitialized(errorMessage)) {
......@@ -562,8 +573,10 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool
const QtDumperHelper::TypeData td = m_helper.typeData(wd.type);
if (loadDebug)
qDebug() << "dumpType" << wd.type << td;
if (td.type == QtDumperHelper::UnknownType)
if (td.type == QtDumperHelper::UnknownType) {
*errorMessage = msgNotHandled(wd.type);
return DumpNotHandled;
}
// Now evaluate
const QString message = QCoreApplication::translate("Debugger::Internal::CdbDumperHelper",
......
......@@ -257,7 +257,7 @@ bool CdbStackFrameContext::completeData(const WatchData &incompleteLocal,
foreach(const WatchData &dwd, dumperResult)
wh->insertData(dwd);
} else {
const QString msg = QString::fromLatin1("Unable to further expand dumper watch data: %1 (%2): %3/%4").arg(incompleteLocal.name, incompleteLocal.type).arg(int(dr)).arg(*errorMessage);
const QString msg = QString::fromLatin1("Unable to further expand dumper watch data: '%1' (%2): %3/%4").arg(incompleteLocal.name, incompleteLocal.type).arg(int(dr)).arg(*errorMessage);
qWarning("%s", qPrintable(msg));
WatchData wd = incompleteLocal;
wd.setAllUnneeded();
......
......@@ -144,7 +144,7 @@ void ToolTipWidget::done()
}
void ToolTipWidget::run(const QPoint &point, QAbstractItemModel *model,
const QModelIndex &index, const QString &msg)
const QModelIndex &index, const QString & /* msg */)
{
move(point);
setModel(model);
......
......@@ -390,9 +390,29 @@ static QString chopConst(QString type)
return type;
}
QString niceType(QString type)
static inline QRegExp stdStringRegExp(const QString &charType)
{
type.replace('*', '@');
QString rc = QLatin1String("basic_string<");
rc += charType;
rc += QLatin1String(",[ ]?std::char_traits<");
rc += charType;
rc += QLatin1String(">,[ ]?std::allocator<");
rc += charType;
rc += QLatin1String("> >");
const QRegExp re(rc);
Q_ASSERT(re.isValid());
return re;
}
QString niceType(const QString typeIn)
{
static QMap<QString, QString> cache;
const QMap<QString, QString>::const_iterator it = cache.constFind(typeIn);
if (it != cache.constEnd()) {
return it.value();
}
QString type = typeIn;
type.replace(QLatin1Char('*'), QLatin1Char('@'));
for (int i = 0; i < 10; ++i) {
int start = type.indexOf("std::allocator<");
......@@ -414,33 +434,37 @@ QString niceType(QString type)
QString alloc = type.mid(start, pos + 1 - start).trimmed();
QString inner = alloc.mid(15, alloc.size() - 16).trimmed();
if (inner == QLatin1String("char"))
// std::string
type.replace(QLatin1String("basic_string<char, std::char_traits<char>, "
"std::allocator<char> >"), QLatin1String("string"));
else if (inner == QLatin1String("wchar_t"))
// std::wstring
type.replace(QLatin1String("basic_string<wchar_t, std::char_traits<wchar_t>, "
"std::allocator<wchar_t> >"), QLatin1String("wstring"));
if (inner == QLatin1String("char")) { // std::string
static const QRegExp stringRegexp = stdStringRegExp(inner);
type.replace(stringRegexp, QLatin1String("string"));
} else if (inner == QLatin1String("wchar_t")) { // std::wstring
static const QRegExp wchartStringRegexp = stdStringRegExp(inner);
type.replace(wchartStringRegexp, QLatin1String("wstring"));
} else if (inner == QLatin1String("unsigned short")) { // std::wstring/MSVC
static const QRegExp usStringRegexp = stdStringRegExp(inner);
type.replace(usStringRegexp, QLatin1String("wstring"));
}
// std::vector, std::deque, std::list
QRegExp re1(QString("(vector|list|deque)<%1, %2\\s*>").arg(inner, alloc));
static const QRegExp re1(QString::fromLatin1("(vector|list|deque)<%1,[ ]?%2\\s*>").arg(inner, alloc));
Q_ASSERT(re1.isValid());
if (re1.indexIn(type) != -1)
type.replace(re1.cap(0), QString("%1<%2>").arg(re1.cap(1), inner));
type.replace(re1.cap(0), QString::fromLatin1("%1<%2>").arg(re1.cap(1), inner));
// std::stack
QRegExp re6(QString("stack<%1, std::deque<%2> >").arg(inner, inner));
re6.setMinimal(true);
static QRegExp re6(QString::fromLatin1("stack<%1,[ ]?std::deque<%2> >").arg(inner, inner));
if (!re6.isMinimal())
re6.setMinimal(true);
Q_ASSERT(re6.isValid());
if (re6.indexIn(type) != -1)
type.replace(re6.cap(0), QString("stack<%1>").arg(inner));
type.replace(re6.cap(0), QString::fromLatin1("stack<%1>").arg(inner));
// std::set
QRegExp re4(QString("set<%1, std::less<%2>, %3\\s*>").arg(inner, inner, alloc));
re4.setMinimal(true);
static QRegExp re4(QString::fromLatin1("set<%1,[ ]?std::less<%2>,[ ]?%3\\s*>").arg(inner, inner, alloc));
if (!re4.isMinimal())
re4.setMinimal(true);
Q_ASSERT(re4.isValid());
if (re4.indexIn(type) != -1)
type.replace(re4.cap(0), QString("set<%1>").arg(inner));
type.replace(re4.cap(0), QString::fromLatin1("set<%1>").arg(inner));
// std::map
if (inner.startsWith("std::pair<")) {
......@@ -460,25 +484,46 @@ QString niceType(QString type)
QString key = chopConst(ckey);
QString value = inner.mid(pos + 2, inner.size() - 3 - pos);
QRegExp re5(QString("map<%1, %2, std::less<%3>, %4\\s*>")
static QRegExp re5(QString("map<%1,[ ]?%2,[ ]?std::less<%3>,[ ]?%4\\s*>")
.arg(key, value, key, alloc));
re5.setMinimal(true);
if (!re5.isMinimal())
re5.setMinimal(true);
Q_ASSERT(re5.isValid());
if (re5.indexIn(type) != -1)
type.replace(re5.cap(0), QString("map<%1, %2>").arg(key, value));
else {
QRegExp re7(QString("map<const %1, %2, std::less<const %3>, %4\\s*>")
static QRegExp re7(QString("map<const %1,[ ]?%2,[ ]?std::less<const %3>,[ ]?%4\\s*>")
.arg(key, value, key, alloc));
re7.setMinimal(true);
if (!re7.isMinimal())
re7.setMinimal(true);
if (re7.indexIn(type) != -1)
type.replace(re7.cap(0), QString("map<const %1, %2>").arg(key, value));
}
}
}
type.replace('@', '*');
type.replace(QLatin1Char('@'), QLatin1Char('*'));
type.replace(QLatin1String(" >"), QString(QLatin1Char('>')));
cache.insert(typeIn, type); // For simplicity, also cache unmodified types
return type;
}
static QString formattedValue(const WatchData &data,
int individualFormat, int typeFormat)
{
if (isIntType(data.type)) {
int format = individualFormat == -1 ? typeFormat : individualFormat;
int value = data.value.toInt();
if (format == 1)
return ("(hex) ") + QString::number(value, 16);
if (format == 2)
return ("(bin) ") + QString::number(value, 2);
if (format == 3)
return ("(oct) ") + QString::number(value, 8);
}
return data.value;
}
bool WatchModel::canFetchMore(const QModelIndex &index) const
{
return index.isValid() && !watchItem(index)->fetchTriggered;
......@@ -573,6 +618,18 @@ QModelIndex WatchModel::watchIndexHelper(const WatchItem *needle,
return QModelIndex();
}
void WatchModel::emitDataChanged(int column, const QModelIndex &parentIndex)
{
QModelIndex idx1 = index(0, column, parentIndex);
QModelIndex idx2 = index(rowCount(parentIndex) - 1, column, parentIndex);
if (idx1.isValid() && idx2.isValid())
emit dataChanged(idx1, idx2);
//qDebug() << "CHANGING:\n" << idx1 << "\n" << idx2 << "\n"
// << data(parentIndex, INameRole).toString();
for (int i = rowCount(parentIndex); --i >= 0; )
emitDataChanged(column, index(i, 0, parentIndex));
}
QVariant WatchModel::data(const QModelIndex &idx, int role) const
{
const WatchItem &data = *watchItem(idx);
......@@ -581,7 +638,9 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
case Qt::DisplayRole: {
switch (idx.column()) {
case 0: return data.name;
case 1: return data.value;
case 1: return formattedValue(data,
m_handler->m_individualFormats[data.iname],
m_handler->m_typeFormats[data.type]);
case 2: return niceType(data.type);
default: break;
}
......@@ -616,7 +675,23 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
case ActiveDataRole:
qDebug() << "ASK FOR" << data.iname;
return true;
case TypeFormatListRole:
if (isIntType(data.type))
return QStringList() << tr("decimal") << tr("hexadecimal")
<< tr("binary") << tr("octal");
break;
case TypeFormatRole:
return m_handler->m_typeFormats[data.type];
case IndividualFormatRole: {
int format = m_handler->m_individualFormats[data.iname];
if (format == -1)
return m_handler->m_typeFormats[data.type];
return format;
}
default:
break;
}
......@@ -625,12 +700,16 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
WatchItem &data = *watchItem(index);
if (role == ExpandedRole) {
QString iname = data(index, INameRole).toString();
if (value.toBool())
m_handler->m_expandedINames.insert(iname);
m_handler->m_expandedINames.insert(data.iname);
else
m_handler->m_expandedINames.remove(iname);
m_handler->m_expandedINames.remove(data.iname);
} else if (role == TypeFormatRole) {
m_handler->setFormat(data.type, value.toInt());
} else if (role == IndividualFormatRole) {
m_handler->m_individualFormats[data.iname] = value.toInt();
}
emit dataChanged(index, index);
return true;
......@@ -773,66 +852,6 @@ void WatchHandler::endCycle()
m_locals->removeOutdated();
m_watchers->removeOutdated();
m_tooltips->removeOutdated();
/*
if (m_inChange) {
MODEL_DEBUG("RECREATE MODEL IGNORED, CURRENT SET:\n" << toString());
return;
}
#ifdef DEBUG_PENDING
MODEL_DEBUG("RECREATE MODEL, CURRENT SET:\n" << toString());
#endif
QHash<QString, int> oldTopINames;
QHash<QString, QString> oldValues;
for (int i = 0, n = m_oldSet.size(); i != n; ++i) {
WatchData &data = m_oldSet[i];
oldValues[data.iname] = data.value;
if (data.level == 2)
++oldTopINames[data.iname];
}
#ifdef DEBUG_PENDING
MODEL_DEBUG("OLD VALUES: " << oldValues);
#endif
for (int i = m_completeSet.size(); --i >= 0; ) {
WatchData &data = m_completeSet[i];
data.level = data.iname.isEmpty() ? 0 : data.iname.count('.') + 1;
data.childIndex.clear();
}
qSort(m_completeSet.begin(), m_completeSet.end(), &iNameSorter);
// Possibly append dummy items to prevent empty views
bool ok = true;
if (ok) {
for (int i = 1; i <= 3; ++i) {
WatchData &data = m_displaySet[i];
if (data.childIndex.size() == 0) {
WatchData dummy;
dummy.state = 0;
dummy.row = 0;
if (i == 1) {
dummy.iname = QLatin1String("local.dummy");
dummy.name = tr("<No Locals>");
} else if (i == 2) {
dummy.iname = QLatin1String("tooltip.dummy");
dummy.name = tr("<No Tooltip>");
} else {