Commit abdf35a8 authored by Erik Verbruggen's avatar Erik Verbruggen
Browse files

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

parents 71549ec6 1a0134a9
......@@ -5,7 +5,7 @@
\title Qt Creator Manual
\section1 Version 1.2.80
\section1 Version 1.2.91
The goal of Qt Creator is to provide a cross-platform, complete Integrated
Development Environment (IDE) to develop Qt projects. It is available for
......@@ -1786,7 +1786,7 @@
There are some known issues with Qt Creator.
The development team is aware of those, there is no need to report them as bug.
\section1 Known Issues of Version 1.2.80
\section1 Known Issues of Version 1.2.91
\list
\o Gdb on Windows may not work if the 'Embassy \reg Security Center' software
......
......@@ -19,16 +19,16 @@ sources.fileextensions = "qtcreator.qdoc addressbook-sdk.qdoc"
qhp.projects = QtCreator
qhp.QtCreator.file = qtcreator.qhp
qhp.QtCreator.namespace = com.nokia.qtcreator.1280
qhp.QtCreator.namespace = com.nokia.qtcreator.1291
qhp.QtCreator.virtualFolder = doc
qhp.QtCreator.indexTitle = Qt Creator
qhp.QtCreator.indexRoot =
qhp.QtCreator.extraFiles = classic.css \
images/qt-logo.png \
images/qtcreator-screenshots.png
qhp.QtCreator.filterAttributes = qtcreator 1.2.80
qhp.QtCreator.customFilters.QtCreator.name = Qt Creator 1.2.80
qhp.QtCreator.customFilters.QtCreator.filterAttributes = qtcreator 1.2.80
qhp.QtCreator.filterAttributes = qtcreator 1.2.91
qhp.QtCreator.customFilters.QtCreator.name = Qt Creator 1.2.91
qhp.QtCreator.customFilters.QtCreator.filterAttributes = qtcreator 1.2.91
# macros.qdocconf
......@@ -211,5 +211,5 @@ HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \
"<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \
"<td width=\"40%\" align=\"left\">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies)</td>\n" \
"<td width=\"20%\" align=\"center\"><a href=\"trademarks.html\">Trademarks</a></td>\n" \
"<td width=\"40%\" align=\"right\"><div align=\"right\">Qt Creator 1.2.80</div></td>\n" \
"<td width=\"40%\" align=\"right\"><div align=\"right\">Qt Creator 1.2.91</div></td>\n" \
"</tr></table></div></address>"
......@@ -184,8 +184,8 @@
<key>CFBundleIdentifier</key>
<string>com.nokia.qtcreator</string>
<key>CFBundleVersion</key>
<string>1.2.80</string>
<string>1.2.91</string>
<key>CFBundleShortVersionString</key>
<string>1.2.80</string>
<string>1.2.91</string>
</dict>
</plist>
......@@ -17,7 +17,7 @@ win32 {
} else:macx {
CONFIG(debug, debug|release):LIBS *= -lExtensionSystem_debug -lAggregation_debug
else:LIBS *= -lExtensionSystem -lAggregation
LIBS += -framework CoreFoundation
ICON = qtcreator.icns
QMAKE_INFO_PLIST = Info.plist
FILETYPES.files = profile.icns prifile.icns
......
......@@ -48,6 +48,20 @@
#ifdef Q_OS_MAC
# include <sys/resource.h>
# include <CoreFoundation/CoreFoundation.h>
// Helper function CoreFoundation -> Qt
static QString stringFromCFString(CFStringRef value) {
QString retVal;
CFIndex maxLength = 2 * CFStringGetLength(value) + 1/*zero term*/; // max UTF8
char *cstring = new char[maxLength];
if (CFStringGetCString(CFStringRef(value), cstring, maxLength, kCFStringEncodingUTF8)) {
retVal = QString::fromUtf8(cstring);
}
delete cstring;
return retVal;
}
#endif
enum { OptionIndent = 4, DescriptionIndent = 24 };
......@@ -216,7 +230,29 @@ int main(int argc, char **argv)
QTranslator translator;
QTranslator qtTranslator;
const QString &locale = QLocale::system().name();
QString locale = QLocale::system().name();
#ifdef Q_OS_MAC
// because QLocale's system locale is basically useless on the Mac.
// Try to get the real system setting via core foundation
CFLocaleRef maclocale = CFLocaleCopyCurrent();
CFTypeRef value = CFLocaleGetValue(maclocale, kCFLocaleLanguageCode);
QString preferredLanguage = stringFromCFString(CFStringRef(value));
if (!preferredLanguage.isEmpty())
locale = preferredLanguage;
CFRelease(maclocale);
CFArrayRef languages = (CFArrayRef)CFPreferencesCopyValue(
CFSTR("AppleLanguages"),
kCFPreferencesAnyApplication,
kCFPreferencesCurrentUser,
kCFPreferencesAnyHost);
// CFShow(languages);
if (CFArrayGetCount(languages) > 0) {
QString preferredLanguage = stringFromCFString(CFStringRef(CFArrayGetValueAtIndex(languages, 0)));
if (!preferredLanguage.isEmpty())
locale = preferredLanguage;
}
CFRelease(languages);
#endif
const QString &creatorTrPath = QCoreApplication::applicationDirPath()
+ QLatin1String(SHARE_PATH "/translations");
if (translator.load(QLatin1String("qtcreator_") + locale, creatorTrPath)) {
......
<plugin name="BinEditor" version="1.2.80" compatVersion="1.2.80">
<plugin name="BinEditor" version="1.2.91" compatVersion="1.2.91">
<vendor>Nokia Corporation</vendor>
<copyright>(C) 2008-2009 Nokia Corporation</copyright>
<license>
......@@ -19,7 +19,7 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.</license>
<description>Binary editor component.</description>
<url>http://qt.nokia.com</url>
<dependencyList>
<dependency name="Core" version="1.2.80"/>
<dependency name="TextEditor" version="1.2.80"/>
<dependency name="Core" version="1.2.91"/>
<dependency name="TextEditor" version="1.2.91"/>
</dependencyList>
</plugin>
......@@ -33,6 +33,9 @@
#include <texteditor/texteditorconstants.h>
#include <QtCore/QByteArrayMatcher>
#include <QtCore/QFile>
#include <QtCore/QTemporaryFile>
#include <QtGui/QApplication>
#include <QtGui/QClipboard>
#include <QtGui/QFontMetrics>
......@@ -77,6 +80,7 @@ BinEditor::BinEditor(QWidget *parent)
{
m_ieditor = 0;
m_inLazyMode = false;
m_baseAddr = 0;
m_blockSize = 4096;
init();
m_unmodifiedState = 0;
......@@ -88,7 +92,7 @@ BinEditor::BinEditor(QWidget *parent)
m_cursorVisible = false;
m_caseSensitiveSearch = false;
setFocusPolicy(Qt::WheelFocus);
m_addressString = QString(9, QLatin1Char(':'));
m_addressString = QString(16 + 3, QLatin1Char(':'));
}
BinEditor::~BinEditor()
......@@ -108,7 +112,7 @@ void BinEditor::init()
m_numVisibleLines = viewport()->height() / m_lineHeight;
m_textWidth = 16 * m_charWidth + m_charWidth;
int m_numberWidth = fm.width(QChar(QLatin1Char('9')));
m_labelWidth = 8 * m_numberWidth + 2 * m_charWidth;
m_labelWidth = 16 * m_numberWidth + 4 * m_charWidth;
int expectedCharWidth = m_columnWidth / 3;
const char *hex = "0123456789abcdef";
......@@ -129,13 +133,19 @@ void BinEditor::init()
}
void BinEditor::addLazyData(int block, const QByteArray &data)
void BinEditor::addLazyData(quint64 block, const QByteArray &data)
{
Q_ASSERT(m_inLazyMode);
Q_ASSERT(data.size() == m_blockSize);
m_lazyData.insert(block, data);
m_lazyRequests.remove(block);
viewport()->update();
const quint64 addr = block * m_blockSize;
if (addr >= m_baseAddr && addr <= m_baseAddr + m_size - 1) {
if (m_lazyData.size() * m_blockSize >= 64 * 1024 * 1024)
m_lazyData.clear();
const int translatedBlock = (addr - m_baseAddr) / m_blockSize;
m_lazyData.insert(translatedBlock, data);
m_lazyRequests.remove(translatedBlock);
viewport()->update();
}
}
bool BinEditor::requestDataAt(int pos, bool synchronous) const
......@@ -144,11 +154,15 @@ bool BinEditor::requestDataAt(int pos, bool synchronous) const
return true;
int block = pos / m_blockSize;
QMap<int, QByteArray>::const_iterator it = m_lazyData.find(block);
QMap<int, QByteArray>::const_iterator it = m_modifiedData.find(block);
if (it != m_modifiedData.constEnd())
return true;
it = m_lazyData.find(block);
if (it == m_lazyData.end()) {
if (!m_lazyRequests.contains(block)) {
m_lazyRequests.insert(block);
emit const_cast<BinEditor*>(this)->lazyDataRequested(block, synchronous);
emit const_cast<BinEditor*>(this)->
lazyDataRequested(m_baseAddr / m_blockSize + block, synchronous);
if (!m_lazyRequests.contains(block))
return true; // synchronous data source
}
......@@ -162,10 +176,8 @@ char BinEditor::dataAt(int pos) const
{
if (!m_inLazyMode)
return m_data.at(pos);
int block = pos / m_blockSize;
return m_lazyData.value(block, m_emptyBlock).at(pos - (block*m_blockSize));
return blockData(block).at(pos - (block*m_blockSize));
}
void BinEditor::changeDataAt(int pos, char c)
......@@ -175,8 +187,17 @@ void BinEditor::changeDataAt(int pos, char c)
return;
}
int block = pos / m_blockSize;
if (m_lazyData.contains(block))
m_lazyData[block][pos - (block*m_blockSize)] = c;
QMap<int, QByteArray>::iterator it = m_modifiedData.find(block);
if (it != m_modifiedData.end()) {
it.value()[pos - (block*m_blockSize)] = c;
} else {
it = m_lazyData.find(block);
if (it != m_lazyData.end()) {
QByteArray data = it.value();
data[pos - (block*m_blockSize)] = c;
m_modifiedData.insert(block, data);
}
}
}
QByteArray BinEditor::dataMid(int from, int length) const
......@@ -189,7 +210,7 @@ QByteArray BinEditor::dataMid(int from, int length) const
QByteArray data;
do {
data += m_lazyData.value(block++, m_emptyBlock);
data += blockData(block++);
} while (block * m_blockSize < end);
return data.mid(from - ((from / m_blockSize) * m_blockSize), length);
......@@ -203,7 +224,9 @@ QByteArray BinEditor::blockData(int block) const
data.resize(m_blockSize);
return data;
}
return m_lazyData.value(block, m_emptyBlock);
QMap<int, QByteArray>::const_iterator it = m_modifiedData.find(block);
return it != m_modifiedData.constEnd()
? it.value() : m_lazyData.value(block, m_emptyBlock);
}
......@@ -294,7 +317,9 @@ bool BinEditor::isReadOnly() const
void BinEditor::setData(const QByteArray &data)
{
m_inLazyMode = false;
m_baseAddr = 0;
m_lazyData.clear();
m_modifiedData.clear();
m_lazyRequests.clear();
m_data = data;
m_size = data.size();
......@@ -316,21 +341,49 @@ QByteArray BinEditor::data() const
return m_data;
}
bool BinEditor::applyModifications(QByteArray &data) const
bool BinEditor::save(const QString &oldFileName, const QString &newFileName)
{
if (!m_inLazyMode) {
data = m_data;
return true;
}
if (data.size() != m_size)
return false;
for (QMap<int,QByteArray>::const_iterator it = m_lazyData.begin(); it != m_lazyData.end(); ++it) {
::memcpy(data.data() + it.key() * m_blockSize, it->constData(), m_blockSize);
if (m_inLazyMode) {
if (oldFileName != newFileName) {
QString tmpName;
{
QTemporaryFile tmp;
if (!tmp.open())
return false;
tmpName = tmp.fileName();
}
if (!QFile::copy(oldFileName, tmpName))
return false;
if (QFile::exists(newFileName) && !QFile::remove(newFileName))
return false;
if (!QFile::rename(tmpName, newFileName))
return false;
}
QFile output(newFileName);
if (!output.open(QIODevice::ReadWrite)) // QtBug: WriteOnly truncates.
return false;
const qint64 size = output.size();
for (QMap<int, QByteArray>::const_iterator it = m_modifiedData.constBegin();
it != m_modifiedData.constEnd(); ++it) {
if (!output.seek(it.key() * m_blockSize))
return false;
if (output.write(it.value()) < m_blockSize)
return false;
}
if (size % m_blockSize != 0 && !output.resize(size))
return false;
} else {
QFile output(newFileName);
if (!output.open(QIODevice::WriteOnly | QIODevice::Truncate))
return false;
if (output.write(m_data) < m_size)
return false;
}
setModified(false);
return true;
}
void BinEditor::setLazyData(int cursorPosition, int size, int blockSize)
void BinEditor::setLazyData(quint64 startAddr, int range, int blockSize)
{
m_inLazyMode = true;
m_blockSize = blockSize;
......@@ -338,8 +391,16 @@ void BinEditor::setLazyData(int cursorPosition, int size, int blockSize)
m_emptyBlock = QByteArray(blockSize, '\0');
m_data.clear();
m_lazyData.clear();
m_modifiedData.clear();
m_lazyRequests.clear();
m_size = size;
// In lazy mode, users can edit data in the range
// [startAddr - range/2, startAddr + range/2].
m_baseAddr = static_cast<quint64>(range/2) > startAddr
? 0 : startAddr - range/2;
m_baseAddr = (m_baseAddr / blockSize) * blockSize;
m_size = m_baseAddr != 0 && static_cast<quint64>(range) >= -m_baseAddr
? -m_baseAddr : range;
m_unmodifiedState = 0;
m_undoStack.clear();
......@@ -347,7 +408,7 @@ void BinEditor::setLazyData(int cursorPosition, int size, int blockSize)
init();
m_cursorPosition = cursorPosition;
m_cursorPosition = startAddr - m_baseAddr;
verticalScrollBar()->setValue(m_cursorPosition / 16);
emit cursorPositionChanged(m_cursorPosition);
......@@ -471,8 +532,9 @@ int BinEditor::dataIndexOf(const QByteArray &pattern, int from, bool caseSensiti
QByteArrayMatcher matcher(pattern);
int block = from / m_blockSize;
while (from < m_size) {
const int end =
qMin<qint64>(static_cast<qint64>(from) + SearchStride, m_size);
while (from < end) {
if (!requestDataAt(block * m_blockSize, true))
return -1;
QByteArray data = blockData(block);
......@@ -488,7 +550,7 @@ int BinEditor::dataIndexOf(const QByteArray &pattern, int from, bool caseSensiti
++block;
from = block * m_blockSize - trailing;
}
return -1;
return end == m_size ? -1 : -2;
}
int BinEditor::dataLastIndexOf(const QByteArray &pattern, int from, bool caseSensitive) const
......@@ -505,8 +567,8 @@ int BinEditor::dataLastIndexOf(const QByteArray &pattern, int from, bool caseSen
char *b = buffer.data();
int block = from / m_blockSize;
while (from > 0) {
const int lowerBound = qMax(0, from - SearchStride);
while (from > lowerBound) {
if (!requestDataAt(block * m_blockSize, true))
return -1;
QByteArray data = blockData(block);
......@@ -522,11 +584,12 @@ int BinEditor::dataLastIndexOf(const QByteArray &pattern, int from, bool caseSen
--block;
from = block * m_blockSize + (m_blockSize-1) + trailing;
}
return -1;
return lowerBound == 0 ? -1 : -2;
}
int BinEditor::find(const QByteArray &pattern_arg, int from, QTextDocument::FindFlags findFlags)
int BinEditor::find(const QByteArray &pattern_arg, int from,
QTextDocument::FindFlags findFlags)
{
if (pattern_arg.isEmpty())
return 0;
......@@ -541,7 +604,7 @@ int BinEditor::find(const QByteArray &pattern_arg, int from, QTextDocument::Find
bool backwards = (findFlags & QTextDocument::FindBackward);
int found = backwards ? dataLastIndexOf(pattern, from, caseSensitiveSearch)
: dataIndexOf(pattern, from, caseSensitiveSearch);
int foundHex = -1;
QByteArray hexPattern = calculateHexPattern(pattern_arg);
if (!hexPattern.isEmpty()) {
......@@ -549,7 +612,8 @@ int BinEditor::find(const QByteArray &pattern_arg, int from, QTextDocument::Find
: dataIndexOf(hexPattern, from);
}
int pos = (found >= 0 && (foundHex < 0 || found < foundHex)) ? found : foundHex;
int pos = foundHex == -1 || (found >= 0 && (foundHex == -2 || found < foundHex))
? found : foundHex;
if (pos >= m_size)
pos = -1;
......@@ -593,20 +657,21 @@ void BinEditor::drawItems(QPainter *painter, int x, int y, const QString &itemSt
}
}
QString BinEditor::addressString(uint address)
QString BinEditor::addressString(quint64 address)
{
QChar *addressStringData = m_addressString.data();
const char *hex = "0123456789abcdef";
for (int h = 0; h < 4; ++h) {
int shift = 4*(7-h);
addressStringData[h] = hex[(address & (0xf<<shift))>>shift];
}
for (int h = 4; h < 8; ++h) {
int shift = 4*(7-h);
addressStringData[h+1] = hex[(address & (0xf<<shift))>>shift];
// Take colons into account.
const int indices[16] = {
0, 1, 2, 3, 5, 6, 7, 8, 10, 11, 12, 13, 15, 16, 17, 18
};
for (int b = 0; b < 8; ++b) {
addressStringData[indices[15 - b*2]] = hex[(address >> (8*b)) & 0xf];
addressStringData[indices[14 - b*2]] = hex[(address >> (8*b + 4)) & 0xf];
}
return m_addressString;
}
void BinEditor::paintEvent(QPaintEvent *e)
......@@ -663,7 +728,8 @@ void BinEditor::paintEvent(QPaintEvent *e)
continue;
painter.drawText(-xoffset, i * m_lineHeight + m_ascent, addressString(((uint) line) * 16));
painter.drawText(-xoffset, i * m_lineHeight + m_ascent,
addressString(m_baseAddr + ((uint) line) * 16));
int cursor = -1;
if (line * 16 <= m_cursorPosition && m_cursorPosition < line * 16 + 16)
......
......@@ -31,8 +31,10 @@
#define BINEDITOR_H
#include <QtCore/QBasicTimer>
#include <QtCore/QMap>
#include <QtCore/QSet>
#include <QtCore/QStack>
#include <QtCore/QString>
#include <QtGui/QAbstractScrollArea>
#include <QtGui/QTextDocument>
......@@ -64,10 +66,10 @@ public:
inline int dataSize() const { return m_size; }
inline bool inLazyMode() const { return m_inLazyMode; }
Q_INVOKABLE void setLazyData(int cursorPosition, int size, int blockSize = 4096);
Q_INVOKABLE void setLazyData(quint64 startAddr, int range, int blockSize = 4096);
inline int lazyDataBlockSize() const { return m_blockSize; }
Q_INVOKABLE void addLazyData(int block, const QByteArray &data);
bool applyModifications(QByteArray &data) const;
Q_INVOKABLE void addLazyData(quint64 block, const QByteArray &data);
bool save(const QString &oldFileName, const QString &newFileName);
void zoomIn(int range = 1);
void zoomOut(int range = 1);
......@@ -86,7 +88,8 @@ public:
void setReadOnly(bool);
bool isReadOnly() const;
int find(const QByteArray &pattern, int from = 0, QTextDocument::FindFlags findFlags = 0);
int find(const QByteArray &pattern, int from = 0,
QTextDocument::FindFlags findFlags = 0);
void selectAll();
void clear();
......@@ -106,8 +109,9 @@ public:
bool isUndoAvailable() const { return m_undoStack.size(); }
bool isRedoAvailable() const { return m_redoStack.size(); }
QString addressString(uint address);
QString addressString(quint64 address);
static const int SearchStride = 1024 * 1024;
public Q_SLOTS:
void setFontSettings(const TextEditor::FontSettings &fs);
......@@ -121,7 +125,7 @@ Q_SIGNALS:
void copyAvailable(bool);
void cursorPositionChanged(int position);
void lazyDataRequested(int block, bool syncronous);
void lazyDataRequested(quint64 block, bool synchronous);
protected:
void scrollContentsBy(int dx, int dy);
......@@ -142,6 +146,7 @@ private:
QByteArray m_data;
QMap <int, QByteArray> m_lazyData;
int m_blockSize;
QMap <int, QByteArray> m_modifiedData;
mutable QSet<int> m_lazyRequests;
QByteArray m_emptyBlock;
QByteArray m_lowerBlock;
......@@ -169,6 +174,7 @@ private:
int m_numLines;
int m_numVisibleLines;
quint64 m_baseAddr;
bool m_cursorVisible;
int m_cursorPosition;
......
......@@ -61,7 +61,11 @@ class BinEditorFind : public Find::IFindSupport
{
Q_OBJECT
public:
BinEditorFind(BinEditor *editor) { m_editor = editor; m_incrementalStartPos = -1; }
BinEditorFind(BinEditor *editor)
{
m_editor = editor;
m_incrementalStartPos = m_contPos = -1;
}
~BinEditorFind() {}
bool supportsReplace() const { return false; }
......@@ -70,7 +74,11 @@ public:
return IFindSupport::FindBackward | IFindSupport::FindCaseSensitively;
}
void resetIncrementalSearch() { m_incrementalStartPos = -1; }
void resetIncrementalSearch()
{
m_incrementalStartPos = m_contPos = -1;
}
void clearResults() { m_editor->highlightSearchResults(QByteArray()); }
QString currentFindString() const { return QString(); }
QString completedFindString() const { return QString(); }
......@@ -82,41 +90,68 @@ public:
return pos;
}
int found = m_editor->find(pattern, pos, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags));
if (found < 0)
found = m_editor->find(pattern,
(findFlags & Find::IFindSupport::FindBackward)?m_editor->dataSize()-1:0,
Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags));
return found;
return m_editor->find(pattern, pos, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags));
}
bool findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags) {
Result findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags) {
QByteArray pattern = txt.toLatin1();
if (pattern != m_lastPattern)
resetIncrementalSearch(); // Because we don't search for nibbles.
m_lastPattern = pattern;
if (m_incrementalStartPos < 0)
m_incrementalStartPos = m_editor->selectionStart();
int pos = m_incrementalStartPos;
if (m_contPos == -1)
m_contPos = m_incrementalStartPos;
findFlags &= ~Find::IFindSupport::FindBackward;
int found = find(pattern, pos, findFlags);
if (found >= 0)
int found = find(pattern, m_contPos, findFlags);
Result result;
if (found >= 0) {
result = Found;
m_editor->highlightSearchResults(pattern, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags));
else
m_editor->highlightSearchResults(QByteArray(), 0);
return found >= 0;
m_contPos = -1;
} else {
if (found == -2) {
result = NotYetFound;
m_contPos +=
findFlags & Find::IFindSupport::FindBackward
? -BinEditor::SearchStride : BinEditor::SearchStride;
} else {
result = NotFound;
m_contPos = -1;
m_editor->highlightSearchResults(QByteArray(), 0);