diff --git a/src/libs/utils/consoleprocess_unix.cpp b/src/libs/utils/consoleprocess_unix.cpp index 610082377852150b6adad7a1bd7f3d6c3b103d07..2e20ac0c37aca3c6f36eb27a8ef25993e4e48129 100644 --- a/src/libs/utils/consoleprocess_unix.cpp +++ b/src/libs/utils/consoleprocess_unix.cpp @@ -73,7 +73,12 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args) } QStringList xtermArgs; - xtermArgs << "-e" << (QCoreApplication::applicationDirPath() + "/qtcreator_process_stub") + xtermArgs << "-e" +#ifdef Q_OS_MAC + << (QCoreApplication::applicationDirPath() + "/../Resources/qtcreator_process_stub") +#else + << (QCoreApplication::applicationDirPath() + "/qtcreator_process_stub") +#endif << (m_debug ? "debug" : "exec") << m_stubServer.fullServerName() << tr("Press <RETURN> to close this window...") diff --git a/src/libs/utils/process_stub.pro b/src/libs/utils/process_stub.pro index accf024ed0fc7371243fc46ce77e7ece290c29e6..a7f48846a4fdf4b3294c17409f45238621aafefd 100644 --- a/src/libs/utils/process_stub.pro +++ b/src/libs/utils/process_stub.pro @@ -1,6 +1,13 @@ +IDE_BUILD_TREE=../../../ +include(../../qworkbench.pri) + TEMPLATE = app TARGET = qtcreator_process_stub -DESTDIR = ../../../bin +macx { + DESTDIR = $$IDE_BUILD_TREE/bin/$${IDE_APP_TARGET}.app/Contents/Resources +} else { + DESTDIR = ../../../bin +} CONFIG += warn_on console use_c_linker CONFIG -= qt app_bundle diff --git a/src/libs/utils/process_stub_win.c b/src/libs/utils/process_stub_win.c index a4998b7e6cfbb619d3c5b83bb5a9b41f1f8dab4a..3d99a6853957de81341d000d2cf9912748d30405 100644 --- a/src/libs/utils/process_stub_win.c +++ b/src/libs/utils/process_stub_win.c @@ -174,7 +174,7 @@ int main() the Windows kernel runs amok when we attempt this. So instead we start a debugged process, eat all the initial debug events, suspend the process and detach from it. If gdb - tries to attach *now*, everthing goes smoothly. Yay. */ + tries to attach *now*, everything goes smoothly. Yay. */ if (creationFlags & DEBUG_ONLY_THIS_PROCESS) { do { if (!WaitForDebugEvent (&dbev, INFINITE)) diff --git a/src/plugins/designer/formeditorplugin.cpp b/src/plugins/designer/formeditorplugin.cpp index e132047df3850a91171252380e41dbeb324253b6..3052c1735855fcd76bc38302eab57c74d2b56546 100644 --- a/src/plugins/designer/formeditorplugin.cpp +++ b/src/plugins/designer/formeditorplugin.cpp @@ -38,9 +38,6 @@ #endif #include "designerconstants.h" -#if QT_VERSION < 0x040500 -# include "settings.h" -#endif #include <coreplugin/icore.h> #include <coreplugin/mimedatabase.h> diff --git a/src/plugins/designer/formeditorw.cpp b/src/plugins/designer/formeditorw.cpp index b3f6ffc70e6d92d55e89493f54e3c8eebc25264b..103d635168af40e56b00478d5b5a280733b8062c 100644 --- a/src/plugins/designer/formeditorw.cpp +++ b/src/plugins/designer/formeditorw.cpp @@ -173,7 +173,10 @@ FormEditorW::FormEditorW() : m_core(Core::ICore::instance()), m_initStage(RegisterPlugins), m_actionGroupEditMode(0), - m_actionPrint(0) + m_actionPrint(0), + m_actionPreview(0), + m_actionGroupPreviewInStyle(0), + m_actionAboutPlugins(0) { if (Designer::Constants::Internal::debug) qDebug() << Q_FUNC_INFO; @@ -250,10 +253,14 @@ void FormEditorW::fullInit() } } + if (m_actionAboutPlugins) + m_actionAboutPlugins->setEnabled(true); + if (Designer::Constants::Internal::debug) { qDebug() << Q_FUNC_INFO << initTime->elapsed() << "ms"; delete initTime; } + m_initStage = FullyInitialized; } @@ -439,6 +446,15 @@ void FormEditorW::setupActions() QAction *actionFormSettings = m_fwm->actionShowFormWindowSettingsDialog(); addToolAction(actionFormSettings, am, globalcontext, QLatin1String("FormEditor.FormSettings"), mformtools); +#if QT_VERSION > 0x040500 + createSeparator(this, am, globalcontext, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator4")); + m_actionAboutPlugins = new QAction(tr("About Qt Designer plugins...."), this); + addToolAction(m_actionAboutPlugins, am, globalcontext, + QLatin1String("FormEditor.AboutPlugins"), mformtools); + connect(m_actionAboutPlugins, SIGNAL(triggered()), m_fwm, SLOT(aboutPlugins())); + m_actionAboutPlugins->setEnabled(false); +#endif + // FWM connect(m_fwm, SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface *)), this, SLOT(activeFormWindowChanged(QDesignerFormWindowInterface *))); } diff --git a/src/plugins/designer/formeditorw.h b/src/plugins/designer/formeditorw.h index bdddf3ae373a671e0c594aa8c00323d662659fd7..d4a94794eef601e24d6e14b50a47f698193db3e2 100644 --- a/src/plugins/designer/formeditorw.h +++ b/src/plugins/designer/formeditorw.h @@ -157,6 +157,7 @@ private: QAction *m_actionPrint; QAction *m_actionPreview; QActionGroup *m_actionGroupPreviewInStyle; + QAction *m_actionAboutPlugins; QList<int> m_context; diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index a0f4016d33ff557cfdbc20038361a417b7dc2b65..33e81f2e86432f6345e22a7adbc7e4b110967890 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -1121,7 +1121,7 @@ void ProjectExplorerPlugin::setCurrent(Project *project, QString filePath, Node if (node) filePath = node->path(); else - node = m_session->nodeForFile(filePath); + node = m_session->nodeForFile(filePath, project); Core::ICore *core = Core::ICore::instance(); diff --git a/src/plugins/projectexplorer/projectwindow.cpp b/src/plugins/projectexplorer/projectwindow.cpp index 0f0850c17cb2f1dabde424335298ca7a0a8f9ffc..c3c769056fe7b8e9ce3979efd0fe5b05483162ce 100644 --- a/src/plugins/projectexplorer/projectwindow.cpp +++ b/src/plugins/projectexplorer/projectwindow.cpp @@ -65,10 +65,9 @@ ProjectWindow::ProjectWindow(QWidget *parent) : QWidget(parent) m_projectExplorer = ProjectExplorerPlugin::instance(); m_session = m_projectExplorer->session(); - connect(m_session, SIGNAL(sessionLoaded()), this, SLOT(restoreStatus())); - connect(m_session, SIGNAL(aboutToSaveSession()), this, SLOT(saveStatus())); - m_treeWidget = new QTreeWidget(this); + m_treeWidget->setSelectionMode(QAbstractItemView::SingleSelection); + m_treeWidget->setSelectionBehavior(QAbstractItemView::SelectRows); m_treeWidget->setFrameStyle(QFrame::NoFrame); m_treeWidget->setRootIsDecorated(false); m_treeWidget->header()->setResizeMode(QHeaderView::ResizeToContents); @@ -79,7 +78,7 @@ ProjectWindow::ProjectWindow(QWidget *parent) : QWidget(parent) ); connect(m_treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*, int)), - this, SLOT(handleItem(QTreeWidgetItem*, int)), Qt::QueuedConnection); + this, SLOT(handleItem(QTreeWidgetItem*, int))); connect(m_treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem *)), this, SLOT(handleCurrentItemChanged(QTreeWidgetItem*))); @@ -116,10 +115,14 @@ ProjectWindow::ProjectWindow(QWidget *parent) : QWidget(parent) topLayout->setSpacing(0); topLayout->addWidget(splitter); - connect(m_session, SIGNAL(sessionLoaded()), this, SLOT(updateTreeWidget())); - connect(m_session, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)), this, SLOT(updateTreeWidget())); - connect(m_session, SIGNAL(projectAdded(ProjectExplorer::Project*)), this, SLOT(updateTreeWidget())); - connect(m_session, SIGNAL(projectRemoved(ProjectExplorer::Project*)), this, SLOT(updateTreeWidget())); + connect(m_session, SIGNAL(sessionLoaded()), this, SLOT(restoreStatus())); + connect(m_session, SIGNAL(aboutToSaveSession()), this, SLOT(saveStatus())); + + connect(m_session, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)), this, SLOT(updateTreeWidgetStatupProjectChanged(ProjectExplorer::Project*))); + connect(m_session, SIGNAL(projectAdded(ProjectExplorer::Project*)), this, SLOT(updateTreeWidgetProjectAdded(ProjectExplorer::Project*))); + connect(m_session, SIGNAL(projectRemoved(ProjectExplorer::Project*)), this, SLOT(updateTreeWidgetProjectRemoved(ProjectExplorer::Project*))); + connect(m_session, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project*)), this, SLOT(updateTreeWidgetAboutToRemoveProject(ProjectExplorer::Project*))); + } ProjectWindow::~ProjectWindow() @@ -128,12 +131,21 @@ ProjectWindow::~ProjectWindow() void ProjectWindow::restoreStatus() { + m_panelsTabWidget->setFocus(); + + if (!m_treeWidget->currentItem() && m_treeWidget->topLevelItemCount()) { + m_treeWidget->setCurrentItem(m_treeWidget->topLevelItem(0), 0, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); + } + const QVariant lastPanel = m_session->value(QLatin1String("ProjectWindow/Panel")); if (lastPanel.isValid()) { const int index = lastPanel.toInt(); if (index < m_panelsTabWidget->count()) m_panelsTabWidget->setCurrentIndex(index); } + + if ((m_panelsTabWidget->currentIndex() == -1) && m_panelsTabWidget->count()) + m_panelsTabWidget->setCurrentIndex(0); } void ProjectWindow::saveStatus() @@ -172,52 +184,69 @@ void ProjectWindow::showProperties(ProjectExplorer::Project *project, const QMod } } -void ProjectWindow::updateTreeWidget() +void ProjectWindow::updateTreeWidgetStatupProjectChanged(ProjectExplorer::Project *startupProject) { - // This setFocus prevents a crash, which I (daniel) spend the better part of a day tracking down. - // To explain: Consider the case that a widget on either the build or run settings has Focus - // Us clearing the m_treewidget will emit a currentItemChanged(0) signal - // Which is connected to showProperties - // showProperties will now remove the widget that has focus from m_panelsTabWidget, so the treewidget - // gets focus, which will in focusIn select the first entry (due to QTreeWidget::clear() implementation, - // there are still items in the model) which emits another currentItemChanged() signal - // That one runs fully thorough and deletes all widgets, even that one that we are currently removing - // from m_panelsTabWidget. - // To prevent that, we simply prevent the focus switching.... - QWidget *focusWidget = qApp->focusWidget(); - while (focusWidget) { - if (focusWidget == this) { - m_treeWidget->setFocus(); - break; + int count = m_treeWidget->topLevelItemCount(); + for (int i = 0; i < count; ++i) { + QTreeWidgetItem *item = m_treeWidget->topLevelItem(i); + if (Project *project = findProject(item->text(2))) { + bool checked = (startupProject == project); + if (item->checkState(1) != (checked ? Qt::Checked : Qt::Unchecked)) + item->setCheckState(1, checked ? Qt::Checked : Qt::Unchecked); + } else { + item->setCheckState(1, Qt::Unchecked); } - focusWidget = focusWidget->parentWidget(); } - m_treeWidget->clear(); +} - foreach(Project *project, m_session->projects()) { - const QFileInfo fileInfo(project->file()->fileName()); +void ProjectWindow::updateTreeWidgetProjectAdded(ProjectExplorer::Project *projectAdded) +{ + int position = m_session->projects().indexOf(projectAdded); + const QFileInfo fileInfo(projectAdded->file()->fileName()); - QTreeWidgetItem *item = new QTreeWidgetItem(); - item->setText(0, fileInfo.baseName()); - item->setIcon(0, Core::FileIconProvider::instance()->icon(fileInfo)); - item->setText(2, fileInfo.filePath()); + QTreeWidgetItem *item = new QTreeWidgetItem(); + item->setText(0, fileInfo.baseName()); + item->setIcon(0, Core::FileIconProvider::instance()->icon(fileInfo)); + item->setText(2, fileInfo.filePath()); - if (project->isApplication()) { - bool checked = (m_session->startupProject() == project); - item->setCheckState(1, checked ? Qt::Checked : Qt::Unchecked); - } + if (projectAdded->isApplication()) { + bool checked = (m_session->startupProject() == projectAdded); + item->setCheckState(1, checked ? Qt::Checked : Qt::Unchecked); + } - m_treeWidget->addTopLevelItem(item); + m_treeWidget->insertTopLevelItem(position, item); +} +void ProjectWindow::updateTreeWidgetAboutToRemoveProject(ProjectExplorer::Project *projectRemoved) { + int count = m_treeWidget->topLevelItemCount(); + for (int i = 0; i < count; ++i) { + QTreeWidgetItem *item = m_treeWidget->topLevelItem(i); + if (item->text(2) == QFileInfo(projectRemoved->file()->fileName()).filePath()) { + if (m_treeWidget->currentItem() == item) { + m_treeWidget->setCurrentItem(0); + } + } } } +void ProjectWindow::updateTreeWidgetProjectRemoved(ProjectExplorer::Project *projectRemoved) +{ + int count = m_treeWidget->topLevelItemCount(); + for (int i = 0; i < count; ++i) { + QTreeWidgetItem *item = m_treeWidget->topLevelItem(i); + if (item->text(2) == QFileInfo(projectRemoved->file()->fileName()).filePath()) { + QTreeWidgetItem *it = m_treeWidget->takeTopLevelItem(i); + delete it; + break; + } + } +} Project *ProjectWindow::findProject(const QString &path) const { QList<Project*> projects = m_session->projects(); foreach (Project* project, projects) - if (project->file()->fileName() == path) + if (QFileInfo(project->file()->fileName()).filePath() == path) return project; return 0; } @@ -232,22 +261,26 @@ void ProjectWindow::handleCurrentItemChanged(QTreeWidgetItem *current) showProperties(project, QModelIndex()); return; } + } else { + showProperties(0, QModelIndex()); } } void ProjectWindow::handleItem(QTreeWidgetItem *item, int column) { + if (!item || column != 1) // startup project return; const QString path = item->text(2); Project *project = findProject(path); - if (project && project->isApplication()) { - if (!(item->checkState(1) == Qt::Checked)) { - item->setCheckState(1, Qt::Checked); // uncheck not supported - } else { + if (!(item->checkState(1) == Qt::Checked)) { // is now unchecked + if (m_session->startupProject() == project) { + item->setCheckState(1, Qt::Checked); // uncheck not supported + } + } else { // is now checked m_session->setStartupProject(project); } } diff --git a/src/plugins/projectexplorer/projectwindow.h b/src/plugins/projectexplorer/projectwindow.h index 199be12cc945e96386637003e541a503c1bc1dac..18d19f749c9f5295da5bc984eaa8722a879a8d8b 100644 --- a/src/plugins/projectexplorer/projectwindow.h +++ b/src/plugins/projectexplorer/projectwindow.h @@ -62,6 +62,12 @@ private slots: void saveStatus(); void updateTreeWidget(); + + void updateTreeWidgetStatupProjectChanged(ProjectExplorer::Project *startupProject); + void updateTreeWidgetProjectAdded(ProjectExplorer::Project *addedProject); + void updateTreeWidgetProjectRemoved(ProjectExplorer::Project *removedProject); + void updateTreeWidgetAboutToRemoveProject(ProjectExplorer::Project *removedProject); + void handleItem(QTreeWidgetItem *item, int column); void handleCurrentItemChanged(QTreeWidgetItem *); diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp index ce88d23c2618157f9ad2878a094f1f4e8b5a3787..cf0d79f8e01fee9f7f1425ce4b786bbe5a8de195 100644 --- a/src/plugins/projectexplorer/session.cpp +++ b/src/plugins/projectexplorer/session.cpp @@ -826,10 +826,12 @@ Project *SessionManager::projectForNode(Node *node) const return project; } -Node *SessionManager::nodeForFile(const QString &fileName) const +Node *SessionManager::nodeForFile(const QString &fileName, Project *project) const { Node *node = 0; - if (Project *project = projectForFile(fileName)) { + if (!project) + project = projectForFile(fileName); + if (project) { FindNodesForFileVisitor findNodes(fileName); project->rootProjectNode()->accept(&findNodes); diff --git a/src/plugins/projectexplorer/session.h b/src/plugins/projectexplorer/session.h index 15fd235977bdc249539cdbb3a27ff1acf64cec90..b2131595219b9f2d4064f04f702b339936d648cd 100644 --- a/src/plugins/projectexplorer/session.h +++ b/src/plugins/projectexplorer/session.h @@ -144,7 +144,7 @@ public: SessionNode *sessionNode() const; Project *projectForNode(ProjectExplorer::Node *node) const; - Node *nodeForFile(const QString &fileName) const; + Node *nodeForFile(const QString &fileName, Project *project = 0) const; Project *projectForFile(const QString &fileName) const; diff --git a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp index 483ea16ff35e3986f6d03f312c63c4a0b2ed1544..8d784f5f4905ea31fa1269b4b43a97a2f11b4708 100644 --- a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp @@ -299,7 +299,7 @@ void Qt4RunConfiguration::updateCachedValues() } #if defined (Q_OS_MAC) - if (!reader->values("-CONFIG").contains("app_bundle")) { + if (reader->values("CONFIG").contains("app_bundle")) { destDir += QLatin1Char('/') + "${QMAKE_TARGET}" + QLatin1String(".app/Contents/MacOS"); diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp index b1498cee99523ccdc8867420067a01b84e67ec5a..522438d7ce6aeb36570846c5a9b72d49b5b7a9f6 100644 --- a/src/shared/proparser/profileevaluator.cpp +++ b/src/shared/proparser/profileevaluator.cpp @@ -781,18 +781,9 @@ bool ProFileEvaluator::Private::visitProValue(ProValue *value) case ProVariable::RemoveOperator: // -= if (!m_cumulative) { if (!m_skipLevel) { - // the insertUnique is a hack for the moment to fix the - // CONFIG -= app_bundle problem on Mac (add it to a variable -CONFIG as was done before) - if (removeEach(&m_tempValuemap, varName, v) == 0) - insertUnique(&m_tempValuemap, QString("-%1").arg(varName), v); - if (removeEach(&m_tempFilevaluemap[currentProFile()], varName, v) == 0) - insertUnique(&m_tempFilevaluemap[currentProFile()], QString("-%1").arg(varName), v); + removeEach(&m_tempValuemap, varName, v); + removeEach(&m_tempFilevaluemap[currentProFile()], varName, v); } - } else if (!m_skipLevel) { - // the insertUnique is a hack for the moment to fix the - // CONFIG -= app_bundle problem on Mac (add it to a variable -CONFIG as was done before) - insertUnique(&m_tempValuemap, QString("-%1").arg(varName), v); - insertUnique(&m_tempFilevaluemap[currentProFile()], QString("-%1").arg(varName), v); } else { // We are stingy with our values, too. } @@ -987,11 +978,9 @@ QString ProFileEvaluator::Private::currentDirectory() const QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &str) { - bool fOK; - bool *ok = &fOK; QStringList ret; - if (ok) - *ok = true; +// if (ok) +// *ok = true; if (str.isEmpty()) return ret; @@ -1007,7 +996,10 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &s const ushort DOT = '.'; const ushort SPACE = ' '; const ushort TAB = '\t'; + const ushort SINGLEQUOTE = '\''; + const ushort DOUBLEQUOTE = '"'; + ushort unicode, quote = 0; const QChar *str_data = str.data(); const int str_len = str.length(); @@ -1017,126 +1009,105 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &s int replaced = 0; QString current; for (int i = 0; i < str_len; ++i) { - ushort c = str_data[i].unicode(); + unicode = str_data[i].unicode(); const int start_var = i; - if (c == BACKSLASH) { - bool escape = false; - const char *symbols = "[]{}()$\\"; - for (const char *s = symbols; *s; ++s) { - if (str_data[i+1] == (ushort)*s) { - i++; - escape = true; - if (!(replaced++)) - current = str.left(start_var); - current.append(str.at(i)); - break; - } - } - if (!escape && replaced) - current.append(QChar(c)); - continue; - } - if (c == SPACE || c == TAB) { - c = 0; - if (!current.isEmpty()) { - unquote(¤t); - ret.append(current); - current.clear(); - } - } else if (c == DOLLAR && str_len > i+2) { - c = str_data[++i].unicode(); - if (c == DOLLAR) { + if (unicode == DOLLAR && str_len > i+2) { + unicode = str_data[++i].unicode(); + if (unicode == DOLLAR) { term = 0; var.clear(); args.clear(); enum { VAR, ENVIRON, FUNCTION, PROPERTY } var_type = VAR; - c = str_data[++i].unicode(); - if (c == LSQUARE) { - c = str_data[++i].unicode(); + unicode = str_data[++i].unicode(); + if (unicode == LSQUARE) { + unicode = str_data[++i].unicode(); term = RSQUARE; var_type = PROPERTY; - } else if (c == LCURLY) { - c = str_data[++i].unicode(); + } else if (unicode == LCURLY) { + unicode = str_data[++i].unicode(); var_type = VAR; term = RCURLY; - } else if (c == LPAREN) { - c = str_data[++i].unicode(); + } else if (unicode == LPAREN) { + unicode = str_data[++i].unicode(); var_type = ENVIRON; term = RPAREN; } - while (1) { - if (!(c & (0xFF<<8)) && - c != DOT && c != UNDERSCORE && - (c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9')) + forever { + if (!(unicode & (0xFF<<8)) && + unicode != DOT && unicode != UNDERSCORE && + //unicode != SINGLEQUOTE && unicode != DOUBLEQUOTE && + (unicode < 'a' || unicode > 'z') && (unicode < 'A' || unicode > 'Z') && + (unicode < '0' || unicode > '9')) break; - var.append(QChar(c)); + var.append(QChar(unicode)); if (++i == str_len) break; - c = str_data[i].unicode(); + unicode = str_data[i].unicode(); + // at this point, i points to either the 'term' or 'next' character (which is in unicode) } - if (var_type == VAR && c == LPAREN) { + if (var_type == VAR && unicode == LPAREN) { var_type = FUNCTION; int depth = 0; - while (1) { + forever { if (++i == str_len) break; - c = str_data[i].unicode(); - if (c == LPAREN) { + unicode = str_data[i].unicode(); + if (unicode == LPAREN) { depth++; - } else if (c == RPAREN) { + } else if (unicode == RPAREN) { if (!depth) break; --depth; } - args.append(QChar(c)); + args.append(QChar(unicode)); } - if (i < str_len-1) - c = str_data[++i].unicode(); + if (++i < str_len) + unicode = str_data[i].unicode(); else - c = 0; + unicode = 0; + // at this point i is pointing to the 'next' character (which is in unicode) + // this might actually be a term character since you can do $${func()} } if (term) { - if (c != term) { + if (unicode != term) { q->logMessage(format("Missing %1 terminator [found %2]") - .arg(QChar(term)).arg(QChar(c))); - if (ok) - *ok = false; + .arg(QChar(term)) + .arg(unicode ? QString(unicode) : QString::fromLatin1(("end-of-line")))); +// if (ok) +// *ok = false; return QStringList(); } - c = 0; - } else if (i > str_len-1) { - c = 0; + } else { + // move the 'cursor' back to the last char of the thing we were looking at + --i; } + // since i never points to the 'next' character, there is no reason for this to be set + unicode = 0; QStringList replacement; if (var_type == ENVIRON) { - replacement << QString::fromLocal8Bit(qgetenv(var.toLocal8Bit().constData())); + replacement = split_value_list(QString::fromLocal8Bit(qgetenv(var.toLatin1().constData()))); } else if (var_type == PROPERTY) { replacement << propertyValue(var); - //if (prop) - // replacement = QStringList(prop->value(var)); } else if (var_type == FUNCTION) { replacement << evaluateExpandFunction(var, args); } else if (var_type == VAR) { - replacement += values(var); + replacement = values(var); } if (!(replaced++) && start_var) current = str.left(start_var); if (!replacement.isEmpty()) { - /* If a list is beteen two strings make sure it expands in such a way - * that the string to the left is prepended to the first string and - * the string to the right is appended to the last string, example: - * LIST = a b c - * V3 = x/$$LIST/f.cpp - * message($$member(V3,0)) # Outputs "x/a" - * message($$member(V3,1)) # Outputs "b" - * message($$member(V3,2)) # Outputs "c/f.cpp" - */ - current.append(replacement.at(0)); - for (int i = 1; i < replacement.count(); ++i) { - unquote(¤t); - ret.append(current); - current = replacement.at(i); + if (quote) { + current += replacement.join(QString(Option::field_sep)); + } else { + current += replacement.takeFirst(); + if (!replacement.isEmpty()) { + if (!current.isEmpty()) + ret.append(current); + current = replacement.takeLast(); + if (!replacement.isEmpty()) + ret += replacement; + } } } } else { @@ -1144,17 +1115,43 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &s current.append(QLatin1Char('$')); } } - if (replaced && c != 0) - current.append(QChar(c)); + if (quote && unicode == quote) { + unicode = 0; + quote = 0; + } else if (unicode == BACKSLASH) { + bool escape = false; + const char *symbols = "[]{}()$\\'\""; + for (const char *s = symbols; *s; ++s) { + if (str_data[i+1].unicode() == (ushort)*s) { + i++; + escape = true; + if (!(replaced++)) + current = str.left(start_var); + current.append(str.at(i)); + break; + } + } + if (escape || !replaced) + unicode =0; + } else if (!quote && (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE)) { + quote = unicode; + unicode = 0; + if (!(replaced++) && i) + current = str.left(i); + } else if (!quote && (unicode == SPACE || unicode == TAB)) { + unicode = 0; + if (!current.isEmpty()) { + ret.append(current); + current.clear(); + } + } + if (replaced && unicode) + current.append(QChar(unicode)); } - if (!replaced) { - current = str; - unquote(¤t); + if (!replaced) + ret = QStringList(str); + else if (!current.isEmpty()) ret.append(current); - } else if (!current.isEmpty()) { - unquote(¤t); - ret.append(current); - } return ret; } @@ -1456,11 +1453,8 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun ret += val; } break; -#if 0 // Disabled, as it is relatively useless, too slow and dangerous. case E_SYSTEM: - if (!m_skipLevel) { // FIXME: should exec only if the result is being used - // (i.e., if this is nested into an assignment) - these - // are less likely to have side effects + if (!m_skipLevel) { if (args.count() < 1 || args.count() > 2) { q->logMessage(format("system(execute) requires one or two arguments.")); } else { @@ -1485,7 +1479,6 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun } } break; -#endif case E_UNIQUE: if(args.count() != 1) { q->logMessage(format("unique(var) requires one argument.")); @@ -1860,7 +1853,7 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct dirstr = file.left(slsh+1); file = file.right(file.length() - slsh - 1); } - if (file.contains('*') || file.contains('?')) + if (file.contains(QLatin1Char('*')) || file.contains(QLatin1Char('?'))) cond = QDir(dirstr).entryList(QStringList(file)).count(); break; @@ -2317,17 +2310,10 @@ void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringL + visitor.values(QLatin1String("FORMS3")); sourceFiles << forms; -#if QT_VERSION >= 0x040500 sourceFiles.sort(); sourceFiles.removeDuplicates(); tsFileNames.sort(); tsFileNames.removeDuplicates(); -#else - sourceFiles = sourceFiles.toSet().toList(); - sourceFiles.sort(); - tsFileNames = tsFileNames.toSet().toList(); - tsFileNames.sort(); -#endif varMap->insert("SOURCES", sourceFiles); varMap->insert("CODECFORTR", QStringList() << codecForTr); diff --git a/src/shared/proparser/proparserutils.h b/src/shared/proparser/proparserutils.h index 5032d325f64bf655c08676131563c766aa73d0d3..05754860386505fe243f2c783157d47797c58628 100644 --- a/src/shared/proparser/proparserutils.h +++ b/src/shared/proparser/proparserutils.h @@ -116,17 +116,6 @@ QString Option::dirlist_sep; QString Option::dir_sep; QChar Option::field_sep; -static void unquote(QString *string) -{ - PRE(string); - if ( (string->startsWith(QLatin1Char('\"')) && string->endsWith(QLatin1Char('\"'))) - || (string->startsWith(QLatin1Char('\'')) && string->endsWith(QLatin1Char('\''))) ) - { - string->remove(0,1); - string->remove(string->length() - 1,1); - } -} - static void insertUnique(QHash<QString, QStringList> *map, const QString &key, const QStringList &value) { @@ -136,14 +125,12 @@ static void insertUnique(QHash<QString, QStringList> *map, sl.append(str); } -static int removeEach(QHash<QString, QStringList> *map, +static void removeEach(QHash<QString, QStringList> *map, const QString &key, const QStringList &value) { - int count = 0; QStringList &sl = (*map)[key]; foreach (const QString &str, value) - count += sl.removeAll(str); - return count; + sl.removeAll(str); } /* @@ -223,7 +210,8 @@ static QStringList split_arg_list(QString params) quote = 0; } else if (!quote && (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE)) { quote = unicode; - } else if (!parens && !quote && unicode == COMMA) { + } + if (!parens && !quote && unicode == COMMA) { QString mid = params.mid(last, x - last).trimmed(); args << mid; last = x+1; @@ -232,8 +220,6 @@ static QStringList split_arg_list(QString params) ++last; } } - for (int i = 0; i < args.count(); i++) - unquote(&args[i]); return args; } @@ -241,34 +227,35 @@ static QStringList split_value_list(const QString &vals, bool do_semicolon=false { QString build; QStringList ret; - QStack<QChar> quote; + QStack<char> quote; - const QChar LPAREN = QLatin1Char('('); - const QChar RPAREN = QLatin1Char(')'); - const QChar SINGLEQUOTE = QLatin1Char('\''); - const QChar DOUBLEQUOTE = QLatin1Char('"'); - const QChar BACKSLASH = QLatin1Char('\\'); - const QChar SEMICOLON = QLatin1Char(';'); + const ushort LPAREN = '('; + const ushort RPAREN = ')'; + const ushort SINGLEQUOTE = '\''; + const ushort DOUBLEQUOTE = '"'; + const ushort BACKSLASH = '\\'; + const ushort SEMICOLON = ';'; + ushort unicode; const QChar *vals_data = vals.data(); const int vals_len = vals.length(); for (int x = 0, parens = 0; x < vals_len; x++) { - QChar c = vals_data[x]; - if (x != vals_len-1 && c == BACKSLASH && - vals_data[x+1].unicode() == '\'' || vals_data[x+1] == DOUBLEQUOTE) { - build += vals_data[x++]; // get that 'escape' - } else if (!quote.isEmpty() && c == quote.top()) { + unicode = vals_data[x].unicode(); + if (x != (int)vals_len-1 && unicode == BACKSLASH && + (vals_data[x+1].unicode() == SINGLEQUOTE || vals_data[x+1].unicode() == DOUBLEQUOTE)) { + build += vals_data[x++]; //get that 'escape' + } else if (!quote.isEmpty() && unicode == quote.top()) { quote.pop(); - } else if (c == SINGLEQUOTE || c == DOUBLEQUOTE) { - quote.push(c); - } else if (c == RPAREN) { + } else if (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE) { + quote.push(unicode); + } else if (unicode == RPAREN) { --parens; - } else if (c == LPAREN) { + } else if (unicode == LPAREN) { ++parens; } - if (!parens && quote.isEmpty() && ((do_semicolon && c == SEMICOLON) || - vals_data[x] == Option::field_sep)) { + if (!parens && quote.isEmpty() && ((do_semicolon && unicode == SEMICOLON) || + vals_data[x] == Option::field_sep)) { ret << build; build.clear(); } else {